workflows/build.yml: - win32/64: install mingw32/64 gcc on msys (because the default gcc installed elsewhere seems to use ucrt, producing incompatible fp printf formats.) tccgen.c: - cleanup funcs: save any lvalues from return expressions. Also use get_temp_local_var() which however was causing a problem on i386 because its gfunc_call() removes the arguments from vstack and by that defeats the 'in-use' tracking of get_temp_local_var(). Fixed by: i386/arm/arm64/x86_64-gen.c: - in gfunc_call(): save_regs before anything else, fixes problems seen in arm64/i386 tccpp.c: - allow arm asm specific use of '#' in macros libtcc.c: - organize -M options, and: tccpe.c: - move the subsystem option parsing from libtcc.c tccelf.c: - improved error handling in tcc_load_ldscript() lib/atomic.S: - TCC_TARGET_... not defined when building the lib - endbrNN security feature not supported by TCC tests/tests2/136_atomic_gcc_style.c: - never use standard assert() in tests
Unified · Split
| @@ -29,29 +29,41 @@ jobs: · 28 unmodified lines | |||
| 29 | - name: make & test tcc (aarch64-osx) | 29 | - name: make & test tcc (aarch64-osx) |
| 30 | run: ./configure && make && make test -k | 30 | run: ./configure && make && make test -k |
| 31 | 31 | ||
| 32 | test-x86-win32: | 32 | test-x86_64-win32: |
| 33 | runs-on: windows-2022 | 33 | runs-on: windows-2025 |
| 34 | timeout-minutes: 6 | 34 | timeout-minutes: 4 |
| 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) |
| 38 | shell: cmd | 38 | shell: cmd |
| 39 | run: | | 39 | run: | |
| 40 | echo ::group:: setup msys mingw64-gcc | ||
| 40 | set MSYS2_PATH_TYPE=inherit | 41 | set MSYS2_PATH_TYPE=inherit |
| 41 | set MSYSTEM=MINGW64 | 42 | set MSYSTEM=MINGW64 |
| 42 | set CHERE_INVOKING=yes | 43 | set CHERE_INVOKING=yes |
| 44 | C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-gcc" | ||
| 45 | echo ::endgroup:: | ||
| 43 | 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 | |||
| 48 | test-i386-win32: | ||
| 49 | runs-on: windows-2025 | ||
| 50 | timeout-minutes: 4 | ||
| 51 | steps: | ||
| 52 | - uses: actions/checkout@v4 | ||
| 44 | - name: make & test tcc (i386-win32) | 53 | - name: make & test tcc (i386-win32) |
| 45 | shell: cmd | 54 | shell: cmd |
| 46 | run: | | 55 | run: | |
| 56 | echo ::group:: setup msys mingw32-gcc | ||
| 47 | set MSYS2_PATH_TYPE=inherit | 57 | set MSYS2_PATH_TYPE=inherit |
| 48 | set MSYSTEM=MINGW32 | 58 | set MSYSTEM=MINGW32 |
| 49 | set CHERE_INVOKING=yes | 59 | set CHERE_INVOKING=yes |
| 50 | C:\msys64\usr\bin\bash -l -c "./configure && make clean all && make test -k" | 60 | C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-i686-gcc" |
| 61 | echo ::endgroup:: | ||
| 62 | C:\msys64\usr\bin\bash -l -c "./configure && make all && make test -k" | ||
| 51 | 63 | ||
| 52 | test-armv7-linux: | 64 | test-armv7-linux: |
| 53 | runs-on: ubuntu-22.04 | 65 | runs-on: ubuntu-22.04 |
| 54 | timeout-minutes: 6 | 66 | timeout-minutes: 8 |
| 55 | steps: | 67 | steps: |
| 56 | - uses: actions/checkout@v4 | 68 | - uses: actions/checkout@v4 |
| 57 | - uses: uraimo/run-on-arch-action@v3 | 69 | - uses: uraimo/run-on-arch-action@v3 |
| @@ -69,14 +81,14 @@ jobs: · 11 unmodified lines | |||
| 69 | 81 | ||
| 70 | test-aarch64-linux: | 82 | test-aarch64-linux: |
| 71 | runs-on: ubuntu-22.04 | 83 | runs-on: ubuntu-22.04 |
| 72 | timeout-minutes: 6 | 84 | timeout-minutes: 8 |
| 73 | steps: | 85 | steps: |
| 74 | - uses: actions/checkout@v4 | 86 | - uses: actions/checkout@v4 |
| 75 | - uses: uraimo/run-on-arch-action@v3 | 87 | - uses: uraimo/run-on-arch-action@v3 |
| 76 | name: make & test tcc (aarch64-linux) | 88 | name: make & test tcc (aarch64-linux) |
| 77 | with: | 89 | with: |
| 78 | arch: aarch64 | 90 | arch: aarch64 |
| 79 | distro: ubuntu22.04 | 91 | distro: ubuntu24.04 |
| 80 | githubToken: ${{ github.token }} | 92 | githubToken: ${{ github.token }} |
| 81 | install: | | 93 | install: | |
| 82 | apt-get update -q -y | 94 | apt-get update -q -y |
| @@ -87,7 +99,7 @@ jobs: · 4 unmodified lines | |||
| 87 | 99 | ||
| 88 | test-riscv64-linux: | 100 | test-riscv64-linux: |
| 89 | runs-on: ubuntu-22.04 | 101 | runs-on: ubuntu-22.04 |
| 90 | timeout-minutes: 6 | 102 | timeout-minutes: 8 |
| 91 | steps: | 103 | steps: |
| 92 | - uses: actions/checkout@v4 | 104 | - uses: actions/checkout@v4 |
| 93 | - uses: uraimo/run-on-arch-action@v3 | 105 | - uses: uraimo/run-on-arch-action@v3 |
| @@ -252,8 +252,11 @@ LDFLAGS += -g · 251 unmodified lines | |||
| 252 | endif | 252 | endif |
| 253 | 253 | ||
| 254 | # convert "include/tccdefs.h" to "tccdefs_.h" | 254 | # convert "include/tccdefs.h" to "tccdefs_.h" |
| 255 | %_.h : include/%.h conftest.c | 255 | %_.h : include/%.h c2str.exe |
| 256 | $S$(CC) -DC2STR $(filter %.c,$^) -o c2str.exe && ./c2str.exe $< $@ | 256 | $S./c2str.exe $< $@ |
| 257 | |||
| 258 | c2str.exe : conftest.c | ||
| 259 | $S$(CC) -DC2STR $< -o $@ | ||
| 257 | 260 | ||
| 258 | # target specific object rule | 261 | # target specific object rule |
| 259 | $(X)%.o : %.c $(LIBTCC_INC) | 262 | $(X)%.o : %.c $(LIBTCC_INC) |
| @@ -1311,10 +1311,6 @@ again: · 1310 unmodified lines | |||
| 1311 | if (++pass < 2) | 1311 | if (++pass < 2) |
| 1312 | goto again; | 1312 | goto again; |
| 1313 | 1313 | ||
| 1314 | /* Manually free remaining registers since next parameters are loaded | ||
| 1315 | * manually, without the help of gv(int). */ | ||
| 1316 | save_regs(nb_args); | ||
| 1317 | |||
| 1318 | if(todo) { | 1314 | if(todo) { |
| 1319 | o(0xE8BD0000|todo); /* pop {todo} */ | 1315 | o(0xE8BD0000|todo); /* pop {todo} */ |
| 1320 | for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) { | 1316 | for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) { |
| @@ -1354,6 +1350,8 @@ void gfunc_call(int nb_args) · 33 unmodified lines | |||
| 1354 | gbound_args(nb_args); | 1350 | gbound_args(nb_args); |
| 1355 | #endif | 1351 | #endif |
| 1356 | 1352 | ||
| 1353 | save_regs(nb_args + 1); | ||
| 1354 | |||
| 1357 | #ifdef TCC_ARM_EABI | 1355 | #ifdef TCC_ARM_EABI |
| 1358 | if (float_abi == ARM_HARD_FLOAT) { | 1356 | if (float_abi == ARM_HARD_FLOAT) { |
| 1359 | variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS); | 1357 | variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS); |
| @@ -997,6 +997,8 @@ ST_FUNC void gfunc_call(int nb_args) · 996 unmodified lines | |||
| 997 | int variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS); | 997 | int variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS); |
| 998 | int var_nb_arg = n_func_args(&vtop[-nb_args].type); | 998 | int var_nb_arg = n_func_args(&vtop[-nb_args].type); |
| 999 | 999 | ||
| 1000 | save_regs(nb_args + 1); | ||
| 1001 | |||
| 1000 | #ifdef CONFIG_TCC_BCHECK | 1002 | #ifdef CONFIG_TCC_BCHECK |
| 1001 | if (tcc_state->do_bounds_check) | 1003 | if (tcc_state->do_bounds_check) |
| 1002 | gbound_args(nb_args); | 1004 | gbound_args(nb_args); |
| @@ -1101,9 +1103,6 @@ ST_FUNC void gfunc_call(int nb_args) · 98 unmodified lines | |||
| 1101 | // value in floating-point registers | 1103 | // value in floating-point registers |
| 1102 | if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { | 1104 | if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { |
| 1103 | uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz); | 1105 | uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz); |
| 1104 | // save regs because struct may overwrite previous func call result | ||
| 1105 | save_regs(0); | ||
| 1106 | |||
| 1107 | vtop->type.t = VT_PTR; | 1106 | vtop->type.t = VT_PTR; |
| 1108 | gaddrof(); | 1107 | gaddrof(); |
| 1109 | gv(RC_R30); | 1108 | gv(RC_R30); |
| @@ -1129,7 +1128,6 @@ ST_FUNC void gfunc_call(int nb_args) · 19 unmodified lines | |||
| 1129 | vswap(); | 1128 | vswap(); |
| 1130 | } | 1129 | } |
| 1131 | 1130 | ||
| 1132 | save_regs(0); | ||
| 1133 | arm64_gen_bl_or_b(0); | 1131 | arm64_gen_bl_or_b(0); |
| 1134 | --vtop; | 1132 | --vtop; |
| 1135 | if (stack & 0xfff) | 1133 | if (stack & 0xfff) |
| @@ -406,6 +406,8 @@ ST_FUNC void gfunc_call(int nb_args) · 405 unmodified lines | |||
| 406 | gbound_args(nb_args); | 406 | gbound_args(nb_args); |
| 407 | #endif | 407 | #endif |
| 408 | 408 | ||
| 409 | save_regs(nb_args + 1); | ||
| 410 | |||
| 409 | args_size = 0; | 411 | args_size = 0; |
| 410 | for(i = 0;i < nb_args; i++) { | 412 | for(i = 0;i < nb_args; i++) { |
| 411 | if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { | 413 | if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { |
| @@ -463,7 +465,7 @@ ST_FUNC void gfunc_call(int nb_args) · 51 unmodified lines | |||
| 463 | } | 465 | } |
| 464 | vtop--; | 466 | vtop--; |
| 465 | } | 467 | } |
| 466 | save_regs(0); /* save used temporary registers */ | 468 | |
| 467 | func_sym = vtop->type.ref; | 469 | func_sym = vtop->type.ref; |
| 468 | func_call = func_sym->f.func_call; | 470 | func_call = func_sym->f.func_call; |
| 469 | /* fast call case */ | 471 | /* fast call case */ |
| @@ -23,8 +23,10 @@ · 22 unmodified lines | |||
| 23 | 23 | ||
| 24 | /* ---------------------------------------------- */ | 24 | /* ---------------------------------------------- */ |
| 25 | #if defined __i386__ | 25 | #if defined __i386__ |
| 26 | |||
| 27 | #define endbr32 | ||
| 28 | |||
| 26 | .text | 29 | .text |
| 27 | .align 2 | ||
| 28 | 30 | ||
| 29 | .global _(__atomic_load_1) | 31 | .global _(__atomic_load_1) |
| 30 | .type _(__atomic_load_1), %function | 32 | .type _(__atomic_load_1), %function |
| @@ -297,9 +299,11 @@ _(atomic_flag_clear_explicit): · 266 unmodified lines | |||
| 297 | #endif //__i386__ | 299 | #endif //__i386__ |
| 298 | 300 | ||
| 299 | /* ---------------------------------------------- */ | 301 | /* ---------------------------------------------- */ |
| 300 | #if defined __x86_64__ && !defined TCC_TARGET_PE | 302 | #if defined __x86_64__ && !defined _WIN32 |
| 303 | |||
| 304 | #define endbr64 | ||
| 305 | |||
| 301 | .text | 306 | .text |
| 302 | .align 2 | ||
| 303 | 307 | ||
| 304 | .global _(__atomic_load_1) | 308 | .global _(__atomic_load_1) |
| 305 | .type _(__atomic_load_1), %function | 309 | .type _(__atomic_load_1), %function |
| @@ -508,12 +512,11 @@ _(atomic_flag_clear_explicit): · 202 unmodified lines | |||
| 508 | ret | 512 | ret |
| 509 | .size _(atomic_flag_clear_explicit), .-_(atomic_flag_clear_explicit) | 513 | .size _(atomic_flag_clear_explicit), .-_(atomic_flag_clear_explicit) |
| 510 | 514 | ||
| 511 | #endif //__x86_64__ && !TCC_TARGET_PE | 515 | #endif //__x86_64__ && !_WIN32 |
| 512 | 516 | ||
| 513 | /* ---------------------------------------------- */ | 517 | /* ---------------------------------------------- */ |
| 514 | #if defined __x86_64__ && defined TCC_TARGET_PE | 518 | #if defined __x86_64__ && defined _WIN32 |
| 515 | .text | 519 | .text |
| 516 | .align 2 | ||
| 517 | 520 | ||
| 518 | .global _(__atomic_load_1) | 521 | .global _(__atomic_load_1) |
| 519 | .type _(__atomic_load_1), %function | 522 | .type _(__atomic_load_1), %function |
| @@ -700,12 +703,11 @@ _(atomic_flag_clear_explicit): · 180 unmodified lines | |||
| 700 | ret | 703 | ret |
| 701 | .size _(atomic_flag_clear_explicit), .-_(atomic_flag_clear_explicit) | 704 | .size _(atomic_flag_clear_explicit), .-_(atomic_flag_clear_explicit) |
| 702 | 705 | ||
| 703 | #endif //__x86_64__ && TCC_TARGET_PE | 706 | #endif //__x86_64__ && _WIN32 |
| 704 | 707 | ||
| 705 | /* ---------------------------------------------- */ | 708 | /* ---------------------------------------------- */ |
| 706 | #if defined __arm__ | 709 | #if defined __arm__ |
| 707 | .text | 710 | .text |
| 708 | .align 2 | ||
| 709 | #ifndef __TINYC__ | 711 | #ifndef __TINYC__ |
| 710 | .arch armv6k | 712 | .arch armv6k |
| 711 | .syntax unified | 713 | .syntax unified |
| @@ -1496,7 +1498,6 @@ _(atomic_flag_clear_explicit): · 784 unmodified lines | |||
| 1496 | /* ---------------------------------------------- */ | 1498 | /* ---------------------------------------------- */ |
| 1497 | #if defined __aarch64__ | 1499 | #if defined __aarch64__ |
| 1498 | .text | 1500 | .text |
| 1499 | .align 2 | ||
| 1500 | 1501 | ||
| 1501 | .global _(__atomic_load_1) | 1502 | .global _(__atomic_load_1) |
| 1502 | .type _(__atomic_load_1), %function | 1503 | .type _(__atomic_load_1), %function |
| @@ -2115,7 +2116,6 @@ _(atomic_flag_clear_explicit): · 612 unmodified lines | |||
| 2115 | /* ---------------------------------------------- */ | 2116 | /* ---------------------------------------------- */ |
| 2116 | #if defined __riscv | 2117 | #if defined __riscv |
| 2117 | .text | 2118 | .text |
| 2118 | .align 2 | ||
| 2119 | 2119 | ||
| 2120 | .global _(__atomic_load_1) | 2120 | .global _(__atomic_load_1) |
| 2121 | .type _(__atomic_load_1), %function | 2121 | .type _(__atomic_load_1), %function |
| @@ -1465,31 +1465,9 @@ static int tcc_set_linker(TCCState *s, const char *optarg) · 1464 unmodified lines | |||
| 1465 | } else if (link_option(&o, "stack=")) { | 1465 | } else if (link_option(&o, "stack=")) { |
| 1466 | s->pe_stack_size = strtoul(o.arg, &end, 10); | 1466 | s->pe_stack_size = strtoul(o.arg, &end, 10); |
| 1467 | } else if (link_option(&o, "subsystem=")) { | 1467 | } else if (link_option(&o, "subsystem=")) { |
| 1468 | #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) | 1468 | if (pe_setsubsy(s, o.arg) < 0) |
| 1469 | if (0==strcmp("native", o.arg)) { | ||
| 1470 | s->pe_subsystem = 1; | ||
| 1471 | } else if (0==strcmp("console", o.arg)) { | ||
| 1472 | s->pe_subsystem = 3; | ||
| 1473 | } else if (0==strcmp("gui", o.arg) || 0==strcmp("windows", o.arg)) { | ||
| 1474 | s->pe_subsystem = 2; | ||
| 1475 | } else if (0==strcmp("posix", o.arg)) { | ||
| 1476 | s->pe_subsystem = 7; | ||
| 1477 | } else if (0==strcmp("efiapp", o.arg)) { | ||
| 1478 | s->pe_subsystem = 10; | ||
| 1479 | } else if (0==strcmp("efiboot", o.arg)) { | ||
| 1480 | s->pe_subsystem = 11; | ||
| 1481 | } else if (0==strcmp("efiruntime", o.arg)) { | ||
| 1482 | s->pe_subsystem = 12; | ||
| 1483 | } else if (0==strcmp("efirom", o.arg)) { | ||
| 1484 | s->pe_subsystem = 13; | ||
| 1485 | #elif defined(TCC_TARGET_ARM) | ||
| 1486 | if (0==strcmp("wince", o.arg)) { | ||
| 1487 | s->pe_subsystem = 9; | ||
| 1488 | #endif | ||
| 1489 | } else | ||
| 1490 | goto err; | 1469 | goto err; |
| 1491 | #endif /* PE */ | 1470 | #elif defined TCC_TARGET_MACHO |
| 1492 | #ifdef TCC_TARGET_MACHO | ||
| 1493 | } else if (link_option(&o, "all_load")) { | 1471 | } else if (link_option(&o, "all_load")) { |
| 1494 | s->filetype |= AFF_WHOLE_ARCHIVE; | 1472 | s->filetype |= AFF_WHOLE_ARCHIVE; |
| 1495 | } else if (link_option(&o, "force_load=")) { | 1473 | } else if (link_option(&o, "force_load=")) { |
| @@ -1653,11 +1631,10 @@ static const TCCOption tcc_options[] = { · 157 unmodified lines | |||
| 1653 | { "w", TCC_OPTION_w, 0 }, | 1631 | { "w", TCC_OPTION_w, 0 }, |
| 1654 | { "E", TCC_OPTION_E, 0}, | 1632 | { "E", TCC_OPTION_E, 0}, |
| 1655 | { "M", TCC_OPTION_M, 0}, | 1633 | { "M", TCC_OPTION_M, 0}, |
| 1656 | { "MD", TCC_OPTION_MD, 0}, | ||
| 1657 | { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG }, | ||
| 1658 | { "MM", TCC_OPTION_MM, 0}, | 1634 | { "MM", TCC_OPTION_MM, 0}, |
| 1659 | { "MMD,", TCC_OPTION_MMD, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, | 1635 | { "MD", TCC_OPTION_MD, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
| 1660 | { "MMD", TCC_OPTION_MMD, 0}, | 1636 | { "MMD", TCC_OPTION_MMD, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, |
| 1637 | { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG }, | ||
| 1661 | { "MP", TCC_OPTION_MP, 0}, | 1638 | { "MP", TCC_OPTION_MP, 0}, |
| 1662 | { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG }, | 1639 | { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG }, |
| 1663 | /* tcctools */ | 1640 | /* tcctools */ |
| @@ -2075,6 +2052,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv) · 411 unmodified lines | |||
| 2075 | case TCC_OPTION_P: | 2052 | case TCC_OPTION_P: |
| 2076 | s->Pflag = atoi(optarg) + 1; | 2053 | s->Pflag = atoi(optarg) + 1; |
| 2077 | break; | 2054 | break; |
| 2055 | |||
| 2078 | case TCC_OPTION_M: | 2056 | case TCC_OPTION_M: |
| 2079 | s->include_sys_deps = 1; | 2057 | s->include_sys_deps = 1; |
| 2080 | // fall through | 2058 | // fall through |
| @@ -2084,29 +2062,31 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv) · 3 unmodified lines | |||
| 2084 | if (!s->deps_outfile) | 2062 | if (!s->deps_outfile) |
| 2085 | tcc_set_str(&s->deps_outfile, "-"); | 2063 | tcc_set_str(&s->deps_outfile, "-"); |
| 2086 | break; | 2064 | break; |
| 2065 | case TCC_OPTION_MD: | ||
| 2066 | s->include_sys_deps = 1; | ||
| 2067 | // fall through | ||
| 2087 | case TCC_OPTION_MMD: | 2068 | case TCC_OPTION_MMD: |
| 2088 | s->gen_deps = 1; | 2069 | s->gen_deps = 1; |
| 2089 | /* usually, only "-MMD" is used */ | 2070 | /* usually, only "-MMD" is used */ |
| 2090 | /* but the Linux Kernel uses "-MMD,depfile" */ | 2071 | /* but the Linux Kernel uses "-MMD,depfile" */ |
| 2091 | if ((optarg) && (*optarg != '\0')) | 2072 | if (*optarg != ',') |
| 2092 | tcc_set_str(&s->deps_outfile, optarg); | 2073 | break; |
| 2093 | break; | 2074 | ++optarg; |
| 2094 | case TCC_OPTION_MD: | 2075 | // fall through |
| 2095 | s->gen_deps = 1; | ||
| 2096 | s->include_sys_deps = 1; | ||
| 2097 | break; | ||
| 2098 | case TCC_OPTION_MF: | 2076 | case TCC_OPTION_MF: |
| 2099 | tcc_set_str(&s->deps_outfile, optarg); | 2077 | tcc_set_str(&s->deps_outfile, optarg); |
| 2100 | break; | 2078 | break; |
| 2101 | case TCC_OPTION_MP: | 2079 | case TCC_OPTION_MP: |
| 2102 | s->gen_phony_deps = 1; | 2080 | s->gen_phony_deps = 1; |
| 2103 | break; | 2081 | break; |
| 2082 | |||
| 2104 | case TCC_OPTION_dumpmachine: | 2083 | case TCC_OPTION_dumpmachine: |
| 2105 | printf("%s\n", dumpmachine_str); | 2084 | printf("%s\n", dumpmachine_str); |
| 2106 | exit(0); | 2085 | exit(0); |
| 2107 | case TCC_OPTION_dumpversion: | 2086 | case TCC_OPTION_dumpversion: |
| 2108 | printf ("%s\n", TCC_VERSION); | 2087 | printf ("%s\n", TCC_VERSION); |
| 2109 | exit(0); | 2088 | exit(0); |
| 2089 | |||
| 2110 | case TCC_OPTION_x: | 2090 | case TCC_OPTION_x: |
| 2111 | x = 0; | 2091 | x = 0; |
| 2112 | if (*optarg == 'c') | 2092 | if (*optarg == 'c') |
| @@ -1790,6 +1790,7 @@ ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str); · 1789 unmodified lines | |||
| 1790 | ST_FUNC int pe_load_file(struct TCCState *s1, int fd, const char *filename); | 1790 | ST_FUNC int pe_load_file(struct TCCState *s1, int fd, const char *filename); |
| 1791 | ST_FUNC int pe_output_file(TCCState * s1, const char *filename); | 1791 | ST_FUNC int pe_output_file(TCCState * s1, const char *filename); |
| 1792 | ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value); | 1792 | ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value); |
| 1793 | ST_FUNC int pe_setsubsy(TCCState *s1, const char *arg); | ||
| 1793 | #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 | 1794 | #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 |
| 1794 | #endif | 1795 | #endif |
| 1795 | #ifdef TCC_TARGET_X86_64 | 1796 | #ifdef TCC_TARGET_X86_64 |
| @@ -3937,7 +3937,7 @@ static int ld_add_file(TCCState *s1, const char filename[]) · 3936 unmodified lines | |||
| 3937 | { | 3937 | { |
| 3938 | if (filename[0] == '-' && filename[1] == 'l') | 3938 | if (filename[0] == '-' && filename[1] == 'l') |
| 3939 | return tcc_add_library(s1, filename + 2); | 3939 | return tcc_add_library(s1, filename + 2); |
| 3940 | { | 3940 | if (CONFIG_SYSROOT[0] != '\0' || !IS_ABSPATH(filename)) { |
| 3941 | /* lookup via library paths */ | 3941 | /* lookup via library paths */ |
| 3942 | int ret = tcc_add_dll(s1, tcc_basename(filename), 0); | 3942 | int ret = tcc_add_dll(s1, tcc_basename(filename), 0); |
| 3943 | if (ret != FILE_NOT_FOUND) | 3943 | if (ret != FILE_NOT_FOUND) |
| @@ -3981,19 +3981,19 @@ repeat: · 37 unmodified lines | |||
| 3981 | } else if (t != LD_TOK_NAME) { | 3981 | } else if (t != LD_TOK_NAME) { |
| 3982 | return tcc_error_noabort("unexpected token '%c'", t); | 3982 | return tcc_error_noabort("unexpected token '%c'", t); |
| 3983 | } else if (!strcmp(filename, "AS_NEEDED")) { | 3983 | } else if (!strcmp(filename, "AS_NEEDED")) { |
| 3984 | ret = ld_add_file_list(s1, filename); | 3984 | ret |= ld_add_file_list(s1, filename); |
| 3985 | } else if (c == 'I' || c == 'G' || c == 'A') { | 3985 | } else if (c == 'I' || c == 'G' || c == 'A') { |
| 3986 | ret = ld_add_file(s1, filename); | 3986 | ret |= !!ld_add_file(s1, filename); |
| 3987 | } | 3987 | } |
| 3988 | if (ret) | 3988 | if (ret < 0) |
| 3989 | return -1; | 3989 | return ret; |
| 3990 | t = ld_next(s1, filename, sizeof(filename)); | 3990 | t = ld_next(s1, filename, sizeof(filename)); |
| 3991 | if (t == ',') | 3991 | if (t == ',') |
| 3992 | t = ld_next(s1, filename, sizeof(filename)); | 3992 | t = ld_next(s1, filename, sizeof(filename)); |
| 3993 | } | 3993 | } |
| 3994 | if (c == 'G' && new_undef_sym(s1, sym_offset)) | 3994 | if (c == 'G' && ret == 0 && new_undef_sym(s1, sym_offset)) |
| 3995 | goto repeat; | 3995 | goto repeat; |
| 3996 | return 0; | 3996 | return ret; |
| 3997 | } | 3997 | } |
| 3998 | 3998 | ||
| 3999 | /* interpret a subset of GNU ldscripts to handle the dummy libc.so | 3999 | /* interpret a subset of GNU ldscripts to handle the dummy libc.so |
| @@ -4001,7 +4001,7 @@ repeat: · 1 unmodified line | |||
| 4001 | ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd) | 4001 | ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd) |
| 4002 | { | 4002 | { |
| 4003 | char cmd[64]; | 4003 | char cmd[64]; |
| 4004 | int t, ret = FILE_NOT_RECOGNIZED; | 4004 | int t, ret = 0, noscript = 1; |
| 4005 | unsigned char *text_ptr, *saved_ptr; | 4005 | unsigned char *text_ptr, *saved_ptr; |
| 4006 | 4006 | ||
| 4007 | saved_ptr = s1->ld_p; | 4007 | saved_ptr = s1->ld_p; |
| @@ -4012,19 +4012,22 @@ ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd) · 4 unmodified lines | |||
| 4012 | break; | 4012 | break; |
| 4013 | if (!strcmp(cmd, "INPUT") || | 4013 | if (!strcmp(cmd, "INPUT") || |
| 4014 | !strcmp(cmd, "GROUP")) { | 4014 | !strcmp(cmd, "GROUP")) { |
| 4015 | ret = ld_add_file_list(s1, cmd); | 4015 | ret |= ld_add_file_list(s1, cmd); |
| 4016 | } else if (!strcmp(cmd, "OUTPUT_FORMAT") || | 4016 | } else if (!strcmp(cmd, "OUTPUT_FORMAT") || |
| 4017 | !strcmp(cmd, "TARGET")) { | 4017 | !strcmp(cmd, "TARGET")) { |
| 4018 | /* ignore some commands */ | 4018 | /* ignore some commands */ |
| 4019 | ret = ld_add_file_list(s1, cmd); | 4019 | ret |= ld_add_file_list(s1, cmd); |
| 4020 | } else if (0 == ret) { | 4020 | } else if (noscript) { |
| 4021 | ret = FILE_NOT_RECOGNIZED; | ||
| 4022 | } else { | ||
| 4021 | ret = tcc_error_noabort("unexpected '%s'", cmd); | 4023 | ret = tcc_error_noabort("unexpected '%s'", cmd); |
| 4022 | } | 4024 | } |
| 4023 | if (ret) | 4025 | if (ret < 0) |
| 4024 | break; | 4026 | break; |
| 4027 | noscript = 0; | ||
| 4025 | } | 4028 | } |
| 4026 | tcc_free(text_ptr); | 4029 | tcc_free(text_ptr); |
| 4027 | s1->ld_p = saved_ptr; | 4030 | s1->ld_p = saved_ptr; |
| 4028 | return ret; | 4031 | return ret < 0 ? ret : -ret; |
| 4029 | } | 4032 | } |
| 4030 | #endif /* !ELF_OBJ_ONLY */ | 4033 | #endif /* !ELF_OBJ_ONLY */ |
| @@ -6839,15 +6839,15 @@ static void end_switch(void) · 6838 unmodified lines | |||
| 6839 | /* ------------------------------------------------------------------------- */ | 6839 | /* ------------------------------------------------------------------------- */ |
| 6840 | /* __attribute__((cleanup(fn))) */ | 6840 | /* __attribute__((cleanup(fn))) */ |
| 6841 | 6841 | ||
| 6842 | /* save SValue of symbol to local stack */ | 6842 | /* protect symbol lvalues from further modification */ |
| 6843 | static void save_cleanup_sym(Sym *s) | 6843 | static void save_lvalues(void) |
| 6844 | { | 6844 | { |
| 6845 | SValue *sv = vtop; | 6845 | SValue *sv = vtop; |
| 6846 | while (sv >= vstack) { | 6846 | while (sv >= vstack) { |
| 6847 | if (sv->sym == s) { | 6847 | if (sv->sym && (sv->r & VT_LVAL)) { |
| 6848 | int align, size = type_size(&sv->type, &align); | 6848 | int align, size = type_size(&sv->type, &align); |
| 6849 | loc = (loc - size) & -align; | 6849 | int r2, l = get_temp_local_var(size, align, &r2); |
| 6850 | vset(&sv->type, VT_LOCAL | VT_LVAL, loc); | 6850 | vset(&sv->type, VT_LOCAL | VT_LVAL, l), vtop->r2 = r2; |
| 6851 | vpushv(sv), *sv = vtop[-1], vstore(), --vtop; | 6851 | vpushv(sv), *sv = vtop[-1], vstore(), --vtop; |
| 6852 | } | 6852 | } |
| 6853 | --sv; | 6853 | --sv; |
| @@ -6860,7 +6860,7 @@ static void try_call_scope_cleanup(Sym *stop) · 6 unmodified lines | |||
| 6860 | for (; cls != stop; cls = cls->next) { | 6860 | for (; cls != stop; cls = cls->next) { |
| 6861 | Sym *fs = cls->cleanup_func; | 6861 | Sym *fs = cls->cleanup_func; |
| 6862 | Sym *vs = cls->prev_tok; | 6862 | Sym *vs = cls->prev_tok; |
| 6863 | save_cleanup_sym(vs); | 6863 | save_lvalues(); |
| 6864 | vpushsym(&fs->type, fs); | 6864 | vpushsym(&fs->type, fs); |
| 6865 | vset(&vs->type, vs->r, vs->c); | 6865 | vset(&vs->type, vs->r, vs->c); |
| 6866 | vtop->sym = vs; | 6866 | vtop->sym = vs; |
| @@ -1254,7 +1254,7 @@ static int pe_check_symbols(struct pe_info *pe) · 1253 unmodified lines | |||
| 1254 | if (sym->st_shndx == SHN_UNDEF) { | 1254 | if (sym->st_shndx == SHN_UNDEF) { |
| 1255 | const char *name = (char*)symtab_section->link->data + sym->st_name; | 1255 | const char *name = (char*)symtab_section->link->data + sym->st_name; |
| 1256 | unsigned type = ELFW(ST_TYPE)(sym->st_info); | 1256 | unsigned type = ELFW(ST_TYPE)(sym->st_info); |
| 1257 | int imp_sym; | 1257 | int imp_sym = 0; |
| 1258 | struct import_symbol *is; | 1258 | struct import_symbol *is; |
| 1259 | 1259 | ||
| 1260 | int _imp_, n; | 1260 | int _imp_, n; |
| @@ -1928,6 +1928,34 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) · 667 unmodified lines | |||
| 1928 | pe->type = pe_type; | 1928 | pe->type = pe_type; |
| 1929 | } | 1929 | } |
| 1930 | 1930 | ||
| 1931 | ST_FUNC int pe_setsubsy(TCCState *s1, const char *arg) | ||
| 1932 | { | ||
| 1933 | static const struct subsy { const char* p; int v; } x[] = { | ||
| 1934 | #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) | ||
| 1935 | { "native", 1 }, | ||
| 1936 | { "gui", 2 }, | ||
| 1937 | { "windows", 2 }, | ||
| 1938 | { "console", 3 }, | ||
| 1939 | { "posix", 7 }, | ||
| 1940 | { "efiapp", 10 }, | ||
| 1941 | { "efiboot", 11 }, | ||
| 1942 | { "efiruntime", 12 }, | ||
| 1943 | { "efirom", 13 }, | ||
| 1944 | #elif defined(TCC_TARGET_ARM) | ||
| 1945 | { "wince", 9 }, | ||
| 1946 | #endif | ||
| 1947 | { 0, -1 }}; | ||
| 1948 | const struct subsy *y; | ||
| 1949 | for (y = x;; ++y) { | ||
| 1950 | if (!y->p) | ||
| 1951 | return -1; | ||
| 1952 | if (0 == strcmp(y->p, arg)) { | ||
| 1953 | s1->pe_subsystem = y->v; | ||
| 1954 | return 0; | ||
| 1955 | } | ||
| 1956 | } | ||
| 1957 | } | ||
| 1958 | |||
| 1931 | static void pe_set_options(TCCState * s1, struct pe_info *pe) | 1959 | static void pe_set_options(TCCState * s1, struct pe_info *pe) |
| 1932 | { | 1960 | { |
| 1933 | if (PE_DLL == pe->type) { | 1961 | if (PE_DLL == pe->type) { |
| @@ -3076,6 +3076,11 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) · 3075 unmodified lines | |||
| 3076 | cval.str.size = tokcstr.size; | 3076 | cval.str.size = tokcstr.size; |
| 3077 | cval.str.data = tokcstr.data; | 3077 | cval.str.data = tokcstr.data; |
| 3078 | tok_str_add2(&str, TOK_PPSTR, &cval); | 3078 | tok_str_add2(&str, TOK_PPSTR, &cval); |
| 3079 | #ifdef TCC_TARGET_ARM | ||
| 3080 | } else if ((parse_flags & PARSE_FLAG_ASM_FILE) && t == TOK_PPNUM) { | ||
| 3081 | /* for example: mov r1,#0 */ | ||
| 3082 | --macro_str, tok_str_add(&str, '#'); | ||
| 3083 | #endif | ||
| 3079 | } else { | 3084 | } else { |
| 3080 | expect("macro parameter after '#'"); | 3085 | expect("macro parameter after '#'"); |
| 3081 | } | 3086 | } |
| @@ -1,8 +1,11 @@ | |||
| 1 | #include <stdatomic.h> | 1 | #include <stdatomic.h> |
| 2 | #include <stdbool.h> | 2 | #include <stdbool.h> |
| 3 | #include <assert.h> | ||
| 4 | #include <stdio.h> | 3 | #include <stdio.h> |
| 5 | 4 | ||
| 5 | // standard assert would popup a dialog box on windows | ||
| 6 | #define assert(x) \ | ||
| 7 | printf("assert \"%s\" : %s\n", #x, (x) ? "yes" : "no"); | ||
| 8 | |||
| 6 | int main() { | 9 | int main() { |
| 7 | // Test 1: Basic functionality of __atomic_store_n and __atomic_load_n | 10 | // Test 1: Basic functionality of __atomic_store_n and __atomic_load_n |
| 8 | { | 11 | { |
| @@ -1 +1,11 @@ | |||
| 1 | assert "loaded == 42" : yes | ||
| 2 | assert "success" : yes | ||
| 3 | assert "atomic_var == 200" : yes | ||
| 4 | assert "expected == 100" : yes | ||
| 5 | assert "!success" : yes | ||
| 6 | assert "atomic_var == 100" : yes | ||
| 7 | assert "expected == 100" : yes | ||
| 8 | assert "atomic_var == 60" : yes | ||
| 9 | assert "loaded_ptr == NULL" : yes | ||
| 10 | assert "__atomic_load_n(&atomic_var, __ATOMIC_RELAXED) == 10" : yes | ||
| 1 | All atomic tests passed! | 11 | All atomic tests passed! |
| @@ -809,6 +809,8 @@ void gfunc_call(int nb_args) · 808 unmodified lines | |||
| 809 | gbound_args(nb_args); | 809 | gbound_args(nb_args); |
| 810 | #endif | 810 | #endif |
| 811 | 811 | ||
| 812 | save_regs(nb_args); | ||
| 813 | |||
| 812 | args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE; | 814 | args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE; |
| 813 | arg = nb_args; | 815 | arg = nb_args; |
| 814 | 816 | ||
| @@ -906,7 +908,7 @@ void gfunc_call(int nb_args) · 91 unmodified lines | |||
| 906 | } | 908 | } |
| 907 | vtop--; | 909 | vtop--; |
| 908 | } | 910 | } |
| 909 | save_regs(0); | 911 | |
| 910 | /* Copy R10 and R11 into RCX and RDX, respectively */ | 912 | /* Copy R10 and R11 into RCX and RDX, respectively */ |
| 911 | if (nb_args > 0) { | 913 | if (nb_args > 0) { |
| 912 | o(0xd1894c); /* mov %r10, %rcx */ | 914 | o(0xd1894c); /* mov %r10, %rcx */ |
| @@ -1249,6 +1251,8 @@ void gfunc_call(int nb_args) · 336 unmodified lines | |||
| 1249 | gbound_args(nb_args); | 1251 | gbound_args(nb_args); |
| 1250 | #endif | 1252 | #endif |
| 1251 | 1253 | ||
| 1254 | save_regs(nb_args); | ||
| 1255 | |||
| 1252 | /* calculate the number of integer/float register arguments, remember | 1256 | /* calculate the number of integer/float register arguments, remember |
| 1253 | arguments to be passed via stack (in onstack[]), and also remember | 1257 | arguments to be passed via stack (in onstack[]), and also remember |
| 1254 | if we have to align the stack pointer to 16 (onstack[i] == 2). Needs | 1258 | if we have to align the stack pointer to 16 (onstack[i] == 2). Needs |
| @@ -1364,9 +1368,6 @@ void gfunc_call(int nb_args) · 109 unmodified lines | |||
| 1364 | 1368 | ||
| 1365 | tcc_free(onstack); | 1369 | tcc_free(onstack); |
| 1366 | 1370 | ||
| 1367 | /* XXX This should be superfluous. */ | ||
| 1368 | save_regs(0); /* save used temporary registers */ | ||
| 1369 | |||
| 1370 | /* then, we prepare register passing arguments. | 1371 | /* then, we prepare register passing arguments. |
| 1371 | Note that we cannot set RDX and RCX in this loop because gv() | 1372 | Note that we cannot set RDX and RCX in this loop because gv() |
| 1372 | may break these temporary registers. Let's use R10 and R11 | 1373 | may break these temporary registers. Let's use R10 and R11 |
| @@ -1416,12 +1417,6 @@ void gfunc_call(int nb_args) · 43 unmodified lines | |||
| 1416 | assert(gen_reg == 0); | 1417 | assert(gen_reg == 0); |
| 1417 | assert(sse_reg == 0); | 1418 | assert(sse_reg == 0); |
| 1418 | 1419 | ||
| 1419 | /* We shouldn't have many operands on the stack anymore, but the | ||
| 1420 | call address itself is still there, and it might be in %eax | ||
| 1421 | (or edx/ecx) currently, which the below writes would clobber. | ||
| 1422 | So evict all remaining operands here. */ | ||
| 1423 | save_regs(0); | ||
| 1424 | |||
| 1425 | /* Copy R10 and R11 into RDX and RCX, respectively */ | 1420 | /* Copy R10 and R11 into RDX and RCX, respectively */ |
| 1426 | if (nb_reg_args > 2) { | 1421 | if (nb_reg_args > 2) { |
| 1427 | o(0xd2894c); /* mov %r10, %rdx */ | 1422 | o(0xd2894c); /* mov %r10, %rdx */ |