History

arm64-win32 review: fix problems and pass tests

tccpe.c: - fix arm64 unwind codes (to make native set/longjmp() work) sizeof(RUNTIME_FUNCTION) is 8 on arm64 in the first place no need to note stack slots if we don't save any registers anyway arm64-gen.c: - fix long double reg-move - fix arm64_hfa() for structs with float arrays - gfunc_prolog(): setup stackframe eariler (simplifies unwind codes) - new function gv_addr(RC); win32/include/setjmp.h: - provide correct definition for setjmo() (frameoffset = 224) tccasm.c: - support ".quad" with symbol & relocation - support ".size" - fix ". - symbol" arithmetic win32/lib/crt1.c and win32/include/stdlib.h: - do not write to __argc/__argv which reside in msvcrt.dll (msvcrt.dll on arm64 does not like that, crashes on unload) tcc.c,libtcc.c: - new functions tcc_fopen/fclose to avoid different stdio unstances in tcc.exe & libtcc.dll tests & github workflow: - add test-win32.bat to run tests with a tcc compiled by build-tcc.bat - add msvcrt_start.c for gcc/clang to use the same runtime as tcc the problem is that newer gcc as well as clang and cl are linking to newer runtimes (such as UCRT) that have partially different printf format behavior which makes tcctest fail. the solution here is to force these compilers to link with msvcrt.dll just like tcc. Also, there is no gcc on arm64-win32 currently at all. Anyway, this approach to running the github CI tests does not require msys2. But It does rely on gnumake as well as on some 'sh' shell though which seems to be installed somewhere (maybe it is the one from git).

grischka committed 6 months ago

Commit 30afb501 parent 576cd2a33 files · +601 −455Browse files

Unified · Split

33 files
  1. .github/workflows/build.yml +26 −31
  2. Makefile +3 −1
  3. arm64-asm.c +0 −4
  4. arm64-gen.c +23 −25
  5. i386-asm.c +0 −7
  6. lib/Makefile +2 −2
  7. lib/armflush.c +13 −0
  8. lib/bt-dll.c +24 −3
  9. lib/lib-arm64.c +0 −7
  10. lib/libtcc1.c +2 −20
  11. libtcc.c +8 −1
  12. tcc.c +6 −6
  13. tcc.h +15 −6
  14. tccasm.c +30 −11
  15. tcclib.h +2 −0
  16. tccpe.c +24 −45
  17. tccrun.c +2 −0
  18. tcctok.h +4 −3
  19. tests/Makefile +5 −4
  20. tests/libtcc_test_mt.c +8 −12
  21. tests/msvcrt_start.c +164 −0
  22. tests/tcctest.c +18 −19
  23. tests/test-win32.bat +74 −0
  24. tests/tests2/Makefile +7 −16
  25. win32/build-tcc.bat +66 −73
  26. win32/include/_mingw.h +1 −7
  27. win32/include/setjmp.h +11 −21
  28. win32/include/stdlib.h +15 −0
  29. win32/include/winapi/winnt.h +13 −48
  30. win32/lib/chkstk.S +2 −72
  31. win32/lib/crt1.c +6 −3
  32. win32/lib/winex.c +27 −0
  33. x86_64-gen.c +0 −8
.github/workflows/build.yml+26−31
@@ -34,56 +34,51 @@ jobs: · 33 unmodified lines
3434 timeout-minutes: 6
3535 steps:
3636 - uses: actions/checkout@v4
37− - name: make & test tcc (x86_64-win32)
38− shell: cmd
39− run: |
40− echo ::group:: setup msys mingw64-gcc
41− set MSYS2_PATH_TYPE=inherit
42− set MSYSTEM=MINGW64
43− set CHERE_INVOKING=yes
44− C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-gcc"
45− echo ::endgroup::
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)
37+ - name: test (x86_64-win32)
5138 shell: cmd
5239 run: |
5340 echo ::group:: run build-tcc.bat
5441 cd win32
55− call build-tcc.bat -t 64 -c cl
42+ call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=amd64
43+ call build-tcc.bat -c cl -t x86_64
44+ @echo off
5645 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
46+ cd ..\tests
47+ call test-win32.bat all -k
5948
6049 test-i386-win32:
6150 runs-on: windows-2025
6251 timeout-minutes: 6
6352 steps:
6453 - uses: actions/checkout@v4
65− - name: make & test tcc (i386-win32)
54+ - name: test (i386-win32)
6655 shell: cmd
6756 run: |
68− echo ::group:: setup msys mingw32-gcc
69− set MSYS2_PATH_TYPE=inherit
70− set MSYSTEM=MINGW32
71− set CHERE_INVOKING=yes
72− C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-i686-gcc"
57+ echo ::group:: run build-tcc.bat
58+ cd win32
59+ call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=x86
60+ call build-tcc.bat -c cl -t i386
61+ @echo off
7362 echo ::endgroup::
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)
63+ cd ..\tests
64+ call test-win32.bat -p c:\mingw32\bin all -k
65+
66+ test-arm64-win32:
67+ runs-on: windows-11-arm
68+ timeout-minutes: 6
69+ steps:
70+ - uses: actions/checkout@v4
71+ - name: test (arm64-win32)
7972 shell: cmd
8073 run: |
8174 echo ::group:: run build-tcc.bat
8275 cd win32
83− call build-tcc.bat -t 32 -c cl
76+ call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=arm64
77+ call build-tcc.bat -c cl -t arm64
78+ @echo off
8479 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
80+ cd ..\tests
81+ call test-win32.bat -c clang all -k
8782
8883 test-armv7-linux:
8984 runs-on: ubuntu-22.04
Makefile+3−1
@@ -31,7 +31,9 @@ ifdef CONFIG_WIN32 · 30 unmodified lines
3131 LIBTCCDEF = libtcc.def
3232 endif
3333 ifneq ($(CONFIG_debug),yes)
34− LDFLAGS += -s
34+ ifneq ($(CC_NAME),clang)
35+ LDFLAGS += -s
36+ endif
3537 endif
3638 NATIVE_TARGET = $(if $(findstring arm64,$(ARCH)),arm64-win32,$(ARCH)-win$(if $(findstring arm,$(ARCH)),ce,32))
3739 else
arm64-asm.c+0−4
@@ -86,11 +86,7 @@ enum { · 85 unmodified lines
8686 #define TREG_X30 30
8787 #define TREG_SP 31
8888
89−#ifdef TCC_TARGET_PE
90−#define ARM64_FREG_BASE 19
91−#else
9289 #define ARM64_FREG_BASE 20
93−#endif
9490 #define ARM64_FREG_LAST (ARM64_FREG_BASE + 7)
9591
9692 typedef struct Operand {
arm64-gen.c+23−25
@@ -579,7 +579,7 @@ ST_FUNC void load(int r, SValue *sv) · 578 unmodified lines
579579 if (svr < VT_CONST) {
580580 if (IS_FREG(r) && IS_FREG(svr))
581581 if (svtt == VT_LDOUBLE)
582− o(ARM64_MOV_V16B | fltr(r) | fltr(svr) << 5);
582+ o(ARM64_MOV_V16B | fltr(r) | fltr(svr) * 0x10020);
583583 // mov v(r).16b,v(svr).16b
584584 else
585585 o(ARM64_FMOV_SCALAR | fltr(r) | fltr(svr) << 5); // fmov d(r),d(svr)
@@ -794,7 +794,7 @@ static int arm64_hfa_aux(CType *type, int *fsize, int num) · 208 unmodified lines
794794 return num;
795795 }
796796 }
797− else if ((type->t & VT_ARRAY) && ((type->t & VT_BTYPE) != VT_PTR)) {
797+ else if (type->t & VT_ARRAY) { /* handle float array within struct */
798798 int num1;
799799 if (!type->ref->c)
800800 return num;
@@ -811,8 +811,7 @@ static int arm64_hfa_aux(CType *type, int *fsize, int num) · 10 unmodified lines
811811
812812 static int arm64_hfa(CType *type, unsigned *fsize)
813813 {
814− if ((type->t & VT_BTYPE) == VT_STRUCT ||
815− ((type->t & VT_ARRAY) && ((type->t & VT_BTYPE) != VT_PTR))) {
814+ if ((type->t & VT_BTYPE) == VT_STRUCT) {
816815 int sz = 0;
817816 int n = arm64_hfa_aux(type, &sz, 0);
818817 if (0 < n && n <= 4) {
@@ -1037,6 +1036,13 @@ static void arm64_sub_sp(uint64_t diff) · 218 unmodified lines
10371036 }
10381037 }
10391038
1039+static int gv_addr(int r)
1040+{
1041+ gaddrof();
1042+ vtop->type.t = VT_PTR;
1043+ return gv(r);
1044+}
1045+
10401046 ST_FUNC void gfunc_call(int nb_args)
10411047 {
10421048 CType *return_type;
@@ -1147,9 +1153,7 @@ ST_FUNC void gfunc_call(int nb_args) · 104 unmodified lines
11471153 else if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
11481154 int align, size = type_size(&vtop->type, &align);
11491155 if (size) {
1150− vtop->type.t = VT_PTR;
1151− gaddrof();
1152− gv(RC_R(a[i] / 2));
1156+ gv_addr(RC_R(a[i] / 2));
11531157 arm64_ldrs(a[i] / 2, size);
11541158 }
11551159 }
@@ -1165,9 +1169,7 @@ ST_FUNC void gfunc_call(int nb_args) · 9 unmodified lines
11651169 uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz);
11661170 if (n > 0) {
11671171 /* HFA struct - load from memory into float registers */
1168− vtop->type.t = VT_PTR;
1169− gaddrof();
1170− gv(RC_R30);
1172+ gv_addr(RC_R30);
11711173 for (j = 0; j < n; j++)
11721174 o(0x3d4003c0 |
11731175 (sz & 16) << 19 | -(sz & 8) << 27 | (sz & 4) << 29 |
@@ -1186,7 +1188,7 @@ ST_FUNC void gfunc_call(int nb_args) · 12 unmodified lines
11861188 if ((return_type->t & VT_BTYPE) == VT_STRUCT) {
11871189 if (a[0] == 1) {
11881190 // indirect return: set x8 and discard the stack value
1189− gv(RC_R(8));
1191+ gv_addr(RC_R(8));
11901192 --vtop;
11911193 }
11921194 else
@@ -1206,7 +1208,7 @@ ST_FUNC void gfunc_call(int nb_args) · 13 unmodified lines
12061208 int bt = rt & VT_BTYPE;
12071209 if (bt == VT_STRUCT && !(a[0] & 1)) {
12081210 // A struct was returned in registers, so write it out:
1209− gv(RC_R(8));
1211+ gv_addr(RC_R(8));
12101212 --vtop;
12111213 if (a[0] == 0) {
12121214 int align, size = type_size(return_type, &align);
@@ -1271,6 +1273,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 58 unmodified lines
12711273
12721274 for (sym = func_type->ref; sym; sym = sym->next)
12731275 ++n;
1276+
12741277 pcs_n = n - 1;
12751278 c = n + variadic;
12761279 t = tcc_malloc(c * sizeof(*t));
@@ -1321,6 +1324,8 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 44 unmodified lines
13211324
13221325 arm64_func_start_offset = ind;
13231326 o(0xa9b27bfd); // stp x29,x30,[sp,#-224]!
1327+ o(0x910003fd); // mov x29,sp
1328+
13241329 for (i = 0; i < last_float; i++)
13251330 // stp q0,q1,[sp,#16], stp q2,q3,[sp,#48]
13261331 // stp q4,q5,[sp,#80], stp q6,q7,[sp,#112]
@@ -1368,7 +1373,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 41 unmodified lines
13681373 tcc_free(a);
13691374 tcc_free(t);
13701375
1371− o(0x910003fd); // mov x29,sp
13721376 arm64_func_sub_sp_offset = ind;
13731377 /* In gfunc_epilog these will be replaced with stack setup code. */
13741378 for (i = 0; i < ARM64_FUNC_STACK_SETUP_SLOTS; ++i)
@@ -1384,8 +1388,7 @@ ST_FUNC void gen_va_start(void) · 9 unmodified lines
13841388 {
13851389 int r;
13861390 --vtop; // we don't need the "arg"
1387− gaddrof();
1388− r = intr(gv(RC_INT));
1391+ r = intr(gv_addr(RC_INT));
13891392
13901393 #ifdef TCC_TARGET_PE
13911394 if (arm64_func_va_list_stack) {
@@ -1433,13 +1436,12 @@ ST_FUNC void gen_va_arg(CType *t) · 41 unmodified lines
14331436 uint32_t r0, r1;
14341437
14351438 #ifdef TCC_TARGET_PE
1436− int indirect = 0, slot = size + 7 & -8;
1439+ int indirect = 0, slot = (size + 7) & -8;
14371440
14381441 if (size > 16)
14391442 indirect = 1, slot = 8;
14401443
1441− gaddrof();
1442− r0 = intr(gv(RC_INT));
1444+ r0 = intr(gv_addr(RC_INT));
14431445 r1 = get_reg(RC_INT);
14441446 vtop[0].r = r1 | VT_LVAL;
14451447 r1 = intr(r1);
@@ -1459,7 +1461,6 @@ ST_FUNC void gen_va_arg(CType *t) · 13 unmodified lines
14591461 o(0x9100001e | r1 << 5 | slot << 10); // add x30,x(r1),#(slot)
14601462 o(0xf900001e | r0 << 5); // str x30,[x(r0)] // ap += slot
14611463 }
1462−
14631464 if (indirect)
14641465 o(ARM64_LDR_X | ARM64_RN(r1) | r1); // ldr x(r1),[x(r1)]
14651466
@@ -1469,8 +1470,7 @@ ST_FUNC void gen_va_arg(CType *t) · 3 unmodified lines
14691470 if (!is_float(t->t))
14701471 hfa = arm64_hfa(t, &fsize);
14711472
1472− gaddrof();
1473− r0 = intr(gv(RC_INT));
1473+ r0 = intr(gv_addr(RC_INT));
14741474 r1 = get_reg(RC_INT);
14751475 vtop[0].r = r1 | VT_LVAL;
14761476 r1 = intr(r1);
@@ -1570,8 +1570,7 @@ ST_FUNC void gfunc_return(CType *func_type) · 93 unmodified lines
15701570 case 0:
15711571 if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
15721572 int align, size = type_size(func_type, &align);
1573− gaddrof();
1574− gv(RC_R(0));
1573+ gv_addr(RC_R(0));
15751574 arm64_ldrs(0, size);
15761575 }
15771576 else
@@ -1590,8 +1589,7 @@ ST_FUNC void gfunc_return(CType *func_type) · 12 unmodified lines
15901589 if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
15911590 /* HFA struct return - load from the address on vtop into float registers */
15921591 uint32_t j, sz, n = arm64_hfa(func_type, &sz);
1593− gaddrof();
1594− gv(RC_R(0));
1592+ gv_addr(RC_R(0));
15951593 for (j = 0; j < n; j++)
15961594 o(0x3d400000 |
15971595 (sz & 16) << 19 | -(sz & 8) << 27 | (sz & 4) << 29 |
i386-asm.c+0−7
@@ -494,13 +494,6 @@ ST_FUNC void gen_expr32(ExprValue *pe) · 493 unmodified lines
494494 gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
495495 }
496496
497−#ifdef TCC_TARGET_X86_64
498−ST_FUNC void gen_expr64(ExprValue *pe)
499−{
500− gen_addr64(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
501−}
502−#endif
503−
504497 /* XXX: unify with C code output ? */
505498 static void gen_disp32(ExprValue *pe)
506499 {
lib/Makefile+2−2
@@ -41,7 +41,7 @@ ARM_O = libtcc1.o armeabi.o armflush.o $(COMMON_O) · 40 unmodified lines
4141 ARM64_O = lib-arm64.o $(COMMON_O)
4242 RISCV64_O = lib-arm64.o $(COMMON_O)
4343 COMMON_O = stdatomic.o atomic.o builtin.o alloca.o alloca-bt.o
44−WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
44+WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o winex.o
4545 LIN_O = dsohandle.o
4646 OSX_O =
4747
@@ -63,7 +63,7 @@ OBJ-x86_64 = $(X86_64_O) va_list.o $(LIN_O) · 15 unmodified lines
6363 OBJ-x86_64-osx = $(X86_64_O) va_list.o $(OSX_O)
6464 OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O)
6565 OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(WIN_O)
66−OBJ-arm64 = $(ARM64_O) $(LIN_O)
66+OBJ-arm64 = $(ARM64_O) armflush.o $(LIN_O)
6767 OBJ-arm64-osx = $(ARM64_O) $(OSX_O)
6868 OBJ-arm64-win32 = $(ARM64_O) chkstk.o $(WIN_O)
6969 OBJ-arm = $(ARM_O) $(LIN_O)
lib/armflush.c+13−0
@@ -4,6 +4,9 @@ · 3 unmodified lines
44 intrinsic with gcc. However tcc in order to compile
55 itself needs this function */
66
7+/* ------------------------------------------------------------- */
8+#if defined __arm__
9+
710 #ifdef __TINYC__
811
912 /* syscall wrapper */
@@ -49,3 +52,13 @@ void __clear_cache(void *beginning, void *end) · 39 unmodified lines
4952 * However, there is no ARM asm parser in tcc so we use it for now */
5053 syscall(__ARM_NR_cacheflush, beginning, end, 0);
5154 }
55+
56+/* ------------------------------------------------------------- */
57+#elif defined __aarch64__
58+void __clear_cache(void *beg, void *end)
59+{
60+ __arm64_clear_cache(beg, end);
61+}
62+
63+/* ------------------------------------------------------------- */
64+#endif
lib/bt-dll.c+24−3
@@ -34,7 +34,11 @@ · 33 unmodified lines
3434 REDIR(__bound_strncmp) \
3535 REDIR(__bound_strcat) \
3636 REDIR(__bound_strchr) \
37− REDIR(__bound_strdup)
37+ REDIR(__bound_strdup) \
38+ REDIR(__bound_strncat) \
39+ REDIR(__bound_strrchr) \
40+ REDIR(__bound_setjmp) \
41+ REDIR(__bound_longjmp)
3842
3943 #ifdef __leading_underscore
4044 #define _(s) "_"#s
@@ -45,11 +49,28 @@ · 4 unmodified lines
4549 #define REDIR(s) void *s;
4650 static struct { REDIR_ALL } all_ptrs;
4751 #undef REDIR
52+
4853 #define REDIR(s) #s"\0"
4954 static const char all_names[] = REDIR_ALL;
5055 #undef REDIR
51−#define REDIR(s) __asm__(".global " _(s) ";" _(s) ": jmp *%0" : : "m" (all_ptrs.s) );
52−static void all_jmps() { REDIR_ALL }
56+
57+#if __aarch64__
58+# define REDIR(s) \
59+ __asm__(".global "_(s)";"_(s)":"); \
60+ __asm__(".int 0x58000090"); /* ldr x16, [pc, #16] */ \
61+ __asm__(".int 0xf9400210"); /* ldr x16, [x16] */ \
62+ __asm__(".int 0xd61f0200"); /* br x16 */ \
63+ __asm__(".int 0xd503201f"); /* nop for alignment */ \
64+ __asm__(".quad all_ptrs + (. - all_jmps - 16) / 24 * 8"); \
65+ __asm__(".type "_(s)",function\n.size "_(s)",.-"_(s));
66+
67+ __asm__(".text\n.align 8\nall_jmps:");
68+ REDIR_ALL
69+#else
70+# define REDIR(s) \
71+ __asm__(".global "_(s)";"_(s)":"); goto *all_ptrs.s;
72+ static void all_jmps() { REDIR_ALL }
73+#endif
5374 #undef REDIR
5475
5576 void __bt_init_dll(int bcheck)
lib/lib-arm64.c+0−7
@@ -23,13 +23,6 @@ typedef unsigned long long uint64_t; · 22 unmodified lines
2323 #include <string.h>
2424 #endif
2525
26−#if !defined __riscv && !defined __APPLE__
27−void __clear_cache(void *beg, void *end)
28−{
29− __arm64_clear_cache(beg, end);
30−}
31−#endif
32−
3326 typedef union {
3427 struct { uint64_t x0, x1; };
3528 long double f;
lib/libtcc1.c+2−20
@@ -107,10 +107,9 @@ union float_long { · 106 unmodified lines
107107 };
108108
109109 /* XXX: we don't support several builtin supports for now */
110−#if !defined __x86_64__ && !defined __arm__ && !defined __riscv && !defined __aarch64__
110+#if defined __i386__
111111
112112 /* XXX: use gcc/tcc intrinsic ? */
113−#if defined __i386__
114113 #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
115114 __asm__ ("subl %5,%1\n\tsbbl %3,%0" \
116115 : "=r" ((USItype) (sh)), \
@@ -139,9 +138,6 @@ union float_long { · 22 unmodified lines
139138 : "=r" (__cbtmp) : "rm" ((USItype) (x))); \
140139 (count) = __cbtmp ^ 31; \
141140 } while (0)
142−#else
143−#error unsupported CPU type
144−#endif
145141
146142 /* most of this code is taken from libgcc2.c from gcc */
147143
@@ -478,7 +474,7 @@ long long __ashldi3(long long a, int b) · 330 unmodified lines
478474 #endif
479475 }
480476
481−#endif /* !__x86_64__ */
477+#endif /* __i386__ */
482478
483479 /* XXX: fix tcc's code generator to do this instead */
484480 float __floatundisf(unsigned long long a)
@@ -625,17 +621,3 @@ long long __fixxfdi (long double a1) · 140 unmodified lines
625621 return s ? ret : -ret;
626622 }
627623 #endif /* !ARM */
628−
629−#if defined _WIN64
630−/* MSVC x64 intrinsic */
631−void __faststorefence(void)
632−{
633−#if defined(__aarch64__)
634− /* ARM64: Data Memory Barrier (Inner Shareable) */
635− __asm__("dmb ish");
636−#else
637− /* x86-64: lock prefix to flush store buffer */
638− __asm__("lock; orl $0,(%%rsp)" ::: "memory");
639−#endif
640−}
641−#endif
libtcc.c+8−1
@@ -124,8 +124,15 @@ static void tcc_add_systemdir(TCCState *s) · 123 unmodified lines
124124 tcc_add_library_path(s, normalize_slashes(buf));
125125 }
126126 #endif
127+/* for tcc -E : On windows (depending on compiler) a FILE*
128+ must be created by the same module where it is used. */
129+PUB_FUNC FILE *tcc_fopen(const char *f, const char *m) {
130+ return fopen(f, m);
131+}
132+PUB_FUNC int tcc_fclose(FILE *f) {
133+ return fclose(f);
134+}
127135 #endif
128−
129136 /********************************************************/
130137
131138 PUB_FUNC void tcc_enter_state(TCCState *s1)
tcc.c+6−6
@@ -293,7 +293,7 @@ int main(int argc, char **argv) · 292 unmodified lines
293293 const char *first_file;
294294 int argc0 = argc;
295295 char **argv0 = argv;
296− FILE *ppfp = stdout;
296+ FILE *ppfp = NULL;
297297
298298 redo:
299299 argc = argc0, argv = argv0;
@@ -335,7 +335,7 @@ redo: · 35 unmodified lines
335335 tcc_error_noabort("no input files");
336336 } else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
337337 if (s->outfile && 0!=strcmp("-",s->outfile)) {
338− ppfp = fopen(s->outfile, "wb");
338+ ppfp = tcc_fopen(s->outfile, "wb");
339339 if (!ppfp)
340340 tcc_error_noabort("could not write '%s'", s->outfile);
341341 }
@@ -355,8 +355,8 @@ redo: · 13 unmodified lines
355355 if (s->output_type == 0)
356356 s->output_type = TCC_OUTPUT_EXE;
357357 tcc_set_output_type(s, s->output_type);
358− s->ppfp = ppfp;
359−
358+ if (ppfp)
359+ s->ppfp = ppfp;
360360 if ((s->output_type == TCC_OUTPUT_MEMORY
361361 || s->output_type == TCC_OUTPUT_PREPROCESS)
362362 && (s->dflag & 16)) { /* -dt option */
@@ -422,7 +422,7 @@ redo: · 59 unmodified lines
422422 tcc_delete(s);
423423 if (!done)
424424 goto redo;
425− if (ppfp && ppfp != stdout)
426− fclose(ppfp);
425+ if (ppfp)
426+ tcc_fclose(ppfp);
427427 return ret;
428428 }
tcc.h+15−6
@@ -52,6 +52,9 @@ extern long double strtold (const char *__nptr, char **__endptr); · 51 unmodified lines
5252
5353 #ifdef _WIN32
5454 # define WIN32_LEAN_AND_MEAN 1
55+# ifndef _WIN32_WINNT
56+# define _WIN32_WINNT 0x502 /* AddVectoredExceptionHandler */
57+# endif
5558 # include <windows.h>
5659 # include <io.h> /* open, close etc. */
5760 # include <direct.h> /* getcwd */
@@ -86,6 +89,9 @@ extern long double strtold (const char *__nptr, char **__endptr); · 28 unmodified lines
8689 # define __x86_64__ 1
8790 # endif
8891 # endif
92+# if defined(_M_ARM64) && !defined(__aarch64__)
93+# define __aarch64__ 1
94+# endif
8995 # ifndef va_copy
9096 # define va_copy(a,b) a = b
9197 # endif
@@ -228,8 +234,7 @@ extern long double strtold (const char *__nptr, char **__endptr); · 136 unmodified lines
228234 /* No ten-byte long doubles on window and macos except in
229235 cross-compilers made by a mingw-GCC */
230236 #if defined TCC_TARGET_PE \
231− || (defined TCC_TARGET_MACHO && defined TCC_TARGET_ARM64) \
232− || (defined _WIN32 && !defined __GNUC__)
237+ || (defined TCC_TARGET_MACHO && defined TCC_TARGET_ARM64)
233238 # define TCC_USING_DOUBLE_FOR_LDOUBLE 1
234239 #endif
235240
@@ -1312,6 +1317,11 @@ PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time); · 1076 unmodified lines
13121317 PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv);
13131318 #ifdef _WIN32
13141319 ST_FUNC char *normalize_slashes(char *path);
1320+PUB_FUNC FILE *tcc_fopen(const char *f, const char *m);
1321+PUB_FUNC int tcc_fclose(FILE *f);
1322+#else
1323+# define tcc_fopen fopen
1324+# define tcc_fclose fclose
13151325 #endif
13161326 ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level);
13171327 ST_FUNC char *tcc_load_text(int fd);
@@ -1683,7 +1693,6 @@ ST_FUNC void gen_increment_tcov (SValue *sv); · 365 unmodified lines
16831693
16841694 /* ------------ x86_64-gen.c ------------ */
16851695 #ifdef TCC_TARGET_X86_64
1686−ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c);
16871696 ST_FUNC void gen_opl(int op);
16881697 #ifdef TCC_TARGET_PE
16891698 ST_FUNC void gen_vla_result(int addr);
@@ -1742,11 +1751,11 @@ ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *n · 52 unmodified lines
17421751 ST_FUNC Sym* get_asm_sym(int name, Sym *csym);
17431752 ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
17441753 ST_FUNC int asm_int_expr(TCCState *s1);
1745−/* ------------ i386-asm.c ------------ */
1746−ST_FUNC void gen_expr32(ExprValue *pe);
1747−#ifdef TCC_TARGET_X86_64
1754+#if PTR_SIZE == 8
17481755 ST_FUNC void gen_expr64(ExprValue *pe);
17491756 #endif
1757+/* ------------ i386-asm.c ------------ */
1758+ST_FUNC void gen_expr32(ExprValue *pe);
17501759 ST_FUNC void asm_opcode(TCCState *s1, int opcode);
17511760 ST_FUNC int asm_parse_regvar(int t);
17521761 ST_FUNC void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
tccasm.c+30−11
@@ -25,6 +25,26 @@ · 24 unmodified lines
2525 static Section *last_text_section; /* to handle .previous asm directive */
2626 static int asmgoto_n;
2727
28+static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global);
29+static Sym* asm_new_label(TCCState *s1, int label, int is_local);
30+static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value);
31+
32+#if PTR_SIZE == 8
33+/* output constant with relocation if 'r & VT_SYM' is true */
34+ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c)
35+{
36+ if (r & VT_SYM)
37+ greloca(cur_text_section, sym, ind, R_DATA_PTR, c), c=0;
38+ gen_le32(c);
39+ gen_le32(c>>32);
40+}
41+
42+ST_FUNC void gen_expr64(ExprValue *pe)
43+{
44+ gen_addr64(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
45+}
46+#endif
47+
2848 static int asm_get_prefix_name(TCCState *s1, const char *prefix, unsigned int n)
2949 {
3050 char buf[64];
@@ -37,10 +57,6 @@ ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n) · 6 unmodified lines
3757 return asm_get_prefix_name(s1, "L..", n);
3858 }
3959
40−static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global);
41−static Sym* asm_new_label(TCCState *s1, int label, int is_local);
42−static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value);
43−
4460 /* If a C name has an _ prepended then only asm labels that start
4561 with _ are representable in C, by removing the first _. ASM names
4662 without _ at the beginning don't correspond to C names, but we use
@@ -328,12 +344,12 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe) · 281 unmodified lines
328344 if (esym1 && esym1->st_shndx == esym2->st_shndx
329345 && esym1->st_shndx != SHN_UNDEF) {
330346 /* we also accept defined symbols in the same section */
331− pe->v += esym1->st_value - esym2->st_value;
347+ pe->v += (int)(esym1->st_value - esym2->st_value);
332348 pe->sym = NULL;
333349 } else if (esym2->st_shndx == cur_text_section->sh_num) {
334350 /* When subtracting a defined symbol in current section
335351 this actually makes the value PC-relative. */
336− pe->v += 0 - esym2->st_value;
352+ pe->v += (int)(0 - esym2->st_value);
337353 pe->pcrel = 1;
338354 e2.sym = NULL;
339355 } else {
@@ -543,7 +559,7 @@ static void asm_parse_directive(TCCState *s1, int global) · 203 unmodified lines
543559 ind += size;
544560 break;
545561 case TOK_ASMDIR_quad:
546−#ifdef TCC_TARGET_X86_64
562+#if PTR_SIZE == 8
547563 size = 8;
548564 goto asm_data;
549565 #else
@@ -592,7 +608,7 @@ static void asm_parse_directive(TCCState *s1, int global) · 42 unmodified lines
592608 if (sec->sh_type != SHT_NOBITS) {
593609 if (size == 4) {
594610 gen_expr32(&e);
595−#ifdef TCC_TARGET_X86_64
611+#if PTR_SIZE == 8
596612 } else if (size == 8) {
597613 gen_expr64(&e);
598614 #endif
@@ -812,6 +828,7 @@ static void asm_parse_directive(TCCState *s1, int global) · 213 unmodified lines
812828 case TOK_ASMDIR_size:
813829 {
814830 Sym *sym;
831+ ElfSym *esym;
815832
816833 next();
817834 if (tok < TOK_IDENT)
@@ -823,8 +840,10 @@ static void asm_parse_directive(TCCState *s1, int global) · 5 unmodified lines
823840 tcc_warning_c(warn_unsupported)("ignoring .size %s,*", get_tok_str(tok, NULL));
824841 next();
825842 skip(',');
826− while (tok != TOK_LINEFEED && tok != ';' && tok != CH_EOF) {
827− next();
843+ n = asm_int_expr(s1);
844+ esym = elfsym(sym);
845+ if (esym) {
846+ esym->st_size = n;
828847 }
829848 }
830849 break;
@@ -952,7 +971,7 @@ static void asm_parse_directive(TCCState *s1, int global) · 121 unmodified lines
952971 }
953972 break;
954973 #endif
955−#ifdef TCC_TARGET_X86_64
974+#if PTR_SIZE == 8
956975 /* added for compatibility with GAS */
957976 case TOK_ASMDIR_code64:
958977 next();
tcclib.h+2−0
@@ -19,6 +19,7 @@ int atoi(const char *nptr); · 18 unmodified lines
1919 long int strtol(const char *nptr, char **endptr, int base);
2020 unsigned long int strtoul(const char *nptr, char **endptr, int base);
2121 void exit(int);
22+void *alloca(size_t);
2223
2324 /* stdio.h */
2425 typedef struct __FILE FILE;
@@ -39,6 +40,7 @@ int getchar(void); · 14 unmodified lines
3940 char *gets(char *s);
4041 int ungetc(int c, FILE *stream);
4142 int fflush(FILE *stream);
43+int puts(const char *s);
4244 int putchar (int c);
4345
4446 int printf(const char *format, ...);
tccpe.c+24−45
@@ -1958,6 +1958,7 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack) · 1957 unmodified lines
19581958 for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress)
19591959 put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym);
19601960 }
1961+
19611962 #elif defined(TCC_TARGET_ARM64)
19621963 /* ARM64 unwind codes:
19631964 save_fplr_x: 10iiiiii - stp x29,lr,[sp,#-(i+1)*8]!
@@ -1975,10 +1976,7 @@ static Section *pe_add_unwind_info(TCCState *s1) · 11 unmodified lines
19751976 s1->uw_pdata->sh_addralign = 4;
19761977 }
19771978 s = find_section(s1, ".xdata");
1978− if (NULL == s) {
1979− s = new_section(s1, ".xdata", SHT_PROGBITS, SHF_ALLOC);
1980− s->sh_addralign = 4;
1981− }
1979+ s->sh_addralign = 4;
19821980 if (0 == s1->uw_sym)
19831981 s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0,
19841982 text_section->sh_num, ".uw_text_base");
@@ -1992,31 +1990,22 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack) · 7 unmodified lines
19921990 {
19931991 TCCState *s1 = tcc_state;
19941992 Section *pd, *xd;
1995− unsigned o, n, d, code_bytes, func_len, stack_slots;
1993+ unsigned o, d, code_bytes, func_len;
19961994 unsigned char *q;
19971995 uint32_t header;
1998− struct {
1996+ struct /* _RUNTIME_FUNCTION */ {
19991997 DWORD BeginAddress;
2000− DWORD EndAddress;
20011998 DWORD UnwindData;
20021999 } *p;
20032000
2001+ int epilog;
2002+
20042003 xd = pe_add_unwind_info(s1);
20052004 pd = s1->uw_pdata;
20062005
2007− stack = (stack + 15) & ~15;
2008− stack_slots = stack >> 4;
20092006 func_len = (end - start) >> 2;
20102007 code_bytes = 0;
2011− if (stack_slots) {
2012− if (stack_slots <= 31) {
2013− code_bytes += 1;
2014− } else if (stack_slots <= 0x7ff) {
2015− code_bytes += 2;
2016− } else {
2017− code_bytes += 4;
2018− }
2019− }
2008+ epilog = code_bytes;
20202009 code_bytes += 3; /* set_fp, save_fplr_x, end */
20212010 code_bytes = (code_bytes + 3) & ~3;
20222011
@@ -2025,23 +2014,13 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack) · 2 unmodified lines
20252014 q = section_ptr_add(xd, 4 + code_bytes);
20262015
20272016 /* Full ARM64 xdata header: E=1 with one epilog and no exception handler. */
2028− header = (func_len & 0x3ffff) | (1u << 21) | ((code_bytes >> 2) << 27);
2017+ header = (func_len & 0x3ffff)
2018+ | 1 << 21
2019+ | (epilog & 0x1F) << 22
2020+ | (code_bytes >> 2) << 27
2021+ ;
20292022 write32le(q, header);
20302023 q += 4;
2031−
2032− if (stack_slots) {
2033− if (stack_slots <= 31) {
2034− *q++ = stack_slots; /* alloc_s */
2035− } else if (stack_slots <= 0x7ff) {
2036− *q++ = 0xC0 | (stack_slots >> 8); /* alloc_m */
2037− *q++ = stack_slots & 0xff;
2038− } else {
2039− *q++ = 0xE0; /* alloc_l */
2040− *q++ = (stack_slots >> 16) & 0xff;
2041− *q++ = (stack_slots >> 8) & 0xff;
2042− *q++ = stack_slots & 0xff;
2043− }
2044− }
20452024 *q++ = 0xE1; /* set_fp */
20462025 *q++ = 0x9B; /* save_fplr_x: stp x29,lr,[sp,#-224]! */
20472026 *q++ = 0xE4; /* end */
@@ -2050,14 +2029,10 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack) · 2 unmodified lines
20502029
20512030 o = pd->data_offset;
20522031 p = section_ptr_add(pd, sizeof *p);
2053−
20542032 p->BeginAddress = start;
2055− p->EndAddress = end;
20562033 p->UnwindData = d;
2057−
2058− for (n = o + 2 * sizeof p->BeginAddress; o < n; o += sizeof p->BeginAddress)
2059− put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym);
2060− put_elf_reloc(symtab_section, pd, n, R_XXX_RELATIVE, s1->uw_xsym);
2034+ put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym);
2035+ put_elf_reloc(symtab_section, pd, o + 4, R_XXX_RELATIVE, s1->uw_xsym);
20612036 }
20622037 #endif
20632038 /* ------------------------------------------------------------- */
@@ -2252,20 +2227,22 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) · 188 unmodified lines
22522227 resolve_common_syms(s1);
22532228 pe_set_options(s1, &pe);
22542229 pe_check_symbols(&pe);
2255−
22562230 if (s1->nb_errors)
2257− ;
2258− else if (filename) {
2231+ goto done;
2232+ if (filename) {
22592233 pe_assign_addresses(&pe);
22602234 relocate_syms(s1, s1->symtab, 0);
2235+ if (s1->nb_errors)
2236+ goto done;
22612237 s1->pe_imagebase = pe.imagebase;
22622238 relocate_sections(s1);
22632239 pe.start_addr = (DWORD)
22642240 (get_sym_addr(s1, pe.start_symbol, 1, 1) - pe.imagebase);
2265− if (0 == s1->nb_errors)
2266− pe_write(&pe);
2267− dynarray_reset(&pe.sec_info, &pe.sec_count);
2241+ if (s1->nb_errors)
2242+ goto done;
2243+ pe_write(&pe);
22682244 } else {
2245+ /* -run */
22692246 #ifdef TCC_IS_NATIVE
22702247 pe.thunk = data_section;
22712248 pe_build_imports(&pe);
@@ -2275,6 +2252,8 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) · 3 unmodified lines
22752252 #endif
22762253 #endif
22772254 }
2255+done:
2256+ dynarray_reset(&pe.sec_info, &pe.sec_count);
22782257 pe_free_imports(&pe);
22792258 #if PE_PRINT_SECTIONS
22802259 if (g_debug & 8)
tccrun.c+2−0
@@ -434,6 +434,8 @@ redo: · 433 unmodified lines
434434
435435 /* relocate symbols */
436436 relocate_syms(s1, s1->symtab, 1);
437+ if (s1->nb_errors)
438+ goto redo;
437439 /* relocate sections */
438440 #ifdef TCC_TARGET_PE
439441 s1->pe_imagebase = mem;
tcctok.h+4−3
@@ -402,12 +402,13 @@ · 401 unmodified lines
402402 DEF_ASMDIR(endr)
403403 DEF_ASMDIR(org)
404404 DEF_ASMDIR(quad)
405−#if defined(TCC_TARGET_I386)
405+#if PTR_SIZE == 4
406406 DEF_ASMDIR(code16)
407407 DEF_ASMDIR(code32)
408−#elif defined(TCC_TARGET_X86_64)
408+#else
409409 DEF_ASMDIR(code64)
410−#elif defined(TCC_TARGET_RISCV64)
410+#endif
411+#if defined(TCC_TARGET_RISCV64)
411412 DEF_ASMDIR(option)
412413 #endif
413414 DEF_ASMDIR(short)
tests/Makefile+5−4
@@ -72,9 +72,9 @@ endif · 71 unmodified lines
7272 RUN_TCC = -run $(TOPSRC)/tcc.c $(TCCFLAGS)
7373 DISAS = objdump -d
7474 ifdef CONFIG_OSX
75−DUMPTCC = (set -x; $(TOP)/tcc -vv; otool -L $(TOP)/tcc; exit 1)
75+DUMPTCC = (set -x; $(TCC_LOCAL) -vv; otool -L $(TCC_LOCAL); exit 1)
7676 else
77−DUMPTCC = (set -x; $(TOP)/tcc -vv; ldd $(TOP)/tcc; exit 1)
77+DUMPTCC = (set -x; $(TCC_LOCAL) -vv; ldd $(TCC_LOCAL); exit 1)
7878 endif
7979
8080 all test :
@@ -82,6 +82,7 @@ all test : · 1 unmodified line
8282 @$(TCC_LOCAL) -v
8383 @$(MAKE) --no-print-directory -s clean
8484 @$(MAKE) --no-print-directory -s -r _all
85+ @echo ------- ALL TESTS PASSED --------
8586
8687 _all : $(TESTS)
8788
@@ -109,8 +110,8 @@ libtcc_test_mt$(EXESUF): libtcc_test_mt.c · 21 unmodified lines
109110
110111 # test.ref - generate using cc
111112 test.ref: tcctest.c
112− $(CC) -o tcctest.gcc $< $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer
113− ./tcctest.gcc > $@
113+ $(CC) -o tcctest.gcc$(EXESUF) $< $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer
114+ ./tcctest.gcc$(EXESUF) > $@
114115
115116 # auto test
116117 test1 test1b: tcctest.c test.ref
tests/libtcc_test_mt.c+8−12
@@ -162,6 +162,7 @@ void *reloc_state(TCCState *s, const char *entry) · 161 unmodified lines
162162 {
163163 void *func;
164164 tcc_add_symbol(s, "add", add);
165+ tcc_add_symbol(s, "printf", printf);
165166 if (tcc_relocate(s) < 0) {
166167 fprintf(stderr, __FILE__ ": could not relocate tcc state.\n");
167168 return NULL;
@@ -337,16 +338,15 @@ int main(int argc, char **argv) · 169 unmodified lines
337338
338339 #else
339340 #include <tcclib.h>
340−
341341 #ifdef _WIN32
342−# ifdef __i386__
343−# define LIBTCC_TEST_WINAPI __attribute__((__stdcall__))
344−# else
345−# define LIBTCC_TEST_WINAPI
342+# ifndef _WIN64
343+ __declspec(stdcall)
346344 # endif
347−void LIBTCC_TEST_WINAPI Sleep(unsigned int milliseconds);
345+ void Sleep(unsigned);
346+# define sleep_ms Sleep
348347 #else
349−unsigned int sleep(unsigned int seconds);
348+ int usleep(unsigned long);
349+# define sleep_ms(x) usleep((x)*1000);
350350 #endif
351351
352352 int fib(n)
@@ -356,11 +356,7 @@ int fib(n) · 3 unmodified lines
356356
357357 int main(int argc, char **argv)
358358 {
359−#ifdef _WIN32
360− Sleep(1000);
361−#else
362− sleep(1);
363−#endif
359+ sleep_ms(333);
364360 printf(" %d", fib(atoi(argv[1])));
365361 return 0;
366362 }
tests/msvcrt_start.c+164−0
@@ -0,0 +1,164 @@
1+/* ------------------------------------------------------------- */
2+/* minimal startup with runtime linker to msvcrt */
3+
4+#if 0
5+
6+#define REDIR_ALL \
7+ REDIR(__set_app_type)\
8+ REDIR(__getmainargs)\
9+ REDIR(_controlfp)\
10+ REDIR(_vsnprintf)\
11+ REDIR(exit)\
12+ \
13+ REDIR(puts)\
14+ REDIR(printf)\
15+ REDIR(putchar)\
16+ REDIR(strtod)\
17+ REDIR(memset)\
18+ REDIR(strcpy)\
19+ REDIR(strlen)\
20+ REDIR(malloc)\
21+ REDIR(free)\
22+
23+#if defined __i386__ && !defined __TINYC__
24+# define __leading_underscore 1
25+#endif
26+
27+#ifdef __leading_underscore
28+# define _(s) "_"#s
29+#else
30+# define _(s) #s
31+#endif
32+
33+#define REDIR(s) void *s;
34+static struct { REDIR_ALL } all_ptrs;
35+#undef REDIR
36+
37+#define REDIR(s) #s"\0"
38+static const char all_names[] = REDIR_ALL;
39+#undef REDIR
40+
41+#if __aarch64__
42+ #if defined __TINYC__
43+ # define ALIGN ".align 8"
44+ #else
45+ # define ALIGN ".align 3" /* .align is power of 2 on non-ELF platforms */
46+ #endif
47+# define REDIR(s) \
48+ __asm__("\n"_(s)":"); \
49+ __asm__(".int 0x58000090"); /* ldr x16, [pc, #16] */ \
50+ __asm__(".int 0xf9400210"); /* ldr x16, [x16] */ \
51+ __asm__(".int 0xd61f0200"); /* br x16 */ \
52+ __asm__(".int 0xd503201f"); /* nop for alignment */ \
53+ __asm__(".quad all_ptrs + (. - all_jmps - 16) / 24 * 8"); \
54+ __asm__(".global "_(s));
55+
56+ __asm__("\t.text\n\t"ALIGN"\nall_jmps:");
57+ REDIR_ALL
58+#else
59+# define REDIR(s) \
60+ __asm__("\n"_(s)":");\
61+ __asm__("jmp *%0"::"m"(all_ptrs.s));\
62+ __asm__(".global "_(s));
63+
64+ static void all_jmps() { REDIR_ALL }
65+#endif
66+#undef REDIR
67+
68+#if 0
69+# include <windows.h>
70+#else
71+# if __i386__
72+# define STDCALL __declspec(stdcall)
73+# else
74+# define STDCALL
75+# endif
76+# define DWORD long unsigned
77+# define HMODULE void*
78+# define HANDLE void*
79+S TDCALL HMODULE LoadLibraryA(const char *);
80+S TDCALL HMODULE GetProcAddress(HMODULE , char*);
81+S TDCALL void ExitProcess(int);
82+S TDCALL int WriteFile(HANDLE, const void*, DWORD, DWORD*, void*);
83+S TDCALL HANDLE GetStdHandle(DWORD);
84+S TDCALL int FlushFileBuffers(HANDLE);
85+# define STD_ERROR_HANDLE -12
86+#endif
87+
88+static void eput(const char *s)
89+{
90+ DWORD n_out;
91+ int n = 0;
92+ while (s[n])
93+ ++n;
94+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), s, n, &n_out, 0);
95+}
96+
97+static void rt_reloc()
98+{
99+ const char *s = all_names;
100+ void **p = (void**)&all_ptrs;
101+ void *dll = LoadLibraryA("msvcrt.dll");
102+ do {
103+ char buf[100], *d = buf;
104+ *p = (void*)GetProcAddress(dll, (char*)s);
105+ *d++ = '_'; do *d++ = *s; while (*s++);
106+ if (0 == *p)
107+ *p = (void*)GetProcAddress(dll, buf);
108+ if (0 == *p) {
109+ eput("MSVCRT_START.C: RUNTIME RELOCATION ERROR: '");
110+ eput(buf+1);
111+ eput("'\n");
112+ ExitProcess(-1);
113+ }
114+ ++p;
115+ } while (*s);
116+}
117+
118+#else
119+# define rt_reloc()
120+#endif
121+
122+int main(int argc, char **argv, char **env);
123+void exit(int);
124+void __set_app_type(int apptype);
125+
126+typedef struct { int newmode; } _startupinfo;
127+int __getmainargs(int *pargc, char ***pargv, char ***penv, int globb, _startupinfo*);
128+
129+void _controlfp(unsigned a, unsigned b);
130+#define _MCW_PC 0x00030000 // Precision Control
131+#define _PC_53 0x00010000 // 53 bits
132+
133+int __argc;
134+char **__argv;
135+char **environ;
136+_startupinfo start_info = {0};
137+
138+void mainCRTStartup(void)
139+{
140+ rt_reloc();
141+#if defined __i386__ || defined __x86_64__
142+ _controlfp(_PC_53, _MCW_PC);
143+#endif
144+ __set_app_type(1);
145+ __getmainargs(&__argc, &__argv, &environ, 0, &start_info);
146+ exit(main(__argc, __argv, environ));
147+}
148+
149+#include <stdarg.h>
150+#define size_t __SIZE_TYPE__
151+int printf(const char *, ...);
152+int _vsnprintf(char *, size_t, const char *, va_list);
153+
154+/* undefined on windows-11-arm64 */
155+int vprintf(const char *format, va_list ap)
156+{
157+ char buf[1000];
158+ _vsnprintf(buf, sizeof buf, format, ap);
159+ return printf("%s", buf);
160+}
161+
162+void __main() {} /* for gcc */
163+void _pei386_runtime_relocator(void) {} /* for gcc */
164+void __chkstk(unsigned n) {} /* for clang */
tests/tcctest.c+18−19
@@ -81,9 +81,6 @@ typedef __SIZE_TYPE__ uintptr_t; · 80 unmodified lines
8181 #include incname
8282 #include stringify(funnyname)
8383
84−int puts(const char *s);
85−void *alloca(size_t size);
86−
8784 int fib(int n);
8885 void num(int n);
8986 void forward_ref(void);
@@ -287,6 +284,7 @@ comment · 197 unmodified lines
287284
288285 printf("basefromheader %s\n", get_basefile_from_header());
289286 printf("base %s\n", __BASE_FILE__);
287+#if !(defined _WIN32 && CC_NAME == CC_clang)
290288 {
291289 /* Some compilers (clang) prepend './' to __FILE__ from included
292290 files. */
@@ -295,6 +293,8 @@ comment · 2 unmodified lines
295293 fn += 2;
296294 printf("filefromheader %s\n", fn);
297295 }
296+#endif
297+
298298 printf("file %s\n", __FILE__);
299299
300300 /* Check that funnily named include was in fact included */
@@ -1095,8 +1095,10 @@ void struct_test() · 794 unmodified lines
10951095 sizeof(struct aligntest2), __alignof__(struct aligntest2));
10961096 printf("aligntest3 sizeof=%d alignof=%d\n",
10971097 sizeof(struct aligntest3), __alignof__(struct aligntest3));
1098+#if !(defined _WIN32 && CC_NAME == CC_clang)
10981099 printf("aligntest4 sizeof=%d alignof=%d\n",
10991100 sizeof(struct aligntest4), __alignof__(struct aligntest4));
1101+#endif
11001102 printf("aligntest5 sizeof=%d alignof=%d\n",
11011103 sizeof(struct aligntest5), __alignof__(struct aligntest5));
11021104 printf("aligntest6 sizeof=%d alignof=%d\n",
@@ -1105,8 +1107,10 @@ void struct_test() · 2 unmodified lines
11051107 sizeof(struct aligntest7), __alignof__(struct aligntest7));
11061108 printf("aligntest8 sizeof=%d alignof=%d\n",
11071109 sizeof(struct aligntest8), __alignof__(struct aligntest8));
1110+#if !(defined _WIN32 && CC_NAME == CC_clang)
11081111 printf("aligntest9 sizeof=%d alignof=%d\n",
11091112 sizeof(struct aligntest9), __alignof__(struct aligntest9));
1113+#endif
11101114 printf("aligntest10 sizeof=%d alignof=%d\n",
11111115 sizeof(struct aligntest10), __alignof__(struct aligntest10));
11121116 printf("altest5 sizeof=%d alignof=%d\n",
@@ -1117,7 +1121,9 @@ void struct_test() · 4 unmodified lines
11171121 sizeof(altest7), __alignof__(altest7));
11181122
11191123 /* empty structures (GCC extension) */
1124+#if !(defined _WIN32 && CC_NAME == CC_clang)
11201125 printf("sizeof(struct empty) = %d\n", sizeof(struct empty));
1126+#endif
11211127 printf("alignof(struct empty) = %d\n", __alignof__(struct empty));
11221128
11231129 printf("Large: sizeof=%d\n", sizeof(ls));
@@ -2176,15 +2182,6 @@ float strtof(const char *nptr, char **endptr); · 1052 unmodified lines
21762182 LONG_DOUBLE strtold(const char *nptr, char **endptr);
21772183 #endif
21782184
2179−#if CC_NAME == CC_clang
2180−/* In clang 0.0/0.0 is nan and not -nan.
2181− Also some older clang version do v=-v
2182− as v = -0 - v */
2183−static char enable_nan_test = 0;
2184−#else
2185−static char enable_nan_test = 1;
2186−#endif
2187−
21882185 #define FTEST(prefix, typename, type, fmt)\
21892186 void prefix ## cmp(type a, type b)\
21902187 {\
@@ -2240,7 +2237,7 @@ void prefix ## fcast(type a)\ · 49 unmodified lines
22402237 b = llia;\
22412238 printf("lltof: " fmt "\n", b);\
22422239 b = llua;\
2243− printf("ulltof: " fmt "\n", b);\
2240+ if (CC_NAME != CC_clang) printf("ulltof: " fmt "\n", b);\
22442241 }\
22452242 \
22462243 float prefix ## retf(type a) { return a; }\
@@ -2300,7 +2297,7 @@ void prefix ## test(void)\ · 53 unmodified lines
23002297 prefix ## fcast(-2334.6);\
23012298 prefix ## call();\
23022299 prefix ## signed_zeros();\
2303− if (enable_nan_test) prefix ## nan();\
2300+ if (CC_NAME != CC_clang) prefix ## nan();\
23042301 }
23052302
23062303 FTEST(f, float, float, "%f")
@@ -2556,8 +2553,8 @@ void longlong_test(void) · 249 unmodified lines
25562553 a = ia;
25572554 b = ua;
25582555 printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", a, b);
2559− printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %Lx\n",
2560− (long long)1,
2556+ printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " "XLONG_LONG_FORMAT"\n",
2557+ (long long)1,
25612558 (long long)-2,
25622559 1LL,
25632560 0x1234567812345679);
@@ -2867,12 +2864,14 @@ void stdarg_test(void) · 303 unmodified lines
28672864 stdarg_for_struct(bob, bob2, bob3, bob4, bob, bob, bob.profile);
28682865 stdarg_for_libc("stdarg_for_libc: %s %.2f %d\n", "string", 1.23, 456);
28692866 stdarg_syntax(1, 17);
2867+#if !(defined _WIN32 && CC_NAME == CC_clang) /* broken clang */
28702868 stdarg_double_struct(6,-1,pts[0],pts[1],pts[2],pts[3],pts[4],pts[5]);
28712869 stdarg_double_struct(7,1,pts[0],-1.0,pts[1],pts[2],pts[3],pts[4],pts[5]);
28722870 stdarg_double_struct(7,2,pts[0],pts[1],-1.0,pts[2],pts[3],pts[4],pts[5]);
28732871 stdarg_double_struct(7,3,pts[0],pts[1],pts[2],-1.0,pts[3],pts[4],pts[5]);
28742872 stdarg_double_struct(7,4,pts[0],pts[1],pts[2],pts[3],-1.0,pts[4],pts[5]);
28752873 stdarg_double_struct(7,5,pts[0],pts[1],pts[2],pts[3],pts[4],-1.0,pts[5]);
2874+#endif
28762875 }
28772876
28782877 int reltab[3] = { 1, 2, 3 };
@@ -3289,7 +3288,7 @@ void local_label_test(void) · 410 unmodified lines
32893288 }
32903289
32913290 /* inline assembler test */
3292−#if defined(__i386__) || defined(__x86_64__)
3291+#if (defined(__i386__) || defined(__x86_64__)) && !(defined _WIN32 && CC_NAME == CC_clang)
32933292
32943293 typedef __SIZE_TYPE__ word;
32953294
@@ -3551,8 +3550,8 @@ void asm_local_label_diff (void) · 255 unmodified lines
35513550 {
35523551 printf ("asm_local_label_diff: %d %d\n", alld_stuff[0], alld_stuff[1]);
35533552 }
3554−#endif
3555−#endif
3553+#endif //!__APPLE__
3554+#endif //!_WIN32
35563555
35573556 /* This checks that static local variables are available from assembler. */
35583557 void asm_local_statics (void)
tests/test-win32.bat+74−0
@@ -0,0 +1,74 @@
1+@echo off
2+setlocal
3+set CC=gcc
4+set TESTS=
5+if "%1"=="/?" goto :usage
6+goto :p0
7+
8+:usage
9+echo usage: test-win32.bat [options...] [tests...]
10+echo options:
11+echo -c compiler reference compiler (gcc or clang)
12+echo -p path prepend path to PATH
13+echo tests tests to run (default all)
14+echo requires: make, gcc/clang, and sh in the PATH
15+exit /B 1
16+
17+:p2
18+shift
19+:p1
20+shift
21+:p0
22+if "%1"=="-c" set CC=%2&&goto p2
23+if "%1"=="-p" set PATH=%2;%PATH%&&goto p2
24+if not "%1"=="" set TESTS=%TESTS% %1&&goto p1
25+if "%TESTS%"=="" set TESTS=all -k
26+
27+set PATH=%CD%\..\win32;%PATH%
28+
29+for /f "delims=-" %%a in ('tcc.exe -dumpmachine') do set ARCH=%%a
30+set ARCH=%ARCH:aarch=arm%
31+set MACH=%ARCH:i386=x86%
32+set MACH=%MACH:x86_64=amd64%
33+rem echo ARCH:%ARCH% MACHINE:%MACH%
34+
35+set CRTLIB=c:/windows/system32/msvcrt.dll
36+set LIBTCC=libtcc.dll
37+set LGCC=-lgcc
38+if %CC%==gcc goto :c2
39+
40+set CRTLIB=msvcrt.lib
41+set LIBTCC=libtcc.lib
42+set LGCC=
43+if exist %CRTLIB% goto :c3
44+tcc -impdef msvcrt.dll
45+lib >nul /def:msvcrt.def /out:%CRTLIB% /machine:%MACH%
46+:c2
47+if not exist %CRTLIB% echo test-win32.bat: error: %CRTLIB% not found&&exit /b 1
48+:c3
49+
50+set REF_LINK=-nostdlib msvcrt_start.c %LGCC% -lkernel32 %CRTLIB%
51+set CFG_MAK=..\config.mak
52+set CFG_H=..\config.h
53+
54+echo>>%CFG_H% #define CC_NAME CC_%CC%
55+echo>>%CFG_H% #define GCC_MAJOR 15
56+
57+if exist %CFG_MAK% del %CFG_MAK%
58+echo>>%CFG_MAK% CC = %CC%.exe
59+echo>>%CFG_MAK% CC_NAME = %CC%
60+echo>>%CFG_MAK% ARCH = %ARCH%
61+echo>>%CFG_MAK% CFLAGS = -Wall -O0
62+echo>>%CFG_MAK% LDFLAGS =
63+echo>>%CFG_MAK% LIBSUF = .lib
64+echo>>%CFG_MAK% prefix = $(TOP)/bin
65+echo>>%CFG_MAK% EXESUF = .exe
66+echo>>%CFG_MAK% DLLSUF = .dll
67+echo>>%CFG_MAK% TARGETOS = WIN32
68+echo>>%CFG_MAK% CONFIG_WIN32 = yes
69+echo>>%CFG_MAK% TOPSRC = $(TOP)
70+echo>>%CFG_MAK% SHELL = sh
71+echo>>%CFG_MAK% test.ref: CFLAGS += %REF_LINK%
72+
73+set GMAKE=make
74+%GMAKE% TCC_LOCAL=tcc.exe LIBTCC=win32/%LIBTCC% %TESTS%
tests/tests2/Makefile+7−16
@@ -48,26 +48,16 @@ ifeq (-$(CONFIG_WIN32)-,-yes-) · 47 unmodified lines
4848 SKIP += 117_builtins.test # win32 port doesn't define __builtins
4949 SKIP += 124_atomic_counter.test # No pthread support
5050 endif
51−ifneq (,$(filter arm% riscv%,$(ARCH)))
52− SKIP += 85_asm-outside-function.test
53− SKIP += 98_al_ax_extend.test
54− SKIP += 99_fastcall.test
55− SKIP += 127_asm_goto.test
56−endif
57−ifeq (,$(filter arm64 aarch64,$(ARCH)))
58− SKIP += 138_arm64_encoding.test
59− SKIP += 139_arm64_errors.test
60−endif
61−ifneq (,$(findstring win32,$(CROSS_TARGET)))
62− SKIP += 106_versym.test
63− SKIP += 114_bound_signal.test
64− SKIP += 124_atomic_counter.test
65−endif
6651 ifneq (,$(filter OpenBSD FreeBSD NetBSD,$(TARGETOS)))
6752 SKIP += 106_versym.test # no pthread_condattr_setpshared
6853 SKIP += 114_bound_signal.test # libc problem signal/fork
6954 SKIP += 116_bound_setjmp2.test # No TLS_FUNC/TLS_VAR in bcheck.c
7055 endif
56+ifeq (,$(filter arm64 aarch64,$(ARCH)))
57+ SKIP += 138_arm64_encoding.test
58+ SKIP += 139_arm64_errors.test
59+ SKIP += 140_arm64_extasm.test
60+endif
7161
7262 # Some tests might need arguments
7363 ARGS =
@@ -88,8 +78,8 @@ endif · 14 unmodified lines
8878
8979 # These tests run several snippets from the same file one by one
9080 60_errors_and_warnings.test : FLAGS += -dt
91−139_arm64_errors.test : FLAGS += -dt
9281 96_nodata_wanted.test : FLAGS += -dt
82+139_arm64_errors.test : FLAGS += -dt
9383
9484 # Always generate certain .expects (don't put these in the GIT),
9585 GEN-ALWAYS =
@@ -141,6 +131,7 @@ endif · 45 unmodified lines
141131 126_bound_global.test: NORUN = true
142132 128_run_atexit.test: FLAGS += -dt
143133 132_bound_test.test: FLAGS += -b
134+140_arm64_extasm.test: GEN = $(GEN-TCC)
144135
145136 # Filter source directory in warnings/errors (out-of-tree builds)
146137 FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'
win32/build-tcc.bat+66−73
@@ -5,13 +5,15 @@ · 4 unmodified lines
55 @echo off
66 setlocal
77 if (%1)==(-clean) goto :cleanup
8−set CC=gcc
8+set CC=gcc -O2 -Wall
99 set /p VERSION= < ..\VERSION
1010 set TCCDIR=
1111 set BINDIR=
1212 set DOC=no
13−set XCC=no
13+set TX=
14+set SELF=%~nx0
1415 goto :a0
16+
1517 :a2
1618 shift
1719 :a3
@@ -27,20 +29,22 @@ if (%1)==(-v) set VERSION=%~2&& goto :a2 · 9 unmodified lines
2729 if (%1)==(-i) set TCCDIR=%2&& goto :a2
2830 if (%1)==(-b) set BINDIR=%2&& goto :a2
2931 if (%1)==(-d) set DOC=yes&& goto :a3
30−if (%1)==(-x) set XCC=yes&& goto :a3
32+if (%1)==(-x) set TX=%2&& goto :a2
3133 if (%1)==() goto :p1
34+
3235 :usage
3336 echo usage: build-tcc.bat [ options ... ]
3437 echo options:
3538 echo -c prog use prog (gcc/tcc/cl) to compile tcc
3639 echo -c "prog options" use prog with options to compile tcc
37−echo -t 32/64 force 32/64 bit default target
40+echo -t target set target
41+echo -x target build tcc cross-compiler for target
3842 echo -v "version" set tcc version
3943 echo -i tccdir install tcc into tccdir
4044 echo -b bindir but install tcc.exe and libtcc.dll into bindir
4145 echo -d create tcc-doc.html too (needs makeinfo)
42−echo -x build the cross compiler too
4346 echo -clean delete all previously produced files and directories
47+echo supported targets i386 x86_64 arm64
4448 exit /B 1
4549
4650 @rem ------------------------------------------------------
@@ -65,6 +69,7 @@ exit /B 0 · 18 unmodified lines
6569 if exist %1 rmdir /Q/S %1 && %LOG% %1
6670 exit /B 0
6771
72+@rem ------------------------------------------------------
6873 :cl
6974 @echo off
7075 set CMD=cl
@@ -84,36 +89,19 @@ echo on · 13 unmodified lines
8489 @rem main program
8590
8691 :p1
87−if not %T%_==_ goto :p2
88−set T=32
89−if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=64
90−if %PROCESSOR_ARCHITEW6432%_==AMD64_ set T=64
91−:p2
92−if "%CC:~-3%"=="gcc" set CC=%CC% -O2 -s -static
93−if (%BINDIR%)==() set BINDIR=%TCCDIR%
94−
95−set D32=-DTCC_TARGET_PE -DTCC_TARGET_I386
96−set D64=-DTCC_TARGET_PE -DTCC_TARGET_X86_64
97−set P32=i386-win32
98−set P64=x86_64-win32
99−
100−if %T%==64 goto :t64
101−set D=%D32%
102−set P=%P32%
103−set DX=%D64%
104−set PX=%P64%
105−set TX=64
106−goto :p3
107−
108−:t64
109−set D=%D64%
110−set P=%P64%
111−set DX=%D32%
112−set PX=%P32%
113−set TX=32
114−goto :p3
115−
116−:p3
92+if not _%TX%_==__ set T=%TX%&&set TX=%TX%-win32-
93+if _%T%_%PROCESSOR_ARCHITECTURE%_==__x86_ set T=i386
94+if _%T%_%PROCESSOR_ARCHITECTURE%_==__ARM64_ set T=arm64
95+if _%T%_==__ set T=x86_64
96+if %T%==i386 set D=-DTCC_TARGET_PE -DTCC_TARGET_I386
97+if %T%==x86_64 set D=-DTCC_TARGET_PE -DTCC_TARGET_X86_64
98+if %T%==arm64 set D=-DTCC_TARGET_PE -DTCC_TARGET_ARM64
99+if "%D%"=="" echo %SELF%: error: unknown target '%T%'&&exit /B 1
100+
101+@if (%CC:~0,3%)==(gcc) set CC=%CC% -s -static
102+@if (%BINDIR%)==() set BINDIR=%TCCDIR%
103+
104+:git_hash
117105 git.exe --version 2>nul
118106 if not %ERRORLEVEL%==0 goto :git_done
119107 for /f %%b in ('git.exe rev-parse --abbrev-ref HEAD') do set GITHASH=%%b
@@ -125,34 +113,37 @@ if %ERRORLEVEL%==1 set GITHASH=%GITHASH%* · 5 unmodified lines
125113
126114 :config.h
127115 echo>..\config.h #define TCC_VERSION "%VERSION%"
128−if not (%GITHASH%)==() echo>> ..\config.h #define TCC_GITHASH "%GITHASH%"
129−@if not (%BINDIR%)==(%TCCDIR%) echo>> ..\config.h #define CONFIG_TCCDIR "%TCCDIR:\=/%"
130−if %TX%==64 echo>> ..\config.h #ifdef TCC_TARGET_X86_64
131−if %TX%==32 echo>> ..\config.h #ifdef TCC_TARGET_I386
132−echo>> ..\config.h #define CONFIG_TCC_CROSSPREFIX "%PX%-"
133−echo>> ..\config.h #endif
116+@if not "%GITHASH%"=="" echo>>..\config.h #define TCC_GITHASH "%GITHASH%"
117+@if not _%BINDIR%_==_%TCCDIR%_ echo>>..\config.h #define CONFIG_TCCDIR "%TCCDIR:\=/%"
118+@if not _%TX%_==__ @echo>>..\config.h #define CONFIG_TCC_CROSSPREFIX "%TX%"
134119
135120 @rem echo>> ..\config.h #define CONFIG_TCC_PREDEFS 1
136121 @rem %CC% -DC2STR ..\conftest.c -o c2str.exe
137122 @rem .\c2str.exe ../include/tccdefs.h ../tccdefs_.h
138123
139−for %%f in (*tcc.exe *tcc.dll) do @del %%f
140−
141−@if _%TCC_C%_==__ goto compiler_2parts
142−@rem if TCC_C was defined then build only tcc.exe
143−%CC% -o tcc.exe %TCC_C% %D%
144−@if errorlevel 1 goto :the_end
145−@goto :compiler_done
124+@if not _%TX%_==__ goto :tcc_cross
125+@if not _%TCC_C%_==__ goto :tcc_only
146126
147−:compiler_2parts
148127 @if _%LIBTCC_C%_==__ set LIBTCC_C=..\libtcc.c
128+@set IMPLIB=libtcc.dll
129+@if "%CC:~0,5%"=="clang" set IMPLIB=libtcc.lib
130+
149131 %CC% -o libtcc.dll -shared %LIBTCC_C% %D% -DLIBTCC_AS_DLL
150132 @if errorlevel 1 goto :the_end
151−%CC% -o tcc.exe ..\tcc.c libtcc.dll %D% -DONE_SOURCE"=0"
133+%CC% -o tcc.exe ..\tcc.c %IMPLIB% %D% -DONE_SOURCE"=0"
152134 @if errorlevel 1 goto :the_end
153−if not _%XCC%_==_yes_ goto :compiler_done
154−%CC% -o %PX%-tcc.exe ..\tcc.c %DX%
135+@goto :compiler_done
136+
137+:tcc_only
138+%CC% -o tcc.exe %TCC_C% %D%
139+@if errorlevel 1 goto :the_end
140+@goto :compiler_done
141+
142+:tcc_cross
143+%CC% -o %TX%tcc.exe ..\tcc.c %D%
155144 @if errorlevel 1 goto :the_end
145+@goto :compiler_done
146+
156147 :compiler_done
157148 @if (%EXES_ONLY%)==(yes) goto :files_done
158149
@@ -168,8 +159,7 @@ if exist libtcc.dll .\tcc -impdef libtcc.dll -o libtcc\libtcc.def · 9 unmodified lines
168159 @if errorlevel 1 goto :the_end
169160
170161 :lib
171−call :make_lib %T% || goto :the_end
172−@if exist %PX%-tcc.exe call :make_lib %TX% %PX%- || goto :the_end
162+@call :make_lib %TX% || goto :the_end
173163
174164 :tcc-doc.html
175165 @if not (%DOC%)==(yes) goto :doc-done
@@ -193,23 +183,26 @@ for %%f in (include examples libtcc doc) do @xcopy>nul /s/i/q/y %%f %TCCDIR%\%%f · 17 unmodified lines
193183 exit /B %ERRORLEVEL%
194184
195185 :make_lib
196−.\tcc -B. -m%1 -c ../lib/libtcc1.c
197−.\tcc -B. -m%1 -c lib/crt1.c
198−.\tcc -B. -m%1 -c lib/crt1w.c
199−.\tcc -B. -m%1 -c lib/wincrt1.c
200−.\tcc -B. -m%1 -c lib/wincrt1w.c
201−.\tcc -B. -m%1 -c lib/dllcrt1.c
202−.\tcc -B. -m%1 -c lib/dllmain.c
203−.\tcc -B. -m%1 -c lib/chkstk.S
204−.\tcc -B. -m%1 -c ../lib/alloca.S
205−.\tcc -B. -m%1 -c ../lib/alloca-bt.S
206−.\tcc -B. -m%1 -c ../lib/stdatomic.c
207−.\tcc -B. -m%1 -c ../lib/atomic.S
208−.\tcc -B. -m%1 -c ../lib/builtin.c
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
210−.\tcc -B. -m%1 -c ../lib/bcheck.c -o lib/%2bcheck.o -bt -I..
211−.\tcc -B. -m%1 -c ../lib/bt-exe.c -o lib/%2bt-exe.o
212−.\tcc -B. -m%1 -c ../lib/bt-log.c -o lib/%2bt-log.o
213−.\tcc -B. -m%1 -c ../lib/bt-dll.c -o lib/%2bt-dll.o
214−.\tcc -B. -m%1 -c ../lib/runmain.c -o lib/%2runmain.o
186+@set LIBTCC1=libtcc1
187+@if _%1_==_arm64_ set LIBTCC1=lib-arm64
188+.\%1tcc -B. -c ../lib/%LIBTCC1%.c
189+.\%1tcc -B. -c lib/crt1.c
190+.\%1tcc -B. -c lib/crt1w.c
191+.\%1tcc -B. -c lib/wincrt1.c
192+.\%1tcc -B. -c lib/wincrt1w.c
193+.\%1tcc -B. -c lib/dllcrt1.c
194+.\%1tcc -B. -c lib/dllmain.c
195+.\%1tcc -B. -c lib/winex.c
196+.\%1tcc -B. -c lib/chkstk.S
197+.\%1tcc -B. -c ../lib/alloca.S
198+.\%1tcc -B. -c ../lib/alloca-bt.S
199+.\%1tcc -B. -c ../lib/stdatomic.c
200+.\%1tcc -B. -c ../lib/atomic.S
201+.\%1tcc -B. -c ../lib/builtin.c
202+.\%1tcc -ar lib/%1libtcc1.a %LIBTCC1%.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o winex.o chkstk.o alloca.o alloca-bt.o stdatomic.o atomic.o builtin.o
203+.\%1tcc -B. -c ../lib/bcheck.c -o lib/%1bcheck.o -bt -I..
204+.\%1tcc -B. -c ../lib/bt-exe.c -o lib/%1bt-exe.o
205+.\%1tcc -B. -c ../lib/bt-log.c -o lib/%1bt-log.o
206+.\%1tcc -B. -c ../lib/bt-dll.c -o lib/%1bt-dll.o
207+.\%1tcc -B. -c ../lib/runmain.c -o lib/%1runmain.o
215208 exit /B %ERRORLEVEL%
win32/include/_mingw.h+1−7
@@ -70,20 +70,14 @@ · 69 unmodified lines
7070
7171 #ifdef _WIN64
7272 #define __stdcall
73−#if defined(__aarch64__) || defined(_M_ARM64) || defined(_ARM64_)
74−#ifndef _M_ARM64
73+#if defined(__aarch64__)
7574 #define _M_ARM64 1
76−#endif
77−#ifndef _ARM64_
7875 #define _ARM64_ 1
79−#endif
8076 #else
8177 #define _AMD64_ 1
8278 #define __x86_64 1
8379 #define _M_X64 100 /* Visual Studio */
8480 #define _M_AMD64 100 /* Visual Studio */
85−#define USE_MINGW_SETJMP_TWO_ARGS
86−#define mingw_getsp tinyc_getbp
8781 #endif
8882 #else
8983 #define __stdcall __attribute__((__stdcall__))
win32/include/setjmp.h+11−21
@@ -170,7 +170,6 @@ extern "C" { · 169 unmodified lines
170170 double D[8];
171171 } _JUMP_BUFFER;
172172 #else
173−
174173 #define _JBLEN 1
175174 #define _JBTYPE int
176175 #endif
@@ -179,31 +178,22 @@ extern "C" { · 2 unmodified lines
179178 #define _JMP_BUF_DEFINED
180179 #endif
181180
182− void * __cdecl __attribute__ ((__nothrow__)) mingw_getsp(void);
181+#pragma pack(pop)
183182
184−#ifdef USE_MINGW_SETJMP_TWO_ARGS
185−#ifndef _INC_SETJMPEX
186−#define setjmp(BUF) _setjmp((BUF),mingw_getsp())
187− int __cdecl __attribute__ ((__nothrow__)) _setjmp(jmp_buf _Buf,void *_Ctx);
188−#else
189−#undef setjmp
190−#define setjmp(BUF) _setjmpex((BUF),mingw_getsp())
191−#define setjmpex(BUF) _setjmpex((BUF),mingw_getsp())
192− int __cdecl __attribute__ ((__nothrow__)) _setjmpex(jmp_buf _Buf,void *_Ctx);
193−#endif
194−#else
195−#ifndef _INC_SETJMPEX
196−#define setjmp _setjmp
197−#endif
198− int __cdecl __attribute__ ((__nothrow__)) setjmp(jmp_buf _Buf);
183+#if defined __aarch64__
184+ int _setjmpex(jmp_buf _Buf, void *frame);
185+ #define setjmp(BUF) _setjmpex((BUF), (char*)__builtin_frame_address(0) + 224)
186+#elif defined __x86_64__
187+ int _setjmp(jmp_buf _Buf, void *frame);
188+ #define setjmp(BUF) _setjmp((BUF), __builtin_frame_address(0))
189+#else /* __i386__ */
190+ int _setjmp(jmp_buf _Buf);
191+ #define setjmp _setjmp
199192 #endif
200193
201− __declspec(noreturn) __attribute__ ((__nothrow__)) void __cdecl ms_longjmp(jmp_buf _Buf,int _Value)/* throw(...)*/;
202− __declspec(noreturn) __attribute__ ((__nothrow__)) void __cdecl longjmp(jmp_buf _Buf,int _Value);
194+__declspec(noreturn) void longjmp(jmp_buf _Buf,int _Value);
203195
204196 #ifdef __cplusplus
205197 }
206198 #endif
207−
208−#pragma pack(pop)
209199 #endif
win32/include/stdlib.h+15−0
@@ -207,6 +207,21 @@ extern "C" { · 206 unmodified lines
207207 #endif
208208 #endif
209209 #endif
210+
211+#if defined __aarch64__
212+/* something does not work using those from msvcrt.dll */
213+# undef __argc
214+# undef __argv
215+# undef __wargv
216+# undef _wenviron
217+# undef _environ
218+extern int __argc;
219+extern char **__argv;
220+extern wchar_t **__wargv;
221+extern char **_environ;
222+extern wchar_t **_wenviron;
223+#endif
224+
210225 #ifndef _pgmptr
211226 #ifdef _MSVCRT_
212227 extern char *_pgmptr;
win32/include/winapi/winnt.h+13−48
@@ -47,9 +47,6 @@ extern "C" { · 46 unmodified lines
4747 #endif
4848 #endif
4949
50−#if !defined(I_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(__aarch64__) && !defined(_ARM64_)
51−#define _ARM64_
52−#endif
5350
5451 #ifdef _WIN64
5552 #define MAX_NATURAL_ALIGNMENT sizeof(ULONGLONG)
@@ -832,8 +829,6 @@ typedef DWORD LCID; · 776 unmodified lines
832829 typedef ULONG_PTR KSPIN_LOCK;
833830 typedef KSPIN_LOCK *PKSPIN_LOCK;
834831
835−#if defined(_AMD64_) || defined(_ARM64_)
836−
837832 #if defined(__x86_64) && !defined(RC_INVOKED)
838833
839834 #ifdef __cplusplus
@@ -1285,7 +1280,6 @@ typedef DWORD LCID; · 445 unmodified lines
12851280 #ifdef __cplusplus
12861281 }
12871282 #endif
1288−#endif
12891283
12901284 #define EXCEPTION_READ_FAULT 0
12911285 #define EXCEPTION_WRITE_FAULT 1
@@ -1339,7 +1333,6 @@ typedef DWORD LCID; · 47 unmodified lines
13391333
13401334 #define LEGACY_SAVE_AREA_LENGTH sizeof(XMM_SAVE_AREA32)
13411335
1342−#if defined(__x86_64) || defined(_AMD64_)
13431336 typedef struct DECLSPEC_ALIGN(16) _CONTEXT {
13441337 DWORD64 P1Home;
13451338 DWORD64 P2Home;
@@ -1411,7 +1404,6 @@ typedef DWORD LCID; · 65 unmodified lines
14111404 DWORD64 LastExceptionToRip;
14121405 DWORD64 LastExceptionFromRip;
14131406 } CONTEXT,*PCONTEXT;
1414−#endif /* defined(__x86_64) || defined(_AMD64_) */
14151407
14161408 #define RUNTIME_FUNCTION_INDIRECT 0x1
14171409
@@ -1422,41 +1414,24 @@ typedef DWORD LCID; · 4 unmodified lines
14221414 } RUNTIME_FUNCTION,*PRUNTIME_FUNCTION;
14231415
14241416 typedef PRUNTIME_FUNCTION (*PGET_RUNTIME_FUNCTION_CALLBACK)(DWORD64 ControlPc,PVOID Context);
1417+ typedef DWORD (*POUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK)(HANDLE Process,PVOID TableAddress,PDWORD Entries,PRUNTIME_FUNCTION *Functions);
14251418
1426−#if defined(_ARM64_) || defined(__aarch64__)
1419+#define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME "OutOfProcessFunctionTableCallback"
1420+#endif /* defined(__x86_64) && !defined(RC_INVOKED) */
1421+
1422+#if defined(_ARM64_)
14271423
14281424 /* ARM64 Context Definition */
14291425 #define CONTEXT_ARM64 0x00400000
1430−
1431−#ifndef CONTEXT_CONTROL
14321426 #define CONTEXT_CONTROL (CONTEXT_ARM64 | 0x00000001L)
1433−#endif
1434−#ifndef CONTEXT_INTEGER
14351427 #define CONTEXT_INTEGER (CONTEXT_ARM64 | 0x00000002L)
1436−#endif
1437−#ifndef CONTEXT_FLOATING_POINT
14381428 #define CONTEXT_FLOATING_POINT (CONTEXT_ARM64 | 0x00000004L)
1439−#endif
1440−#ifndef CONTEXT_DEBUG
14411429 #define CONTEXT_DEBUG (CONTEXT_ARM64 | 0x00000008L)
1442−#endif
1443−
1444−#ifndef CONTEXT_FULL
14451430 #define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT)
1446−#endif
1447−#ifndef CONTEXT_ALL
14481431 #define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG)
1449−#endif
1450−
1451−#ifndef ARM64_MAX_BREAKPOINTS
14521432 #define ARM64_MAX_BREAKPOINTS 8
1453−#endif
1454−#ifndef ARM64_MAX_WATCHPOINTS
14551433 #define ARM64_MAX_WATCHPOINTS 2
1456−#endif
14571434
1458−#ifndef _ARM64_NT_NEON128_DECLARED
1459−#define _ARM64_NT_NEON128_DECLARED
14601435 typedef union _ARM64_NT_NEON128 {
14611436 struct {
14621437 ULONGLONG Low;
@@ -1467,10 +1442,7 @@ typedef DWORD LCID; · 4 unmodified lines
14671442 WORD H[8];
14681443 BYTE B[16];
14691444 } ARM64_NT_NEON128,*PARM64_NT_NEON128;
1470−#endif
14711445
1472−#ifndef _ARM64_CONTEXT_DECLARED
1473−#define _ARM64_CONTEXT_DECLARED
14741446 typedef struct DECLSPEC_ALIGN(16) _ARM64_NT_CONTEXT {
14751447 ULONG ContextFlags;
14761448 ULONG Cpsr;
@@ -1522,27 +1494,20 @@ typedef DWORD LCID; · 45 unmodified lines
15221494 } ARM64_NT_CONTEXT,*PARM64_NT_CONTEXT;
15231495
15241496 C_ASSERT(sizeof(ARM64_NT_CONTEXT) == 0x390);
1525− C_ASSERT(offsetof(ARM64_NT_CONTEXT, ContextFlags) == 0x000);
1526− C_ASSERT(offsetof(ARM64_NT_CONTEXT, X) == 0x008);
1527− C_ASSERT(offsetof(ARM64_NT_CONTEXT, Fp) == 0x0f0);
1528− C_ASSERT(offsetof(ARM64_NT_CONTEXT, Lr) == 0x0f8);
1529− C_ASSERT(offsetof(ARM64_NT_CONTEXT, Sp) == 0x100);
1530− C_ASSERT(offsetof(ARM64_NT_CONTEXT, Pc) == 0x108);
1531− C_ASSERT(offsetof(ARM64_NT_CONTEXT, V) == 0x110);
1532− C_ASSERT(sizeof(((ARM64_NT_CONTEXT *)0)->V[0]) == 16);
1533− C_ASSERT(offsetof(ARM64_NT_CONTEXT, Fpcr) == 0x310);
1534− C_ASSERT(offsetof(ARM64_NT_CONTEXT, Fpsr) == 0x314);
1535− C_ASSERT(offsetof(ARM64_NT_CONTEXT, Bvr) == 0x338);
1536− C_ASSERT(offsetof(ARM64_NT_CONTEXT, Wvr) == 0x380);
1537−#endif
15381497
15391498 typedef ARM64_NT_CONTEXT CONTEXT,*PCONTEXT;
15401499
1541−#endif /* _ARM64_ || __aarch64__ */
1500+ typedef struct _RUNTIME_FUNCTION {
1501+ DWORD BeginAddress;
1502+ DWORD UnwindData;
1503+ } RUNTIME_FUNCTION,*PRUNTIME_FUNCTION;
1504+
1505+ typedef PRUNTIME_FUNCTION (*PGET_RUNTIME_FUNCTION_CALLBACK)(DWORD64 ControlPc,PVOID Context);
15421506 typedef DWORD (*POUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK)(HANDLE Process,PVOID TableAddress,PDWORD Entries,PRUNTIME_FUNCTION *Functions);
15431507
1544−#define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME "OutOfProcessFunctionTableCallback"
1508+#endif /* _ARM64_ */
15451509
1510+#if (defined _ARM64_ || defined _AMD64_) && !defined RC_INVOKED
15461511 NTSYSAPI VOID __cdecl RtlRestoreContext (PCONTEXT ContextRecord,struct _EXCEPTION_RECORD *ExceptionRecord);
15471512 NTSYSAPI BOOLEAN __cdecl RtlAddFunctionTable(PRUNTIME_FUNCTION FunctionTable,DWORD EntryCount,DWORD64 BaseAddress);
15481513 NTSYSAPI BOOLEAN __cdecl RtlInstallFunctionTableCallback(DWORD64 TableIdentifier,DWORD64 BaseAddress,DWORD Length,PGET_RUNTIME_FUNCTION_CALLBACK Callback,PVOID Context,PCWSTR OutOfProcessCallbackDll);
win32/lib/chkstk.S+2−72
@@ -9,7 +9,6 @@ · 8 unmodified lines
99
1010 /* ---------------------------------------------- */
1111 #if defined(__aarch64__)
12−/* ---------------------------------------------- */
1312
1413 .globl __chkstk
1514 __chkstk:
@@ -33,68 +32,8 @@ L_chkstk_tail: · 17 unmodified lines
3332 L_chkstk_done:
3433 ret
3534
36−.globl _(tinyc_getbp)
37−_(tinyc_getbp):
38− mov x0, x29
39− ret
40−
41−.globl _(mingw_getsp)
42−_(mingw_getsp):
43− mov x0, sp
44− ret
45−
46−.globl _(__mingw_setjmp)
47−_(__mingw_setjmp):
48− /* _JUMP_BUFFER layout matches win32/include/setjmp.h for _ARM64_:
49− 0x00 Frame, 0x08 Reserved, 0x10-0x68 X19-X30, 0x70 Sp,
50− 0x78 Fpcr/Fpsr, 0x80-0xB8 D8-D15. */
51− str xzr, [x0] /* Frame = 0 */
52− stp x19, x20, [x0, 16]
53− stp x21, x22, [x0, 32]
54− stp x23, x24, [x0, 48]
55− stp x25, x26, [x0, 64]
56− stp x27, x28, [x0, 80]
57− stp x29, x30, [x0, 96]
58− mov x2, sp
59− str x2, [x0, 112] /* Sp */
60− mrs x2, FPCR
61− str w2, [x0, 120] /* Fpcr */
62− mrs x2, FPSR
63− str w2, [x0, 124] /* Fpsr */
64− stp d8, d9, [x0, 128]
65− stp d10, d11, [x0, 144]
66− stp d12, d13, [x0, 160]
67− stp d14, d15, [x0, 176]
68− mov x0, 0
69− ret
70−
71−.globl _(__mingw_longjmp)
72−_(__mingw_longjmp):
73− ldp x19, x20, [x0, 16]
74− ldp x21, x22, [x0, 32]
75− ldp x23, x24, [x0, 48]
76− ldp x25, x26, [x0, 64]
77− ldp x27, x28, [x0, 80]
78− ldp x29, x30, [x0, 96]
79− ldr x2, [x0, 112] /* Sp */
80− mov sp, x2
81− ldr w2, [x0, 120] /* Fpcr */
82− msr FPCR, x2
83− ldr w2, [x0, 124] /* Fpsr */
84− msr FPSR, x2
85− ldp d8, d9, [x0, 128]
86− ldp d10, d11, [x0, 144]
87− ldp d12, d13, [x0, 160]
88− ldp d14, d15, [x0, 176]
89− mov x0, x1
90− cbnz x0, L_longjmp_done
91− mov x0, 1
92−L_longjmp_done:
93− ret
94−
95−/* ---------------------------------------------- */
96−#elif !defined(__x86_64__)
9735 /* ---------------------------------------------- */
36+#elif defined(__i386__)
9837
9938 .globl _(__chkstk)
10039 _(__chkstk):
@@ -118,8 +57,7 @@ P0: · 17 unmodified lines
11857 jmp *4(%eax)
11958
12059 /* ---------------------------------------------- */
121−#else
122−/* ---------------------------------------------- */
60+#else /* __x86_64__ */
12361
12462 .globl _(__chkstk)
12563 _(__chkstk):
@@ -143,14 +81,6 @@ P0: · 17 unmodified lines
14381 mov (%rax),%rcx /* restore ecx */
14482 jmp *8(%rax)
14583
146−/* ---------------------------------------------- */
147−/* setjmp/longjmp support */
148−
149−.globl _(tinyc_getbp)
150−_(tinyc_getbp):
151− mov %rbp,%rax
152− ret
153−
15484 /* ---------------------------------------------- */
15585 #endif
15686 /* ---------------------------------------------- */
win32/lib/crt1.c+6−3
@@ -75,10 +75,11 @@ __attribute__((weak)) extern int __run_on_exit(); · 74 unmodified lines
7575 int _runtmain(int argc, /* as tcc passed in */ char **argv)
7676 {
7777 int ret;
78−#ifdef UNICODE
78+#if defined UNICODE || defined __aarch64__
7979 _startupinfo start_info = {0};
80−
81− __tgetmainargs(&__argc, &__targv, &_tenviron, _dowildcard, &start_info);
80+ __tgetmainargs(&__argc, &__targv, &_tenviron, 0, &start_info);
81+#endif
82+#ifdef UNICODE
8283 /* may be wrong when tcc has received wildcards (*.c) */
8384 if (argc < __argc) {
8485 __targv += __argc - argc;
@@ -93,6 +94,8 @@ int _runtmain(int argc, /* as tcc passed in */ char **argv) · 8 unmodified lines
9394 #endif
9495 run_ctors(__argc, __targv, _tenviron);
9596 ret = _tmain(__argc, __targv, _tenviron);
97+ fflush(stdout);
98+ fflush(stderr);
9699 run_dtors();
97100 __run_on_exit(ret);
98101 return ret;
win32/lib/winex.c+27−0
@@ -0,0 +1,27 @@
1+/* ------------------------------------------------------------------------- */
2+/* winex.c : extra stuff */
3+
4+#if __aarch64__
5+#include <stdlib.h>
6+/* replaces environ from arm64-msvcrt.dll which does not exist */
7+char **_environ;
8+wchar_t **_wenviron;
9+/* those do exist but have problems */
10+int __argc;
11+char **__argv;
12+wchar_t **__wargv;
13+#endif
14+
15+#if __aarch64__ || __x86_64__
16+/* MSVC x64 intrinsic */
17+void __faststorefence(void)
18+{
19+#if __aarch64__
20+ /* ARM64: Data Memory Barrier (Inner Shareable) */
21+ __asm__("dmb ish");
22+#elif __x86_64__
23+ /* x86-64: lock prefix to flush store buffer */
24+ __asm__("lock; orl $0,(%%rsp)" ::: "memory");
25+#endif
26+}
27+#endif
x86_64-gen.c+0−8
@@ -266,14 +266,6 @@ ST_FUNC void gen_addr32(int r, Sym *sym, int c) · 265 unmodified lines
266266 gen_le32(c);
267267 }
268268
269−/* output constant with relocation if 'r & VT_SYM' is true */
270−ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c)
271−{
272− if (r & VT_SYM)
273− greloca(cur_text_section, sym, ind, R_X86_64_64, c), c=0;
274− gen_le64(c);
275−}
276−
277269 /* output constant with relocation if 'r & VT_SYM' is true */
278270 ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
279271 {

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