mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 15:44:18 +08:00
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).
This commit is contained in:
parent
576cd2a923
commit
30afb50e64
63
.github/workflows/build.yml
vendored
63
.github/workflows/build.yml
vendored
@ -34,56 +34,51 @@ jobs:
|
||||
timeout-minutes: 6
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: make & test tcc (x86_64-win32)
|
||||
shell: cmd
|
||||
run: |
|
||||
echo ::group:: setup msys mingw64-gcc
|
||||
set MSYS2_PATH_TYPE=inherit
|
||||
set MSYSTEM=MINGW64
|
||||
set CHERE_INVOKING=yes
|
||||
C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-gcc"
|
||||
echo ::endgroup::
|
||||
C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k"
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: amd64
|
||||
- name: build with MSVC (x86_64-win32)
|
||||
- name: test (x86_64-win32)
|
||||
shell: cmd
|
||||
run: |
|
||||
echo ::group:: run build-tcc.bat
|
||||
cd win32
|
||||
call build-tcc.bat -t 64 -c cl
|
||||
call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=amd64
|
||||
call build-tcc.bat -c cl -t x86_64
|
||||
@echo off
|
||||
echo ::endgroup::
|
||||
.\tcc -I.. libtcc.dll -v ../tests/libtcc_test.c -o libtest.exe && .\libtest.exe
|
||||
.\tcc -I.. libtcc.dll -run ../tests/libtcc_test.c
|
||||
cd ..\tests
|
||||
call test-win32.bat all -k
|
||||
|
||||
test-i386-win32:
|
||||
runs-on: windows-2025
|
||||
timeout-minutes: 6
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: make & test tcc (i386-win32)
|
||||
shell: cmd
|
||||
run: |
|
||||
echo ::group:: setup msys mingw32-gcc
|
||||
set MSYS2_PATH_TYPE=inherit
|
||||
set MSYSTEM=MINGW32
|
||||
set CHERE_INVOKING=yes
|
||||
C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-i686-gcc"
|
||||
echo ::endgroup::
|
||||
C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k"
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: x86
|
||||
- name: build with MSVC (i386-win32)
|
||||
- name: test (i386-win32)
|
||||
shell: cmd
|
||||
run: |
|
||||
echo ::group:: run build-tcc.bat
|
||||
cd win32
|
||||
call build-tcc.bat -t 32 -c cl
|
||||
call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=x86
|
||||
call build-tcc.bat -c cl -t i386
|
||||
@echo off
|
||||
echo ::endgroup::
|
||||
.\tcc -I.. libtcc.dll -v ../tests/libtcc_test.c -o libtest.exe && .\libtest.exe
|
||||
.\tcc -I.. libtcc.dll -run ../tests/libtcc_test.c
|
||||
cd ..\tests
|
||||
call test-win32.bat -p c:\mingw32\bin all -k
|
||||
|
||||
test-arm64-win32:
|
||||
runs-on: windows-11-arm
|
||||
timeout-minutes: 6
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: test (arm64-win32)
|
||||
shell: cmd
|
||||
run: |
|
||||
echo ::group:: run build-tcc.bat
|
||||
cd win32
|
||||
call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=arm64
|
||||
call build-tcc.bat -c cl -t arm64
|
||||
@echo off
|
||||
echo ::endgroup::
|
||||
cd ..\tests
|
||||
call test-win32.bat -c clang all -k
|
||||
|
||||
test-armv7-linux:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
4
Makefile
4
Makefile
@ -31,7 +31,9 @@ ifdef CONFIG_WIN32
|
||||
LIBTCCDEF = libtcc.def
|
||||
endif
|
||||
ifneq ($(CONFIG_debug),yes)
|
||||
LDFLAGS += -s
|
||||
ifneq ($(CC_NAME),clang)
|
||||
LDFLAGS += -s
|
||||
endif
|
||||
endif
|
||||
NATIVE_TARGET = $(if $(findstring arm64,$(ARCH)),arm64-win32,$(ARCH)-win$(if $(findstring arm,$(ARCH)),ce,32))
|
||||
else
|
||||
|
||||
@ -86,11 +86,7 @@ enum {
|
||||
#define TREG_X30 30
|
||||
#define TREG_SP 31
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
#define ARM64_FREG_BASE 19
|
||||
#else
|
||||
#define ARM64_FREG_BASE 20
|
||||
#endif
|
||||
#define ARM64_FREG_LAST (ARM64_FREG_BASE + 7)
|
||||
|
||||
typedef struct Operand {
|
||||
|
||||
48
arm64-gen.c
48
arm64-gen.c
@ -579,7 +579,7 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
if (svr < VT_CONST) {
|
||||
if (IS_FREG(r) && IS_FREG(svr))
|
||||
if (svtt == VT_LDOUBLE)
|
||||
o(ARM64_MOV_V16B | fltr(r) | fltr(svr) << 5);
|
||||
o(ARM64_MOV_V16B | fltr(r) | fltr(svr) * 0x10020);
|
||||
// mov v(r).16b,v(svr).16b
|
||||
else
|
||||
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)
|
||||
return num;
|
||||
}
|
||||
}
|
||||
else if ((type->t & VT_ARRAY) && ((type->t & VT_BTYPE) != VT_PTR)) {
|
||||
else if (type->t & VT_ARRAY) { /* handle float array within struct */
|
||||
int num1;
|
||||
if (!type->ref->c)
|
||||
return num;
|
||||
@ -811,8 +811,7 @@ static int arm64_hfa_aux(CType *type, int *fsize, int num)
|
||||
|
||||
static int arm64_hfa(CType *type, unsigned *fsize)
|
||||
{
|
||||
if ((type->t & VT_BTYPE) == VT_STRUCT ||
|
||||
((type->t & VT_ARRAY) && ((type->t & VT_BTYPE) != VT_PTR))) {
|
||||
if ((type->t & VT_BTYPE) == VT_STRUCT) {
|
||||
int sz = 0;
|
||||
int n = arm64_hfa_aux(type, &sz, 0);
|
||||
if (0 < n && n <= 4) {
|
||||
@ -1037,6 +1036,13 @@ static void arm64_sub_sp(uint64_t diff)
|
||||
}
|
||||
}
|
||||
|
||||
static int gv_addr(int r)
|
||||
{
|
||||
gaddrof();
|
||||
vtop->type.t = VT_PTR;
|
||||
return gv(r);
|
||||
}
|
||||
|
||||
ST_FUNC void gfunc_call(int nb_args)
|
||||
{
|
||||
CType *return_type;
|
||||
@ -1147,9 +1153,7 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
else if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
int align, size = type_size(&vtop->type, &align);
|
||||
if (size) {
|
||||
vtop->type.t = VT_PTR;
|
||||
gaddrof();
|
||||
gv(RC_R(a[i] / 2));
|
||||
gv_addr(RC_R(a[i] / 2));
|
||||
arm64_ldrs(a[i] / 2, size);
|
||||
}
|
||||
}
|
||||
@ -1165,9 +1169,7 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz);
|
||||
if (n > 0) {
|
||||
/* HFA struct - load from memory into float registers */
|
||||
vtop->type.t = VT_PTR;
|
||||
gaddrof();
|
||||
gv(RC_R30);
|
||||
gv_addr(RC_R30);
|
||||
for (j = 0; j < n; j++)
|
||||
o(0x3d4003c0 |
|
||||
(sz & 16) << 19 | -(sz & 8) << 27 | (sz & 4) << 29 |
|
||||
@ -1186,7 +1188,7 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
if ((return_type->t & VT_BTYPE) == VT_STRUCT) {
|
||||
if (a[0] == 1) {
|
||||
// indirect return: set x8 and discard the stack value
|
||||
gv(RC_R(8));
|
||||
gv_addr(RC_R(8));
|
||||
--vtop;
|
||||
}
|
||||
else
|
||||
@ -1206,7 +1208,7 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
int bt = rt & VT_BTYPE;
|
||||
if (bt == VT_STRUCT && !(a[0] & 1)) {
|
||||
// A struct was returned in registers, so write it out:
|
||||
gv(RC_R(8));
|
||||
gv_addr(RC_R(8));
|
||||
--vtop;
|
||||
if (a[0] == 0) {
|
||||
int align, size = type_size(return_type, &align);
|
||||
@ -1271,6 +1273,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
|
||||
for (sym = func_type->ref; sym; sym = sym->next)
|
||||
++n;
|
||||
|
||||
pcs_n = n - 1;
|
||||
c = n + variadic;
|
||||
t = tcc_malloc(c * sizeof(*t));
|
||||
@ -1321,6 +1324,8 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
|
||||
arm64_func_start_offset = ind;
|
||||
o(0xa9b27bfd); // stp x29,x30,[sp,#-224]!
|
||||
o(0x910003fd); // mov x29,sp
|
||||
|
||||
for (i = 0; i < last_float; i++)
|
||||
// stp q0,q1,[sp,#16], stp q2,q3,[sp,#48]
|
||||
// stp q4,q5,[sp,#80], stp q6,q7,[sp,#112]
|
||||
@ -1368,7 +1373,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
tcc_free(a);
|
||||
tcc_free(t);
|
||||
|
||||
o(0x910003fd); // mov x29,sp
|
||||
arm64_func_sub_sp_offset = ind;
|
||||
/* In gfunc_epilog these will be replaced with stack setup code. */
|
||||
for (i = 0; i < ARM64_FUNC_STACK_SETUP_SLOTS; ++i)
|
||||
@ -1384,8 +1388,7 @@ ST_FUNC void gen_va_start(void)
|
||||
{
|
||||
int r;
|
||||
--vtop; // we don't need the "arg"
|
||||
gaddrof();
|
||||
r = intr(gv(RC_INT));
|
||||
r = intr(gv_addr(RC_INT));
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (arm64_func_va_list_stack) {
|
||||
@ -1433,13 +1436,12 @@ ST_FUNC void gen_va_arg(CType *t)
|
||||
uint32_t r0, r1;
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
int indirect = 0, slot = size + 7 & -8;
|
||||
int indirect = 0, slot = (size + 7) & -8;
|
||||
|
||||
if (size > 16)
|
||||
indirect = 1, slot = 8;
|
||||
|
||||
gaddrof();
|
||||
r0 = intr(gv(RC_INT));
|
||||
r0 = intr(gv_addr(RC_INT));
|
||||
r1 = get_reg(RC_INT);
|
||||
vtop[0].r = r1 | VT_LVAL;
|
||||
r1 = intr(r1);
|
||||
@ -1459,7 +1461,6 @@ ST_FUNC void gen_va_arg(CType *t)
|
||||
o(0x9100001e | r1 << 5 | slot << 10); // add x30,x(r1),#(slot)
|
||||
o(0xf900001e | r0 << 5); // str x30,[x(r0)] // ap += slot
|
||||
}
|
||||
|
||||
if (indirect)
|
||||
o(ARM64_LDR_X | ARM64_RN(r1) | r1); // ldr x(r1),[x(r1)]
|
||||
|
||||
@ -1469,8 +1470,7 @@ ST_FUNC void gen_va_arg(CType *t)
|
||||
if (!is_float(t->t))
|
||||
hfa = arm64_hfa(t, &fsize);
|
||||
|
||||
gaddrof();
|
||||
r0 = intr(gv(RC_INT));
|
||||
r0 = intr(gv_addr(RC_INT));
|
||||
r1 = get_reg(RC_INT);
|
||||
vtop[0].r = r1 | VT_LVAL;
|
||||
r1 = intr(r1);
|
||||
@ -1570,8 +1570,7 @@ ST_FUNC void gfunc_return(CType *func_type)
|
||||
case 0:
|
||||
if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
|
||||
int align, size = type_size(func_type, &align);
|
||||
gaddrof();
|
||||
gv(RC_R(0));
|
||||
gv_addr(RC_R(0));
|
||||
arm64_ldrs(0, size);
|
||||
}
|
||||
else
|
||||
@ -1590,8 +1589,7 @@ ST_FUNC void gfunc_return(CType *func_type)
|
||||
if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
|
||||
/* HFA struct return - load from the address on vtop into float registers */
|
||||
uint32_t j, sz, n = arm64_hfa(func_type, &sz);
|
||||
gaddrof();
|
||||
gv(RC_R(0));
|
||||
gv_addr(RC_R(0));
|
||||
for (j = 0; j < n; j++)
|
||||
o(0x3d400000 |
|
||||
(sz & 16) << 19 | -(sz & 8) << 27 | (sz & 4) << 29 |
|
||||
|
||||
@ -494,13 +494,6 @@ ST_FUNC void gen_expr32(ExprValue *pe)
|
||||
gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
||||
}
|
||||
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
ST_FUNC void gen_expr64(ExprValue *pe)
|
||||
{
|
||||
gen_addr64(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* XXX: unify with C code output ? */
|
||||
static void gen_disp32(ExprValue *pe)
|
||||
{
|
||||
|
||||
@ -41,7 +41,7 @@ ARM_O = libtcc1.o armeabi.o armflush.o $(COMMON_O)
|
||||
ARM64_O = lib-arm64.o $(COMMON_O)
|
||||
RISCV64_O = lib-arm64.o $(COMMON_O)
|
||||
COMMON_O = stdatomic.o atomic.o builtin.o alloca.o alloca-bt.o
|
||||
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
|
||||
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o winex.o
|
||||
LIN_O = dsohandle.o
|
||||
OSX_O =
|
||||
|
||||
@ -63,7 +63,7 @@ OBJ-x86_64 = $(X86_64_O) va_list.o $(LIN_O)
|
||||
OBJ-x86_64-osx = $(X86_64_O) va_list.o $(OSX_O)
|
||||
OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O)
|
||||
OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(WIN_O)
|
||||
OBJ-arm64 = $(ARM64_O) $(LIN_O)
|
||||
OBJ-arm64 = $(ARM64_O) armflush.o $(LIN_O)
|
||||
OBJ-arm64-osx = $(ARM64_O) $(OSX_O)
|
||||
OBJ-arm64-win32 = $(ARM64_O) chkstk.o $(WIN_O)
|
||||
OBJ-arm = $(ARM_O) $(LIN_O)
|
||||
|
||||
@ -4,6 +4,9 @@
|
||||
intrinsic with gcc. However tcc in order to compile
|
||||
itself needs this function */
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#if defined __arm__
|
||||
|
||||
#ifdef __TINYC__
|
||||
|
||||
/* syscall wrapper */
|
||||
@ -49,3 +52,13 @@ void __clear_cache(void *beginning, void *end)
|
||||
* However, there is no ARM asm parser in tcc so we use it for now */
|
||||
syscall(__ARM_NR_cacheflush, beginning, end, 0);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#elif defined __aarch64__
|
||||
void __clear_cache(void *beg, void *end)
|
||||
{
|
||||
__arm64_clear_cache(beg, end);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#endif
|
||||
|
||||
27
lib/bt-dll.c
27
lib/bt-dll.c
@ -34,7 +34,11 @@
|
||||
REDIR(__bound_strncmp) \
|
||||
REDIR(__bound_strcat) \
|
||||
REDIR(__bound_strchr) \
|
||||
REDIR(__bound_strdup)
|
||||
REDIR(__bound_strdup) \
|
||||
REDIR(__bound_strncat) \
|
||||
REDIR(__bound_strrchr) \
|
||||
REDIR(__bound_setjmp) \
|
||||
REDIR(__bound_longjmp)
|
||||
|
||||
#ifdef __leading_underscore
|
||||
#define _(s) "_"#s
|
||||
@ -45,11 +49,28 @@
|
||||
#define REDIR(s) void *s;
|
||||
static struct { REDIR_ALL } all_ptrs;
|
||||
#undef REDIR
|
||||
|
||||
#define REDIR(s) #s"\0"
|
||||
static const char all_names[] = REDIR_ALL;
|
||||
#undef REDIR
|
||||
#define REDIR(s) __asm__(".global " _(s) ";" _(s) ": jmp *%0" : : "m" (all_ptrs.s) );
|
||||
static void all_jmps() { REDIR_ALL }
|
||||
|
||||
#if __aarch64__
|
||||
# define REDIR(s) \
|
||||
__asm__(".global "_(s)";"_(s)":"); \
|
||||
__asm__(".int 0x58000090"); /* ldr x16, [pc, #16] */ \
|
||||
__asm__(".int 0xf9400210"); /* ldr x16, [x16] */ \
|
||||
__asm__(".int 0xd61f0200"); /* br x16 */ \
|
||||
__asm__(".int 0xd503201f"); /* nop for alignment */ \
|
||||
__asm__(".quad all_ptrs + (. - all_jmps - 16) / 24 * 8"); \
|
||||
__asm__(".type "_(s)",function\n.size "_(s)",.-"_(s));
|
||||
|
||||
__asm__(".text\n.align 8\nall_jmps:");
|
||||
REDIR_ALL
|
||||
#else
|
||||
# define REDIR(s) \
|
||||
__asm__(".global "_(s)";"_(s)":"); goto *all_ptrs.s;
|
||||
static void all_jmps() { REDIR_ALL }
|
||||
#endif
|
||||
#undef REDIR
|
||||
|
||||
void __bt_init_dll(int bcheck)
|
||||
|
||||
@ -23,13 +23,6 @@ typedef unsigned long long uint64_t;
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#if !defined __riscv && !defined __APPLE__
|
||||
void __clear_cache(void *beg, void *end)
|
||||
{
|
||||
__arm64_clear_cache(beg, end);
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
struct { uint64_t x0, x1; };
|
||||
long double f;
|
||||
|
||||
@ -107,10 +107,9 @@ union float_long {
|
||||
};
|
||||
|
||||
/* XXX: we don't support several builtin supports for now */
|
||||
#if !defined __x86_64__ && !defined __arm__ && !defined __riscv && !defined __aarch64__
|
||||
#if defined __i386__
|
||||
|
||||
/* XXX: use gcc/tcc intrinsic ? */
|
||||
#if defined __i386__
|
||||
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
||||
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \
|
||||
: "=r" ((USItype) (sh)), \
|
||||
@ -139,9 +138,6 @@ union float_long {
|
||||
: "=r" (__cbtmp) : "rm" ((USItype) (x))); \
|
||||
(count) = __cbtmp ^ 31; \
|
||||
} while (0)
|
||||
#else
|
||||
#error unsupported CPU type
|
||||
#endif
|
||||
|
||||
/* most of this code is taken from libgcc2.c from gcc */
|
||||
|
||||
@ -478,7 +474,7 @@ long long __ashldi3(long long a, int b)
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* !__x86_64__ */
|
||||
#endif /* __i386__ */
|
||||
|
||||
/* XXX: fix tcc's code generator to do this instead */
|
||||
float __floatundisf(unsigned long long a)
|
||||
@ -625,17 +621,3 @@ long long __fixxfdi (long double a1)
|
||||
return s ? ret : -ret;
|
||||
}
|
||||
#endif /* !ARM */
|
||||
|
||||
#if defined _WIN64
|
||||
/* MSVC x64 intrinsic */
|
||||
void __faststorefence(void)
|
||||
{
|
||||
#if defined(__aarch64__)
|
||||
/* ARM64: Data Memory Barrier (Inner Shareable) */
|
||||
__asm__("dmb ish");
|
||||
#else
|
||||
/* x86-64: lock prefix to flush store buffer */
|
||||
__asm__("lock; orl $0,(%%rsp)" ::: "memory");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
9
libtcc.c
9
libtcc.c
@ -124,8 +124,15 @@ static void tcc_add_systemdir(TCCState *s)
|
||||
tcc_add_library_path(s, normalize_slashes(buf));
|
||||
}
|
||||
#endif
|
||||
/* for tcc -E : On windows (depending on compiler) a FILE*
|
||||
must be created by the same module where it is used. */
|
||||
PUB_FUNC FILE *tcc_fopen(const char *f, const char *m) {
|
||||
return fopen(f, m);
|
||||
}
|
||||
PUB_FUNC int tcc_fclose(FILE *f) {
|
||||
return fclose(f);
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************************************************/
|
||||
|
||||
PUB_FUNC void tcc_enter_state(TCCState *s1)
|
||||
|
||||
12
tcc.c
12
tcc.c
@ -293,7 +293,7 @@ int main(int argc, char **argv)
|
||||
const char *first_file;
|
||||
int argc0 = argc;
|
||||
char **argv0 = argv;
|
||||
FILE *ppfp = stdout;
|
||||
FILE *ppfp = NULL;
|
||||
|
||||
redo:
|
||||
argc = argc0, argv = argv0;
|
||||
@ -335,7 +335,7 @@ redo:
|
||||
tcc_error_noabort("no input files");
|
||||
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
if (s->outfile && 0!=strcmp("-",s->outfile)) {
|
||||
ppfp = fopen(s->outfile, "wb");
|
||||
ppfp = tcc_fopen(s->outfile, "wb");
|
||||
if (!ppfp)
|
||||
tcc_error_noabort("could not write '%s'", s->outfile);
|
||||
}
|
||||
@ -355,8 +355,8 @@ redo:
|
||||
if (s->output_type == 0)
|
||||
s->output_type = TCC_OUTPUT_EXE;
|
||||
tcc_set_output_type(s, s->output_type);
|
||||
s->ppfp = ppfp;
|
||||
|
||||
if (ppfp)
|
||||
s->ppfp = ppfp;
|
||||
if ((s->output_type == TCC_OUTPUT_MEMORY
|
||||
|| s->output_type == TCC_OUTPUT_PREPROCESS)
|
||||
&& (s->dflag & 16)) { /* -dt option */
|
||||
@ -422,7 +422,7 @@ redo:
|
||||
tcc_delete(s);
|
||||
if (!done)
|
||||
goto redo;
|
||||
if (ppfp && ppfp != stdout)
|
||||
fclose(ppfp);
|
||||
if (ppfp)
|
||||
tcc_fclose(ppfp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
21
tcc.h
21
tcc.h
@ -52,6 +52,9 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||
|
||||
#ifdef _WIN32
|
||||
# define WIN32_LEAN_AND_MEAN 1
|
||||
# ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x502 /* AddVectoredExceptionHandler */
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# include <io.h> /* open, close etc. */
|
||||
# include <direct.h> /* getcwd */
|
||||
@ -86,6 +89,9 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||
# define __x86_64__ 1
|
||||
# endif
|
||||
# endif
|
||||
# if defined(_M_ARM64) && !defined(__aarch64__)
|
||||
# define __aarch64__ 1
|
||||
# endif
|
||||
# ifndef va_copy
|
||||
# define va_copy(a,b) a = b
|
||||
# endif
|
||||
@ -228,8 +234,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||
/* No ten-byte long doubles on window and macos except in
|
||||
cross-compilers made by a mingw-GCC */
|
||||
#if defined TCC_TARGET_PE \
|
||||
|| (defined TCC_TARGET_MACHO && defined TCC_TARGET_ARM64) \
|
||||
|| (defined _WIN32 && !defined __GNUC__)
|
||||
|| (defined TCC_TARGET_MACHO && defined TCC_TARGET_ARM64)
|
||||
# define TCC_USING_DOUBLE_FOR_LDOUBLE 1
|
||||
#endif
|
||||
|
||||
@ -1312,6 +1317,11 @@ PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
|
||||
PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv);
|
||||
#ifdef _WIN32
|
||||
ST_FUNC char *normalize_slashes(char *path);
|
||||
PUB_FUNC FILE *tcc_fopen(const char *f, const char *m);
|
||||
PUB_FUNC int tcc_fclose(FILE *f);
|
||||
#else
|
||||
# define tcc_fopen fopen
|
||||
# define tcc_fclose fclose
|
||||
#endif
|
||||
ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level);
|
||||
ST_FUNC char *tcc_load_text(int fd);
|
||||
@ -1683,7 +1693,6 @@ ST_FUNC void gen_increment_tcov (SValue *sv);
|
||||
|
||||
/* ------------ x86_64-gen.c ------------ */
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c);
|
||||
ST_FUNC void gen_opl(int op);
|
||||
#ifdef TCC_TARGET_PE
|
||||
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
|
||||
ST_FUNC Sym* get_asm_sym(int name, Sym *csym);
|
||||
ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
|
||||
ST_FUNC int asm_int_expr(TCCState *s1);
|
||||
/* ------------ i386-asm.c ------------ */
|
||||
ST_FUNC void gen_expr32(ExprValue *pe);
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
#if PTR_SIZE == 8
|
||||
ST_FUNC void gen_expr64(ExprValue *pe);
|
||||
#endif
|
||||
/* ------------ i386-asm.c ------------ */
|
||||
ST_FUNC void gen_expr32(ExprValue *pe);
|
||||
ST_FUNC void asm_opcode(TCCState *s1, int opcode);
|
||||
ST_FUNC int asm_parse_regvar(int t);
|
||||
ST_FUNC void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
|
||||
|
||||
41
tccasm.c
41
tccasm.c
@ -25,6 +25,26 @@
|
||||
static Section *last_text_section; /* to handle .previous asm directive */
|
||||
static int asmgoto_n;
|
||||
|
||||
static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global);
|
||||
static Sym* asm_new_label(TCCState *s1, int label, int is_local);
|
||||
static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value);
|
||||
|
||||
#if PTR_SIZE == 8
|
||||
/* output constant with relocation if 'r & VT_SYM' is true */
|
||||
ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c)
|
||||
{
|
||||
if (r & VT_SYM)
|
||||
greloca(cur_text_section, sym, ind, R_DATA_PTR, c), c=0;
|
||||
gen_le32(c);
|
||||
gen_le32(c>>32);
|
||||
}
|
||||
|
||||
ST_FUNC void gen_expr64(ExprValue *pe)
|
||||
{
|
||||
gen_addr64(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int asm_get_prefix_name(TCCState *s1, const char *prefix, unsigned int n)
|
||||
{
|
||||
char buf[64];
|
||||
@ -37,10 +57,6 @@ ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
|
||||
return asm_get_prefix_name(s1, "L..", n);
|
||||
}
|
||||
|
||||
static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global);
|
||||
static Sym* asm_new_label(TCCState *s1, int label, int is_local);
|
||||
static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value);
|
||||
|
||||
/* If a C name has an _ prepended then only asm labels that start
|
||||
with _ are representable in C, by removing the first _. ASM names
|
||||
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)
|
||||
if (esym1 && esym1->st_shndx == esym2->st_shndx
|
||||
&& esym1->st_shndx != SHN_UNDEF) {
|
||||
/* we also accept defined symbols in the same section */
|
||||
pe->v += esym1->st_value - esym2->st_value;
|
||||
pe->v += (int)(esym1->st_value - esym2->st_value);
|
||||
pe->sym = NULL;
|
||||
} else if (esym2->st_shndx == cur_text_section->sh_num) {
|
||||
/* When subtracting a defined symbol in current section
|
||||
this actually makes the value PC-relative. */
|
||||
pe->v += 0 - esym2->st_value;
|
||||
pe->v += (int)(0 - esym2->st_value);
|
||||
pe->pcrel = 1;
|
||||
e2.sym = NULL;
|
||||
} else {
|
||||
@ -543,7 +559,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
ind += size;
|
||||
break;
|
||||
case TOK_ASMDIR_quad:
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
#if PTR_SIZE == 8
|
||||
size = 8;
|
||||
goto asm_data;
|
||||
#else
|
||||
@ -592,7 +608,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
if (sec->sh_type != SHT_NOBITS) {
|
||||
if (size == 4) {
|
||||
gen_expr32(&e);
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
#if PTR_SIZE == 8
|
||||
} else if (size == 8) {
|
||||
gen_expr64(&e);
|
||||
#endif
|
||||
@ -812,6 +828,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
case TOK_ASMDIR_size:
|
||||
{
|
||||
Sym *sym;
|
||||
ElfSym *esym;
|
||||
|
||||
next();
|
||||
if (tok < TOK_IDENT)
|
||||
@ -823,8 +840,10 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
tcc_warning_c(warn_unsupported)("ignoring .size %s,*", get_tok_str(tok, NULL));
|
||||
next();
|
||||
skip(',');
|
||||
while (tok != TOK_LINEFEED && tok != ';' && tok != CH_EOF) {
|
||||
next();
|
||||
n = asm_int_expr(s1);
|
||||
esym = elfsym(sym);
|
||||
if (esym) {
|
||||
esym->st_size = n;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -952,7 +971,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
#if PTR_SIZE == 8
|
||||
/* added for compatibility with GAS */
|
||||
case TOK_ASMDIR_code64:
|
||||
next();
|
||||
|
||||
2
tcclib.h
2
tcclib.h
@ -19,6 +19,7 @@ int atoi(const char *nptr);
|
||||
long int strtol(const char *nptr, char **endptr, int base);
|
||||
unsigned long int strtoul(const char *nptr, char **endptr, int base);
|
||||
void exit(int);
|
||||
void *alloca(size_t);
|
||||
|
||||
/* stdio.h */
|
||||
typedef struct __FILE FILE;
|
||||
@ -39,6 +40,7 @@ int getchar(void);
|
||||
char *gets(char *s);
|
||||
int ungetc(int c, FILE *stream);
|
||||
int fflush(FILE *stream);
|
||||
int puts(const char *s);
|
||||
int putchar (int c);
|
||||
|
||||
int printf(const char *format, ...);
|
||||
|
||||
69
tccpe.c
69
tccpe.c
@ -1958,6 +1958,7 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
||||
for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress)
|
||||
put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym);
|
||||
}
|
||||
|
||||
#elif defined(TCC_TARGET_ARM64)
|
||||
/* ARM64 unwind codes:
|
||||
save_fplr_x: 10iiiiii - stp x29,lr,[sp,#-(i+1)*8]!
|
||||
@ -1975,10 +1976,7 @@ static Section *pe_add_unwind_info(TCCState *s1)
|
||||
s1->uw_pdata->sh_addralign = 4;
|
||||
}
|
||||
s = find_section(s1, ".xdata");
|
||||
if (NULL == s) {
|
||||
s = new_section(s1, ".xdata", SHT_PROGBITS, SHF_ALLOC);
|
||||
s->sh_addralign = 4;
|
||||
}
|
||||
s->sh_addralign = 4;
|
||||
if (0 == s1->uw_sym)
|
||||
s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0,
|
||||
text_section->sh_num, ".uw_text_base");
|
||||
@ -1992,31 +1990,22 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
||||
{
|
||||
TCCState *s1 = tcc_state;
|
||||
Section *pd, *xd;
|
||||
unsigned o, n, d, code_bytes, func_len, stack_slots;
|
||||
unsigned o, d, code_bytes, func_len;
|
||||
unsigned char *q;
|
||||
uint32_t header;
|
||||
struct {
|
||||
struct /* _RUNTIME_FUNCTION */ {
|
||||
DWORD BeginAddress;
|
||||
DWORD EndAddress;
|
||||
DWORD UnwindData;
|
||||
} *p;
|
||||
|
||||
int epilog;
|
||||
|
||||
xd = pe_add_unwind_info(s1);
|
||||
pd = s1->uw_pdata;
|
||||
|
||||
stack = (stack + 15) & ~15;
|
||||
stack_slots = stack >> 4;
|
||||
func_len = (end - start) >> 2;
|
||||
code_bytes = 0;
|
||||
if (stack_slots) {
|
||||
if (stack_slots <= 31) {
|
||||
code_bytes += 1;
|
||||
} else if (stack_slots <= 0x7ff) {
|
||||
code_bytes += 2;
|
||||
} else {
|
||||
code_bytes += 4;
|
||||
}
|
||||
}
|
||||
epilog = code_bytes;
|
||||
code_bytes += 3; /* set_fp, save_fplr_x, end */
|
||||
code_bytes = (code_bytes + 3) & ~3;
|
||||
|
||||
@ -2025,23 +2014,13 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
||||
q = section_ptr_add(xd, 4 + code_bytes);
|
||||
|
||||
/* Full ARM64 xdata header: E=1 with one epilog and no exception handler. */
|
||||
header = (func_len & 0x3ffff) | (1u << 21) | ((code_bytes >> 2) << 27);
|
||||
header = (func_len & 0x3ffff)
|
||||
| 1 << 21
|
||||
| (epilog & 0x1F) << 22
|
||||
| (code_bytes >> 2) << 27
|
||||
;
|
||||
write32le(q, header);
|
||||
q += 4;
|
||||
|
||||
if (stack_slots) {
|
||||
if (stack_slots <= 31) {
|
||||
*q++ = stack_slots; /* alloc_s */
|
||||
} else if (stack_slots <= 0x7ff) {
|
||||
*q++ = 0xC0 | (stack_slots >> 8); /* alloc_m */
|
||||
*q++ = stack_slots & 0xff;
|
||||
} else {
|
||||
*q++ = 0xE0; /* alloc_l */
|
||||
*q++ = (stack_slots >> 16) & 0xff;
|
||||
*q++ = (stack_slots >> 8) & 0xff;
|
||||
*q++ = stack_slots & 0xff;
|
||||
}
|
||||
}
|
||||
*q++ = 0xE1; /* set_fp */
|
||||
*q++ = 0x9B; /* save_fplr_x: stp x29,lr,[sp,#-224]! */
|
||||
*q++ = 0xE4; /* end */
|
||||
@ -2050,14 +2029,10 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
||||
|
||||
o = pd->data_offset;
|
||||
p = section_ptr_add(pd, sizeof *p);
|
||||
|
||||
p->BeginAddress = start;
|
||||
p->EndAddress = end;
|
||||
p->UnwindData = d;
|
||||
|
||||
for (n = o + 2 * sizeof p->BeginAddress; o < n; o += sizeof p->BeginAddress)
|
||||
put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym);
|
||||
put_elf_reloc(symtab_section, pd, n, R_XXX_RELATIVE, s1->uw_xsym);
|
||||
put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym);
|
||||
put_elf_reloc(symtab_section, pd, o + 4, R_XXX_RELATIVE, s1->uw_xsym);
|
||||
}
|
||||
#endif
|
||||
/* ------------------------------------------------------------- */
|
||||
@ -2252,20 +2227,22 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
|
||||
resolve_common_syms(s1);
|
||||
pe_set_options(s1, &pe);
|
||||
pe_check_symbols(&pe);
|
||||
|
||||
if (s1->nb_errors)
|
||||
;
|
||||
else if (filename) {
|
||||
goto done;
|
||||
if (filename) {
|
||||
pe_assign_addresses(&pe);
|
||||
relocate_syms(s1, s1->symtab, 0);
|
||||
if (s1->nb_errors)
|
||||
goto done;
|
||||
s1->pe_imagebase = pe.imagebase;
|
||||
relocate_sections(s1);
|
||||
pe.start_addr = (DWORD)
|
||||
(get_sym_addr(s1, pe.start_symbol, 1, 1) - pe.imagebase);
|
||||
if (0 == s1->nb_errors)
|
||||
pe_write(&pe);
|
||||
dynarray_reset(&pe.sec_info, &pe.sec_count);
|
||||
if (s1->nb_errors)
|
||||
goto done;
|
||||
pe_write(&pe);
|
||||
} else {
|
||||
/* -run */
|
||||
#ifdef TCC_IS_NATIVE
|
||||
pe.thunk = data_section;
|
||||
pe_build_imports(&pe);
|
||||
@ -2275,6 +2252,8 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
done:
|
||||
dynarray_reset(&pe.sec_info, &pe.sec_count);
|
||||
pe_free_imports(&pe);
|
||||
#if PE_PRINT_SECTIONS
|
||||
if (g_debug & 8)
|
||||
|
||||
2
tccrun.c
2
tccrun.c
@ -434,6 +434,8 @@ redo:
|
||||
|
||||
/* relocate symbols */
|
||||
relocate_syms(s1, s1->symtab, 1);
|
||||
if (s1->nb_errors)
|
||||
goto redo;
|
||||
/* relocate sections */
|
||||
#ifdef TCC_TARGET_PE
|
||||
s1->pe_imagebase = mem;
|
||||
|
||||
7
tcctok.h
7
tcctok.h
@ -402,12 +402,13 @@
|
||||
DEF_ASMDIR(endr)
|
||||
DEF_ASMDIR(org)
|
||||
DEF_ASMDIR(quad)
|
||||
#if defined(TCC_TARGET_I386)
|
||||
#if PTR_SIZE == 4
|
||||
DEF_ASMDIR(code16)
|
||||
DEF_ASMDIR(code32)
|
||||
#elif defined(TCC_TARGET_X86_64)
|
||||
#else
|
||||
DEF_ASMDIR(code64)
|
||||
#elif defined(TCC_TARGET_RISCV64)
|
||||
#endif
|
||||
#if defined(TCC_TARGET_RISCV64)
|
||||
DEF_ASMDIR(option)
|
||||
#endif
|
||||
DEF_ASMDIR(short)
|
||||
|
||||
@ -72,9 +72,9 @@ endif
|
||||
RUN_TCC = -run $(TOPSRC)/tcc.c $(TCCFLAGS)
|
||||
DISAS = objdump -d
|
||||
ifdef CONFIG_OSX
|
||||
DUMPTCC = (set -x; $(TOP)/tcc -vv; otool -L $(TOP)/tcc; exit 1)
|
||||
DUMPTCC = (set -x; $(TCC_LOCAL) -vv; otool -L $(TCC_LOCAL); exit 1)
|
||||
else
|
||||
DUMPTCC = (set -x; $(TOP)/tcc -vv; ldd $(TOP)/tcc; exit 1)
|
||||
DUMPTCC = (set -x; $(TCC_LOCAL) -vv; ldd $(TCC_LOCAL); exit 1)
|
||||
endif
|
||||
|
||||
all test :
|
||||
@ -82,6 +82,7 @@ all test :
|
||||
@$(TCC_LOCAL) -v
|
||||
@$(MAKE) --no-print-directory -s clean
|
||||
@$(MAKE) --no-print-directory -s -r _all
|
||||
@echo ------- ALL TESTS PASSED --------
|
||||
|
||||
_all : $(TESTS)
|
||||
|
||||
@ -109,8 +110,8 @@ libtcc_test_mt$(EXESUF): libtcc_test_mt.c
|
||||
|
||||
# test.ref - generate using cc
|
||||
test.ref: tcctest.c
|
||||
$(CC) -o tcctest.gcc $< $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer
|
||||
./tcctest.gcc > $@
|
||||
$(CC) -o tcctest.gcc$(EXESUF) $< $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer
|
||||
./tcctest.gcc$(EXESUF) > $@
|
||||
|
||||
# auto test
|
||||
test1 test1b: tcctest.c test.ref
|
||||
|
||||
@ -162,6 +162,7 @@ void *reloc_state(TCCState *s, const char *entry)
|
||||
{
|
||||
void *func;
|
||||
tcc_add_symbol(s, "add", add);
|
||||
tcc_add_symbol(s, "printf", printf);
|
||||
if (tcc_relocate(s) < 0) {
|
||||
fprintf(stderr, __FILE__ ": could not relocate tcc state.\n");
|
||||
return NULL;
|
||||
@ -337,16 +338,15 @@ int main(int argc, char **argv)
|
||||
|
||||
#else
|
||||
#include <tcclib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef __i386__
|
||||
# define LIBTCC_TEST_WINAPI __attribute__((__stdcall__))
|
||||
# else
|
||||
# define LIBTCC_TEST_WINAPI
|
||||
# ifndef _WIN64
|
||||
__declspec(stdcall)
|
||||
# endif
|
||||
void LIBTCC_TEST_WINAPI Sleep(unsigned int milliseconds);
|
||||
void Sleep(unsigned);
|
||||
# define sleep_ms Sleep
|
||||
#else
|
||||
unsigned int sleep(unsigned int seconds);
|
||||
int usleep(unsigned long);
|
||||
# define sleep_ms(x) usleep((x)*1000);
|
||||
#endif
|
||||
|
||||
int fib(n)
|
||||
@ -356,11 +356,7 @@ int fib(n)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Sleep(1000);
|
||||
#else
|
||||
sleep(1);
|
||||
#endif
|
||||
sleep_ms(333);
|
||||
printf(" %d", fib(atoi(argv[1])));
|
||||
return 0;
|
||||
}
|
||||
|
||||
164
tests/msvcrt_start.c
Normal file
164
tests/msvcrt_start.c
Normal file
@ -0,0 +1,164 @@
|
||||
/* ------------------------------------------------------------- */
|
||||
/* minimal startup with runtime linker to msvcrt */
|
||||
|
||||
#if 0
|
||||
|
||||
#define REDIR_ALL \
|
||||
REDIR(__set_app_type)\
|
||||
REDIR(__getmainargs)\
|
||||
REDIR(_controlfp)\
|
||||
REDIR(_vsnprintf)\
|
||||
REDIR(exit)\
|
||||
\
|
||||
REDIR(puts)\
|
||||
REDIR(printf)\
|
||||
REDIR(putchar)\
|
||||
REDIR(strtod)\
|
||||
REDIR(memset)\
|
||||
REDIR(strcpy)\
|
||||
REDIR(strlen)\
|
||||
REDIR(malloc)\
|
||||
REDIR(free)\
|
||||
|
||||
#if defined __i386__ && !defined __TINYC__
|
||||
# define __leading_underscore 1
|
||||
#endif
|
||||
|
||||
#ifdef __leading_underscore
|
||||
# define _(s) "_"#s
|
||||
#else
|
||||
# define _(s) #s
|
||||
#endif
|
||||
|
||||
#define REDIR(s) void *s;
|
||||
static struct { REDIR_ALL } all_ptrs;
|
||||
#undef REDIR
|
||||
|
||||
#define REDIR(s) #s"\0"
|
||||
static const char all_names[] = REDIR_ALL;
|
||||
#undef REDIR
|
||||
|
||||
#if __aarch64__
|
||||
#if defined __TINYC__
|
||||
# define ALIGN ".align 8"
|
||||
#else
|
||||
# define ALIGN ".align 3" /* .align is power of 2 on non-ELF platforms */
|
||||
#endif
|
||||
# define REDIR(s) \
|
||||
__asm__("\n"_(s)":"); \
|
||||
__asm__(".int 0x58000090"); /* ldr x16, [pc, #16] */ \
|
||||
__asm__(".int 0xf9400210"); /* ldr x16, [x16] */ \
|
||||
__asm__(".int 0xd61f0200"); /* br x16 */ \
|
||||
__asm__(".int 0xd503201f"); /* nop for alignment */ \
|
||||
__asm__(".quad all_ptrs + (. - all_jmps - 16) / 24 * 8"); \
|
||||
__asm__(".global "_(s));
|
||||
|
||||
__asm__("\t.text\n\t"ALIGN"\nall_jmps:");
|
||||
REDIR_ALL
|
||||
#else
|
||||
# define REDIR(s) \
|
||||
__asm__("\n"_(s)":");\
|
||||
__asm__("jmp *%0"::"m"(all_ptrs.s));\
|
||||
__asm__(".global "_(s));
|
||||
|
||||
static void all_jmps() { REDIR_ALL }
|
||||
#endif
|
||||
#undef REDIR
|
||||
|
||||
#if 0
|
||||
# include <windows.h>
|
||||
#else
|
||||
# if __i386__
|
||||
# define STDCALL __declspec(stdcall)
|
||||
# else
|
||||
# define STDCALL
|
||||
# endif
|
||||
# define DWORD long unsigned
|
||||
# define HMODULE void*
|
||||
# define HANDLE void*
|
||||
S TDCALL HMODULE LoadLibraryA(const char *);
|
||||
S TDCALL HMODULE GetProcAddress(HMODULE , char*);
|
||||
S TDCALL void ExitProcess(int);
|
||||
S TDCALL int WriteFile(HANDLE, const void*, DWORD, DWORD*, void*);
|
||||
S TDCALL HANDLE GetStdHandle(DWORD);
|
||||
S TDCALL int FlushFileBuffers(HANDLE);
|
||||
# define STD_ERROR_HANDLE -12
|
||||
#endif
|
||||
|
||||
static void eput(const char *s)
|
||||
{
|
||||
DWORD n_out;
|
||||
int n = 0;
|
||||
while (s[n])
|
||||
++n;
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), s, n, &n_out, 0);
|
||||
}
|
||||
|
||||
static void rt_reloc()
|
||||
{
|
||||
const char *s = all_names;
|
||||
void **p = (void**)&all_ptrs;
|
||||
void *dll = LoadLibraryA("msvcrt.dll");
|
||||
do {
|
||||
char buf[100], *d = buf;
|
||||
*p = (void*)GetProcAddress(dll, (char*)s);
|
||||
*d++ = '_'; do *d++ = *s; while (*s++);
|
||||
if (0 == *p)
|
||||
*p = (void*)GetProcAddress(dll, buf);
|
||||
if (0 == *p) {
|
||||
eput("MSVCRT_START.C: RUNTIME RELOCATION ERROR: '");
|
||||
eput(buf+1);
|
||||
eput("'\n");
|
||||
ExitProcess(-1);
|
||||
}
|
||||
++p;
|
||||
} while (*s);
|
||||
}
|
||||
|
||||
#else
|
||||
# define rt_reloc()
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv, char **env);
|
||||
void exit(int);
|
||||
void __set_app_type(int apptype);
|
||||
|
||||
typedef struct { int newmode; } _startupinfo;
|
||||
int __getmainargs(int *pargc, char ***pargv, char ***penv, int globb, _startupinfo*);
|
||||
|
||||
void _controlfp(unsigned a, unsigned b);
|
||||
#define _MCW_PC 0x00030000 // Precision Control
|
||||
#define _PC_53 0x00010000 // 53 bits
|
||||
|
||||
int __argc;
|
||||
char **__argv;
|
||||
char **environ;
|
||||
_startupinfo start_info = {0};
|
||||
|
||||
void mainCRTStartup(void)
|
||||
{
|
||||
rt_reloc();
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
_controlfp(_PC_53, _MCW_PC);
|
||||
#endif
|
||||
__set_app_type(1);
|
||||
__getmainargs(&__argc, &__argv, &environ, 0, &start_info);
|
||||
exit(main(__argc, __argv, environ));
|
||||
}
|
||||
|
||||
#include <stdarg.h>
|
||||
#define size_t __SIZE_TYPE__
|
||||
int printf(const char *, ...);
|
||||
int _vsnprintf(char *, size_t, const char *, va_list);
|
||||
|
||||
/* undefined on windows-11-arm64 */
|
||||
int vprintf(const char *format, va_list ap)
|
||||
{
|
||||
char buf[1000];
|
||||
_vsnprintf(buf, sizeof buf, format, ap);
|
||||
return printf("%s", buf);
|
||||
}
|
||||
|
||||
void __main() {} /* for gcc */
|
||||
void _pei386_runtime_relocator(void) {} /* for gcc */
|
||||
void __chkstk(unsigned n) {} /* for clang */
|
||||
@ -81,9 +81,6 @@ typedef __SIZE_TYPE__ uintptr_t;
|
||||
#include incname
|
||||
#include stringify(funnyname)
|
||||
|
||||
int puts(const char *s);
|
||||
void *alloca(size_t size);
|
||||
|
||||
int fib(int n);
|
||||
void num(int n);
|
||||
void forward_ref(void);
|
||||
@ -287,6 +284,7 @@ comment
|
||||
|
||||
printf("basefromheader %s\n", get_basefile_from_header());
|
||||
printf("base %s\n", __BASE_FILE__);
|
||||
#if !(defined _WIN32 && CC_NAME == CC_clang)
|
||||
{
|
||||
/* Some compilers (clang) prepend './' to __FILE__ from included
|
||||
files. */
|
||||
@ -295,6 +293,8 @@ comment
|
||||
fn += 2;
|
||||
printf("filefromheader %s\n", fn);
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("file %s\n", __FILE__);
|
||||
|
||||
/* Check that funnily named include was in fact included */
|
||||
@ -1095,8 +1095,10 @@ void struct_test()
|
||||
sizeof(struct aligntest2), __alignof__(struct aligntest2));
|
||||
printf("aligntest3 sizeof=%d alignof=%d\n",
|
||||
sizeof(struct aligntest3), __alignof__(struct aligntest3));
|
||||
#if !(defined _WIN32 && CC_NAME == CC_clang)
|
||||
printf("aligntest4 sizeof=%d alignof=%d\n",
|
||||
sizeof(struct aligntest4), __alignof__(struct aligntest4));
|
||||
#endif
|
||||
printf("aligntest5 sizeof=%d alignof=%d\n",
|
||||
sizeof(struct aligntest5), __alignof__(struct aligntest5));
|
||||
printf("aligntest6 sizeof=%d alignof=%d\n",
|
||||
@ -1105,8 +1107,10 @@ void struct_test()
|
||||
sizeof(struct aligntest7), __alignof__(struct aligntest7));
|
||||
printf("aligntest8 sizeof=%d alignof=%d\n",
|
||||
sizeof(struct aligntest8), __alignof__(struct aligntest8));
|
||||
#if !(defined _WIN32 && CC_NAME == CC_clang)
|
||||
printf("aligntest9 sizeof=%d alignof=%d\n",
|
||||
sizeof(struct aligntest9), __alignof__(struct aligntest9));
|
||||
#endif
|
||||
printf("aligntest10 sizeof=%d alignof=%d\n",
|
||||
sizeof(struct aligntest10), __alignof__(struct aligntest10));
|
||||
printf("altest5 sizeof=%d alignof=%d\n",
|
||||
@ -1117,7 +1121,9 @@ void struct_test()
|
||||
sizeof(altest7), __alignof__(altest7));
|
||||
|
||||
/* empty structures (GCC extension) */
|
||||
#if !(defined _WIN32 && CC_NAME == CC_clang)
|
||||
printf("sizeof(struct empty) = %d\n", sizeof(struct empty));
|
||||
#endif
|
||||
printf("alignof(struct empty) = %d\n", __alignof__(struct empty));
|
||||
|
||||
printf("Large: sizeof=%d\n", sizeof(ls));
|
||||
@ -2176,15 +2182,6 @@ float strtof(const char *nptr, char **endptr);
|
||||
LONG_DOUBLE strtold(const char *nptr, char **endptr);
|
||||
#endif
|
||||
|
||||
#if CC_NAME == CC_clang
|
||||
/* In clang 0.0/0.0 is nan and not -nan.
|
||||
Also some older clang version do v=-v
|
||||
as v = -0 - v */
|
||||
static char enable_nan_test = 0;
|
||||
#else
|
||||
static char enable_nan_test = 1;
|
||||
#endif
|
||||
|
||||
#define FTEST(prefix, typename, type, fmt)\
|
||||
void prefix ## cmp(type a, type b)\
|
||||
{\
|
||||
@ -2240,7 +2237,7 @@ void prefix ## fcast(type a)\
|
||||
b = llia;\
|
||||
printf("lltof: " fmt "\n", b);\
|
||||
b = llua;\
|
||||
printf("ulltof: " fmt "\n", b);\
|
||||
if (CC_NAME != CC_clang) printf("ulltof: " fmt "\n", b);\
|
||||
}\
|
||||
\
|
||||
float prefix ## retf(type a) { return a; }\
|
||||
@ -2300,7 +2297,7 @@ void prefix ## test(void)\
|
||||
prefix ## fcast(-2334.6);\
|
||||
prefix ## call();\
|
||||
prefix ## signed_zeros();\
|
||||
if (enable_nan_test) prefix ## nan();\
|
||||
if (CC_NAME != CC_clang) prefix ## nan();\
|
||||
}
|
||||
|
||||
FTEST(f, float, float, "%f")
|
||||
@ -2556,7 +2553,7 @@ void longlong_test(void)
|
||||
a = ia;
|
||||
b = ua;
|
||||
printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", a, b);
|
||||
printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %Lx\n",
|
||||
printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " "XLONG_LONG_FORMAT"\n",
|
||||
(long long)1,
|
||||
(long long)-2,
|
||||
1LL,
|
||||
@ -2867,12 +2864,14 @@ void stdarg_test(void)
|
||||
stdarg_for_struct(bob, bob2, bob3, bob4, bob, bob, bob.profile);
|
||||
stdarg_for_libc("stdarg_for_libc: %s %.2f %d\n", "string", 1.23, 456);
|
||||
stdarg_syntax(1, 17);
|
||||
#if !(defined _WIN32 && CC_NAME == CC_clang) /* broken clang */
|
||||
stdarg_double_struct(6,-1,pts[0],pts[1],pts[2],pts[3],pts[4],pts[5]);
|
||||
stdarg_double_struct(7,1,pts[0],-1.0,pts[1],pts[2],pts[3],pts[4],pts[5]);
|
||||
stdarg_double_struct(7,2,pts[0],pts[1],-1.0,pts[2],pts[3],pts[4],pts[5]);
|
||||
stdarg_double_struct(7,3,pts[0],pts[1],pts[2],-1.0,pts[3],pts[4],pts[5]);
|
||||
stdarg_double_struct(7,4,pts[0],pts[1],pts[2],pts[3],-1.0,pts[4],pts[5]);
|
||||
stdarg_double_struct(7,5,pts[0],pts[1],pts[2],pts[3],pts[4],-1.0,pts[5]);
|
||||
#endif
|
||||
}
|
||||
|
||||
int reltab[3] = { 1, 2, 3 };
|
||||
@ -3289,7 +3288,7 @@ void local_label_test(void)
|
||||
}
|
||||
|
||||
/* inline assembler test */
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#if (defined(__i386__) || defined(__x86_64__)) && !(defined _WIN32 && CC_NAME == CC_clang)
|
||||
|
||||
typedef __SIZE_TYPE__ word;
|
||||
|
||||
@ -3551,8 +3550,8 @@ void asm_local_label_diff (void)
|
||||
{
|
||||
printf ("asm_local_label_diff: %d %d\n", alld_stuff[0], alld_stuff[1]);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif //!__APPLE__
|
||||
#endif //!_WIN32
|
||||
|
||||
/* This checks that static local variables are available from assembler. */
|
||||
void asm_local_statics (void)
|
||||
|
||||
74
tests/test-win32.bat
Normal file
74
tests/test-win32.bat
Normal file
@ -0,0 +1,74 @@
|
||||
@echo off
|
||||
setlocal
|
||||
set CC=gcc
|
||||
set TESTS=
|
||||
if "%1"=="/?" goto :usage
|
||||
goto :p0
|
||||
|
||||
:usage
|
||||
echo usage: test-win32.bat [options...] [tests...]
|
||||
echo options:
|
||||
echo -c compiler reference compiler (gcc or clang)
|
||||
echo -p path prepend path to PATH
|
||||
echo tests tests to run (default all)
|
||||
echo requires: make, gcc/clang, and sh in the PATH
|
||||
exit /B 1
|
||||
|
||||
:p2
|
||||
shift
|
||||
:p1
|
||||
shift
|
||||
:p0
|
||||
if "%1"=="-c" set CC=%2&&goto p2
|
||||
if "%1"=="-p" set PATH=%2;%PATH%&&goto p2
|
||||
if not "%1"=="" set TESTS=%TESTS% %1&&goto p1
|
||||
if "%TESTS%"=="" set TESTS=all -k
|
||||
|
||||
set PATH=%CD%\..\win32;%PATH%
|
||||
|
||||
for /f "delims=-" %%a in ('tcc.exe -dumpmachine') do set ARCH=%%a
|
||||
set ARCH=%ARCH:aarch=arm%
|
||||
set MACH=%ARCH:i386=x86%
|
||||
set MACH=%MACH:x86_64=amd64%
|
||||
rem echo ARCH:%ARCH% MACHINE:%MACH%
|
||||
|
||||
set CRTLIB=c:/windows/system32/msvcrt.dll
|
||||
set LIBTCC=libtcc.dll
|
||||
set LGCC=-lgcc
|
||||
if %CC%==gcc goto :c2
|
||||
|
||||
set CRTLIB=msvcrt.lib
|
||||
set LIBTCC=libtcc.lib
|
||||
set LGCC=
|
||||
if exist %CRTLIB% goto :c3
|
||||
tcc -impdef msvcrt.dll
|
||||
lib >nul /def:msvcrt.def /out:%CRTLIB% /machine:%MACH%
|
||||
:c2
|
||||
if not exist %CRTLIB% echo test-win32.bat: error: %CRTLIB% not found&&exit /b 1
|
||||
:c3
|
||||
|
||||
set REF_LINK=-nostdlib msvcrt_start.c %LGCC% -lkernel32 %CRTLIB%
|
||||
set CFG_MAK=..\config.mak
|
||||
set CFG_H=..\config.h
|
||||
|
||||
echo>>%CFG_H% #define CC_NAME CC_%CC%
|
||||
echo>>%CFG_H% #define GCC_MAJOR 15
|
||||
|
||||
if exist %CFG_MAK% del %CFG_MAK%
|
||||
echo>>%CFG_MAK% CC = %CC%.exe
|
||||
echo>>%CFG_MAK% CC_NAME = %CC%
|
||||
echo>>%CFG_MAK% ARCH = %ARCH%
|
||||
echo>>%CFG_MAK% CFLAGS = -Wall -O0
|
||||
echo>>%CFG_MAK% LDFLAGS =
|
||||
echo>>%CFG_MAK% LIBSUF = .lib
|
||||
echo>>%CFG_MAK% prefix = $(TOP)/bin
|
||||
echo>>%CFG_MAK% EXESUF = .exe
|
||||
echo>>%CFG_MAK% DLLSUF = .dll
|
||||
echo>>%CFG_MAK% TARGETOS = WIN32
|
||||
echo>>%CFG_MAK% CONFIG_WIN32 = yes
|
||||
echo>>%CFG_MAK% TOPSRC = $(TOP)
|
||||
echo>>%CFG_MAK% SHELL = sh
|
||||
echo>>%CFG_MAK% test.ref: CFLAGS += %REF_LINK%
|
||||
|
||||
set GMAKE=make
|
||||
%GMAKE% TCC_LOCAL=tcc.exe LIBTCC=win32/%LIBTCC% %TESTS%
|
||||
@ -48,26 +48,16 @@ ifeq (-$(CONFIG_WIN32)-,-yes-)
|
||||
SKIP += 117_builtins.test # win32 port doesn't define __builtins
|
||||
SKIP += 124_atomic_counter.test # No pthread support
|
||||
endif
|
||||
ifneq (,$(filter arm% riscv%,$(ARCH)))
|
||||
SKIP += 85_asm-outside-function.test
|
||||
SKIP += 98_al_ax_extend.test
|
||||
SKIP += 99_fastcall.test
|
||||
SKIP += 127_asm_goto.test
|
||||
endif
|
||||
ifeq (,$(filter arm64 aarch64,$(ARCH)))
|
||||
SKIP += 138_arm64_encoding.test
|
||||
SKIP += 139_arm64_errors.test
|
||||
endif
|
||||
ifneq (,$(findstring win32,$(CROSS_TARGET)))
|
||||
SKIP += 106_versym.test
|
||||
SKIP += 114_bound_signal.test
|
||||
SKIP += 124_atomic_counter.test
|
||||
endif
|
||||
ifneq (,$(filter OpenBSD FreeBSD NetBSD,$(TARGETOS)))
|
||||
SKIP += 106_versym.test # no pthread_condattr_setpshared
|
||||
SKIP += 114_bound_signal.test # libc problem signal/fork
|
||||
SKIP += 116_bound_setjmp2.test # No TLS_FUNC/TLS_VAR in bcheck.c
|
||||
endif
|
||||
ifeq (,$(filter arm64 aarch64,$(ARCH)))
|
||||
SKIP += 138_arm64_encoding.test
|
||||
SKIP += 139_arm64_errors.test
|
||||
SKIP += 140_arm64_extasm.test
|
||||
endif
|
||||
|
||||
# Some tests might need arguments
|
||||
ARGS =
|
||||
@ -88,8 +78,8 @@ endif
|
||||
|
||||
# These tests run several snippets from the same file one by one
|
||||
60_errors_and_warnings.test : FLAGS += -dt
|
||||
139_arm64_errors.test : FLAGS += -dt
|
||||
96_nodata_wanted.test : FLAGS += -dt
|
||||
139_arm64_errors.test : FLAGS += -dt
|
||||
|
||||
# Always generate certain .expects (don't put these in the GIT),
|
||||
GEN-ALWAYS =
|
||||
@ -141,6 +131,7 @@ endif
|
||||
126_bound_global.test: NORUN = true
|
||||
128_run_atexit.test: FLAGS += -dt
|
||||
132_bound_test.test: FLAGS += -b
|
||||
140_arm64_extasm.test: GEN = $(GEN-TCC)
|
||||
|
||||
# Filter source directory in warnings/errors (out-of-tree builds)
|
||||
FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'
|
||||
|
||||
@ -5,13 +5,15 @@
|
||||
@echo off
|
||||
setlocal
|
||||
if (%1)==(-clean) goto :cleanup
|
||||
set CC=gcc
|
||||
set CC=gcc -O2 -Wall
|
||||
set /p VERSION= < ..\VERSION
|
||||
set TCCDIR=
|
||||
set BINDIR=
|
||||
set DOC=no
|
||||
set XCC=no
|
||||
set TX=
|
||||
set SELF=%~nx0
|
||||
goto :a0
|
||||
|
||||
:a2
|
||||
shift
|
||||
:a3
|
||||
@ -27,20 +29,22 @@ if (%1)==(-v) set VERSION=%~2&& goto :a2
|
||||
if (%1)==(-i) set TCCDIR=%2&& goto :a2
|
||||
if (%1)==(-b) set BINDIR=%2&& goto :a2
|
||||
if (%1)==(-d) set DOC=yes&& goto :a3
|
||||
if (%1)==(-x) set XCC=yes&& goto :a3
|
||||
if (%1)==(-x) set TX=%2&& goto :a2
|
||||
if (%1)==() goto :p1
|
||||
|
||||
:usage
|
||||
echo usage: build-tcc.bat [ options ... ]
|
||||
echo options:
|
||||
echo -c prog use prog (gcc/tcc/cl) to compile tcc
|
||||
echo -c "prog options" use prog with options to compile tcc
|
||||
echo -t 32/64 force 32/64 bit default target
|
||||
echo -t target set target
|
||||
echo -x target build tcc cross-compiler for target
|
||||
echo -v "version" set tcc version
|
||||
echo -i tccdir install tcc into tccdir
|
||||
echo -b bindir but install tcc.exe and libtcc.dll into bindir
|
||||
echo -d create tcc-doc.html too (needs makeinfo)
|
||||
echo -x build the cross compiler too
|
||||
echo -clean delete all previously produced files and directories
|
||||
echo supported targets i386 x86_64 arm64
|
||||
exit /B 1
|
||||
|
||||
@rem ------------------------------------------------------
|
||||
@ -65,6 +69,7 @@ exit /B 0
|
||||
if exist %1 rmdir /Q/S %1 && %LOG% %1
|
||||
exit /B 0
|
||||
|
||||
@rem ------------------------------------------------------
|
||||
:cl
|
||||
@echo off
|
||||
set CMD=cl
|
||||
@ -84,36 +89,19 @@ echo on
|
||||
@rem main program
|
||||
|
||||
:p1
|
||||
if not %T%_==_ goto :p2
|
||||
set T=32
|
||||
if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=64
|
||||
if %PROCESSOR_ARCHITEW6432%_==AMD64_ set T=64
|
||||
:p2
|
||||
if "%CC:~-3%"=="gcc" set CC=%CC% -O2 -s -static
|
||||
if (%BINDIR%)==() set BINDIR=%TCCDIR%
|
||||
if not _%TX%_==__ set T=%TX%&&set TX=%TX%-win32-
|
||||
if _%T%_%PROCESSOR_ARCHITECTURE%_==__x86_ set T=i386
|
||||
if _%T%_%PROCESSOR_ARCHITECTURE%_==__ARM64_ set T=arm64
|
||||
if _%T%_==__ set T=x86_64
|
||||
if %T%==i386 set D=-DTCC_TARGET_PE -DTCC_TARGET_I386
|
||||
if %T%==x86_64 set D=-DTCC_TARGET_PE -DTCC_TARGET_X86_64
|
||||
if %T%==arm64 set D=-DTCC_TARGET_PE -DTCC_TARGET_ARM64
|
||||
if "%D%"=="" echo %SELF%: error: unknown target '%T%'&&exit /B 1
|
||||
|
||||
set D32=-DTCC_TARGET_PE -DTCC_TARGET_I386
|
||||
set D64=-DTCC_TARGET_PE -DTCC_TARGET_X86_64
|
||||
set P32=i386-win32
|
||||
set P64=x86_64-win32
|
||||
@if (%CC:~0,3%)==(gcc) set CC=%CC% -s -static
|
||||
@if (%BINDIR%)==() set BINDIR=%TCCDIR%
|
||||
|
||||
if %T%==64 goto :t64
|
||||
set D=%D32%
|
||||
set P=%P32%
|
||||
set DX=%D64%
|
||||
set PX=%P64%
|
||||
set TX=64
|
||||
goto :p3
|
||||
|
||||
:t64
|
||||
set D=%D64%
|
||||
set P=%P64%
|
||||
set DX=%D32%
|
||||
set PX=%P32%
|
||||
set TX=32
|
||||
goto :p3
|
||||
|
||||
:p3
|
||||
:git_hash
|
||||
git.exe --version 2>nul
|
||||
if not %ERRORLEVEL%==0 goto :git_done
|
||||
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%*
|
||||
|
||||
:config.h
|
||||
echo>..\config.h #define TCC_VERSION "%VERSION%"
|
||||
if not (%GITHASH%)==() echo>> ..\config.h #define TCC_GITHASH "%GITHASH%"
|
||||
@if not (%BINDIR%)==(%TCCDIR%) echo>> ..\config.h #define CONFIG_TCCDIR "%TCCDIR:\=/%"
|
||||
if %TX%==64 echo>> ..\config.h #ifdef TCC_TARGET_X86_64
|
||||
if %TX%==32 echo>> ..\config.h #ifdef TCC_TARGET_I386
|
||||
echo>> ..\config.h #define CONFIG_TCC_CROSSPREFIX "%PX%-"
|
||||
echo>> ..\config.h #endif
|
||||
@if not "%GITHASH%"=="" echo>>..\config.h #define TCC_GITHASH "%GITHASH%"
|
||||
@if not _%BINDIR%_==_%TCCDIR%_ echo>>..\config.h #define CONFIG_TCCDIR "%TCCDIR:\=/%"
|
||||
@if not _%TX%_==__ @echo>>..\config.h #define CONFIG_TCC_CROSSPREFIX "%TX%"
|
||||
|
||||
@rem echo>> ..\config.h #define CONFIG_TCC_PREDEFS 1
|
||||
@rem %CC% -DC2STR ..\conftest.c -o c2str.exe
|
||||
@rem .\c2str.exe ../include/tccdefs.h ../tccdefs_.h
|
||||
|
||||
for %%f in (*tcc.exe *tcc.dll) do @del %%f
|
||||
@if not _%TX%_==__ goto :tcc_cross
|
||||
@if not _%TCC_C%_==__ goto :tcc_only
|
||||
|
||||
@if _%TCC_C%_==__ goto compiler_2parts
|
||||
@rem if TCC_C was defined then build only tcc.exe
|
||||
@if _%LIBTCC_C%_==__ set LIBTCC_C=..\libtcc.c
|
||||
@set IMPLIB=libtcc.dll
|
||||
@if "%CC:~0,5%"=="clang" set IMPLIB=libtcc.lib
|
||||
|
||||
%CC% -o libtcc.dll -shared %LIBTCC_C% %D% -DLIBTCC_AS_DLL
|
||||
@if errorlevel 1 goto :the_end
|
||||
%CC% -o tcc.exe ..\tcc.c %IMPLIB% %D% -DONE_SOURCE"=0"
|
||||
@if errorlevel 1 goto :the_end
|
||||
@goto :compiler_done
|
||||
|
||||
:tcc_only
|
||||
%CC% -o tcc.exe %TCC_C% %D%
|
||||
@if errorlevel 1 goto :the_end
|
||||
@goto :compiler_done
|
||||
|
||||
:compiler_2parts
|
||||
@if _%LIBTCC_C%_==__ set LIBTCC_C=..\libtcc.c
|
||||
%CC% -o libtcc.dll -shared %LIBTCC_C% %D% -DLIBTCC_AS_DLL
|
||||
@if errorlevel 1 goto :the_end
|
||||
%CC% -o tcc.exe ..\tcc.c libtcc.dll %D% -DONE_SOURCE"=0"
|
||||
@if errorlevel 1 goto :the_end
|
||||
if not _%XCC%_==_yes_ goto :compiler_done
|
||||
%CC% -o %PX%-tcc.exe ..\tcc.c %DX%
|
||||
:tcc_cross
|
||||
%CC% -o %TX%tcc.exe ..\tcc.c %D%
|
||||
@if errorlevel 1 goto :the_end
|
||||
@goto :compiler_done
|
||||
|
||||
:compiler_done
|
||||
@if (%EXES_ONLY%)==(yes) goto :files_done
|
||||
|
||||
@ -168,8 +159,7 @@ if exist libtcc.dll .\tcc -impdef libtcc.dll -o libtcc\libtcc.def
|
||||
@if errorlevel 1 goto :the_end
|
||||
|
||||
:lib
|
||||
call :make_lib %T% || goto :the_end
|
||||
@if exist %PX%-tcc.exe call :make_lib %TX% %PX%- || goto :the_end
|
||||
@call :make_lib %TX% || goto :the_end
|
||||
|
||||
:tcc-doc.html
|
||||
@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
|
||||
exit /B %ERRORLEVEL%
|
||||
|
||||
:make_lib
|
||||
.\tcc -B. -m%1 -c ../lib/libtcc1.c
|
||||
.\tcc -B. -m%1 -c lib/crt1.c
|
||||
.\tcc -B. -m%1 -c lib/crt1w.c
|
||||
.\tcc -B. -m%1 -c lib/wincrt1.c
|
||||
.\tcc -B. -m%1 -c lib/wincrt1w.c
|
||||
.\tcc -B. -m%1 -c lib/dllcrt1.c
|
||||
.\tcc -B. -m%1 -c lib/dllmain.c
|
||||
.\tcc -B. -m%1 -c lib/chkstk.S
|
||||
.\tcc -B. -m%1 -c ../lib/alloca.S
|
||||
.\tcc -B. -m%1 -c ../lib/alloca-bt.S
|
||||
.\tcc -B. -m%1 -c ../lib/stdatomic.c
|
||||
.\tcc -B. -m%1 -c ../lib/atomic.S
|
||||
.\tcc -B. -m%1 -c ../lib/builtin.c
|
||||
.\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
|
||||
.\tcc -B. -m%1 -c ../lib/bcheck.c -o lib/%2bcheck.o -bt -I..
|
||||
.\tcc -B. -m%1 -c ../lib/bt-exe.c -o lib/%2bt-exe.o
|
||||
.\tcc -B. -m%1 -c ../lib/bt-log.c -o lib/%2bt-log.o
|
||||
.\tcc -B. -m%1 -c ../lib/bt-dll.c -o lib/%2bt-dll.o
|
||||
.\tcc -B. -m%1 -c ../lib/runmain.c -o lib/%2runmain.o
|
||||
@set LIBTCC1=libtcc1
|
||||
@if _%1_==_arm64_ set LIBTCC1=lib-arm64
|
||||
.\%1tcc -B. -c ../lib/%LIBTCC1%.c
|
||||
.\%1tcc -B. -c lib/crt1.c
|
||||
.\%1tcc -B. -c lib/crt1w.c
|
||||
.\%1tcc -B. -c lib/wincrt1.c
|
||||
.\%1tcc -B. -c lib/wincrt1w.c
|
||||
.\%1tcc -B. -c lib/dllcrt1.c
|
||||
.\%1tcc -B. -c lib/dllmain.c
|
||||
.\%1tcc -B. -c lib/winex.c
|
||||
.\%1tcc -B. -c lib/chkstk.S
|
||||
.\%1tcc -B. -c ../lib/alloca.S
|
||||
.\%1tcc -B. -c ../lib/alloca-bt.S
|
||||
.\%1tcc -B. -c ../lib/stdatomic.c
|
||||
.\%1tcc -B. -c ../lib/atomic.S
|
||||
.\%1tcc -B. -c ../lib/builtin.c
|
||||
.\%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
|
||||
.\%1tcc -B. -c ../lib/bcheck.c -o lib/%1bcheck.o -bt -I..
|
||||
.\%1tcc -B. -c ../lib/bt-exe.c -o lib/%1bt-exe.o
|
||||
.\%1tcc -B. -c ../lib/bt-log.c -o lib/%1bt-log.o
|
||||
.\%1tcc -B. -c ../lib/bt-dll.c -o lib/%1bt-dll.o
|
||||
.\%1tcc -B. -c ../lib/runmain.c -o lib/%1runmain.o
|
||||
exit /B %ERRORLEVEL%
|
||||
|
||||
@ -70,20 +70,14 @@
|
||||
|
||||
#ifdef _WIN64
|
||||
#define __stdcall
|
||||
#if defined(__aarch64__) || defined(_M_ARM64) || defined(_ARM64_)
|
||||
#ifndef _M_ARM64
|
||||
#if defined(__aarch64__)
|
||||
#define _M_ARM64 1
|
||||
#endif
|
||||
#ifndef _ARM64_
|
||||
#define _ARM64_ 1
|
||||
#endif
|
||||
#else
|
||||
#define _AMD64_ 1
|
||||
#define __x86_64 1
|
||||
#define _M_X64 100 /* Visual Studio */
|
||||
#define _M_AMD64 100 /* Visual Studio */
|
||||
#define USE_MINGW_SETJMP_TWO_ARGS
|
||||
#define mingw_getsp tinyc_getbp
|
||||
#endif
|
||||
#else
|
||||
#define __stdcall __attribute__((__stdcall__))
|
||||
|
||||
@ -170,7 +170,6 @@ extern "C" {
|
||||
double D[8];
|
||||
} _JUMP_BUFFER;
|
||||
#else
|
||||
|
||||
#define _JBLEN 1
|
||||
#define _JBTYPE int
|
||||
#endif
|
||||
@ -179,31 +178,22 @@ extern "C" {
|
||||
#define _JMP_BUF_DEFINED
|
||||
#endif
|
||||
|
||||
void * __cdecl __attribute__ ((__nothrow__)) mingw_getsp(void);
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef USE_MINGW_SETJMP_TWO_ARGS
|
||||
#ifndef _INC_SETJMPEX
|
||||
#define setjmp(BUF) _setjmp((BUF),mingw_getsp())
|
||||
int __cdecl __attribute__ ((__nothrow__)) _setjmp(jmp_buf _Buf,void *_Ctx);
|
||||
#else
|
||||
#undef setjmp
|
||||
#define setjmp(BUF) _setjmpex((BUF),mingw_getsp())
|
||||
#define setjmpex(BUF) _setjmpex((BUF),mingw_getsp())
|
||||
int __cdecl __attribute__ ((__nothrow__)) _setjmpex(jmp_buf _Buf,void *_Ctx);
|
||||
#endif
|
||||
#else
|
||||
#ifndef _INC_SETJMPEX
|
||||
#define setjmp _setjmp
|
||||
#endif
|
||||
int __cdecl __attribute__ ((__nothrow__)) setjmp(jmp_buf _Buf);
|
||||
#if defined __aarch64__
|
||||
int _setjmpex(jmp_buf _Buf, void *frame);
|
||||
#define setjmp(BUF) _setjmpex((BUF), (char*)__builtin_frame_address(0) + 224)
|
||||
#elif defined __x86_64__
|
||||
int _setjmp(jmp_buf _Buf, void *frame);
|
||||
#define setjmp(BUF) _setjmp((BUF), __builtin_frame_address(0))
|
||||
#else /* __i386__ */
|
||||
int _setjmp(jmp_buf _Buf);
|
||||
#define setjmp _setjmp
|
||||
#endif
|
||||
|
||||
__declspec(noreturn) __attribute__ ((__nothrow__)) void __cdecl ms_longjmp(jmp_buf _Buf,int _Value)/* throw(...)*/;
|
||||
__declspec(noreturn) __attribute__ ((__nothrow__)) void __cdecl longjmp(jmp_buf _Buf,int _Value);
|
||||
__declspec(noreturn) void longjmp(jmp_buf _Buf,int _Value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
@ -207,6 +207,21 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined __aarch64__
|
||||
/* something does not work using those from msvcrt.dll */
|
||||
# undef __argc
|
||||
# undef __argv
|
||||
# undef __wargv
|
||||
# undef _wenviron
|
||||
# undef _environ
|
||||
extern int __argc;
|
||||
extern char **__argv;
|
||||
extern wchar_t **__wargv;
|
||||
extern char **_environ;
|
||||
extern wchar_t **_wenviron;
|
||||
#endif
|
||||
|
||||
#ifndef _pgmptr
|
||||
#ifdef _MSVCRT_
|
||||
extern char *_pgmptr;
|
||||
|
||||
@ -47,9 +47,6 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(I_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(__aarch64__) && !defined(_ARM64_)
|
||||
#define _ARM64_
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
#define MAX_NATURAL_ALIGNMENT sizeof(ULONGLONG)
|
||||
@ -832,8 +829,6 @@ typedef DWORD LCID;
|
||||
typedef ULONG_PTR KSPIN_LOCK;
|
||||
typedef KSPIN_LOCK *PKSPIN_LOCK;
|
||||
|
||||
#if defined(_AMD64_) || defined(_ARM64_)
|
||||
|
||||
#if defined(__x86_64) && !defined(RC_INVOKED)
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -1285,7 +1280,6 @@ typedef DWORD LCID;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define EXCEPTION_READ_FAULT 0
|
||||
#define EXCEPTION_WRITE_FAULT 1
|
||||
@ -1339,7 +1333,6 @@ typedef DWORD LCID;
|
||||
|
||||
#define LEGACY_SAVE_AREA_LENGTH sizeof(XMM_SAVE_AREA32)
|
||||
|
||||
#if defined(__x86_64) || defined(_AMD64_)
|
||||
typedef struct DECLSPEC_ALIGN(16) _CONTEXT {
|
||||
DWORD64 P1Home;
|
||||
DWORD64 P2Home;
|
||||
@ -1411,7 +1404,6 @@ typedef DWORD LCID;
|
||||
DWORD64 LastExceptionToRip;
|
||||
DWORD64 LastExceptionFromRip;
|
||||
} CONTEXT,*PCONTEXT;
|
||||
#endif /* defined(__x86_64) || defined(_AMD64_) */
|
||||
|
||||
#define RUNTIME_FUNCTION_INDIRECT 0x1
|
||||
|
||||
@ -1422,41 +1414,24 @@ typedef DWORD LCID;
|
||||
} RUNTIME_FUNCTION,*PRUNTIME_FUNCTION;
|
||||
|
||||
typedef PRUNTIME_FUNCTION (*PGET_RUNTIME_FUNCTION_CALLBACK)(DWORD64 ControlPc,PVOID Context);
|
||||
typedef DWORD (*POUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK)(HANDLE Process,PVOID TableAddress,PDWORD Entries,PRUNTIME_FUNCTION *Functions);
|
||||
|
||||
#if defined(_ARM64_) || defined(__aarch64__)
|
||||
#define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME "OutOfProcessFunctionTableCallback"
|
||||
#endif /* defined(__x86_64) && !defined(RC_INVOKED) */
|
||||
|
||||
#if defined(_ARM64_)
|
||||
|
||||
/* ARM64 Context Definition */
|
||||
#define CONTEXT_ARM64 0x00400000
|
||||
|
||||
#ifndef CONTEXT_CONTROL
|
||||
#define CONTEXT_CONTROL (CONTEXT_ARM64 | 0x00000001L)
|
||||
#endif
|
||||
#ifndef CONTEXT_INTEGER
|
||||
#define CONTEXT_INTEGER (CONTEXT_ARM64 | 0x00000002L)
|
||||
#endif
|
||||
#ifndef CONTEXT_FLOATING_POINT
|
||||
#define CONTEXT_FLOATING_POINT (CONTEXT_ARM64 | 0x00000004L)
|
||||
#endif
|
||||
#ifndef CONTEXT_DEBUG
|
||||
#define CONTEXT_DEBUG (CONTEXT_ARM64 | 0x00000008L)
|
||||
#endif
|
||||
|
||||
#ifndef CONTEXT_FULL
|
||||
#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT)
|
||||
#endif
|
||||
#ifndef CONTEXT_ALL
|
||||
#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG)
|
||||
#endif
|
||||
|
||||
#ifndef ARM64_MAX_BREAKPOINTS
|
||||
#define ARM64_MAX_BREAKPOINTS 8
|
||||
#endif
|
||||
#ifndef ARM64_MAX_WATCHPOINTS
|
||||
#define ARM64_MAX_WATCHPOINTS 2
|
||||
#endif
|
||||
|
||||
#ifndef _ARM64_NT_NEON128_DECLARED
|
||||
#define _ARM64_NT_NEON128_DECLARED
|
||||
typedef union _ARM64_NT_NEON128 {
|
||||
struct {
|
||||
ULONGLONG Low;
|
||||
@ -1467,10 +1442,7 @@ typedef DWORD LCID;
|
||||
WORD H[8];
|
||||
BYTE B[16];
|
||||
} ARM64_NT_NEON128,*PARM64_NT_NEON128;
|
||||
#endif
|
||||
|
||||
#ifndef _ARM64_CONTEXT_DECLARED
|
||||
#define _ARM64_CONTEXT_DECLARED
|
||||
typedef struct DECLSPEC_ALIGN(16) _ARM64_NT_CONTEXT {
|
||||
ULONG ContextFlags;
|
||||
ULONG Cpsr;
|
||||
@ -1522,27 +1494,20 @@ typedef DWORD LCID;
|
||||
} ARM64_NT_CONTEXT,*PARM64_NT_CONTEXT;
|
||||
|
||||
C_ASSERT(sizeof(ARM64_NT_CONTEXT) == 0x390);
|
||||
C_ASSERT(offsetof(ARM64_NT_CONTEXT, ContextFlags) == 0x000);
|
||||
C_ASSERT(offsetof(ARM64_NT_CONTEXT, X) == 0x008);
|
||||
C_ASSERT(offsetof(ARM64_NT_CONTEXT, Fp) == 0x0f0);
|
||||
C_ASSERT(offsetof(ARM64_NT_CONTEXT, Lr) == 0x0f8);
|
||||
C_ASSERT(offsetof(ARM64_NT_CONTEXT, Sp) == 0x100);
|
||||
C_ASSERT(offsetof(ARM64_NT_CONTEXT, Pc) == 0x108);
|
||||
C_ASSERT(offsetof(ARM64_NT_CONTEXT, V) == 0x110);
|
||||
C_ASSERT(sizeof(((ARM64_NT_CONTEXT *)0)->V[0]) == 16);
|
||||
C_ASSERT(offsetof(ARM64_NT_CONTEXT, Fpcr) == 0x310);
|
||||
C_ASSERT(offsetof(ARM64_NT_CONTEXT, Fpsr) == 0x314);
|
||||
C_ASSERT(offsetof(ARM64_NT_CONTEXT, Bvr) == 0x338);
|
||||
C_ASSERT(offsetof(ARM64_NT_CONTEXT, Wvr) == 0x380);
|
||||
#endif
|
||||
|
||||
typedef ARM64_NT_CONTEXT CONTEXT,*PCONTEXT;
|
||||
|
||||
#endif /* _ARM64_ || __aarch64__ */
|
||||
typedef struct _RUNTIME_FUNCTION {
|
||||
DWORD BeginAddress;
|
||||
DWORD UnwindData;
|
||||
} RUNTIME_FUNCTION,*PRUNTIME_FUNCTION;
|
||||
|
||||
typedef PRUNTIME_FUNCTION (*PGET_RUNTIME_FUNCTION_CALLBACK)(DWORD64 ControlPc,PVOID Context);
|
||||
typedef DWORD (*POUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK)(HANDLE Process,PVOID TableAddress,PDWORD Entries,PRUNTIME_FUNCTION *Functions);
|
||||
|
||||
#define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME "OutOfProcessFunctionTableCallback"
|
||||
#endif /* _ARM64_ */
|
||||
|
||||
#if (defined _ARM64_ || defined _AMD64_) && !defined RC_INVOKED
|
||||
NTSYSAPI VOID __cdecl RtlRestoreContext (PCONTEXT ContextRecord,struct _EXCEPTION_RECORD *ExceptionRecord);
|
||||
NTSYSAPI BOOLEAN __cdecl RtlAddFunctionTable(PRUNTIME_FUNCTION FunctionTable,DWORD EntryCount,DWORD64 BaseAddress);
|
||||
NTSYSAPI BOOLEAN __cdecl RtlInstallFunctionTableCallback(DWORD64 TableIdentifier,DWORD64 BaseAddress,DWORD Length,PGET_RUNTIME_FUNCTION_CALLBACK Callback,PVOID Context,PCWSTR OutOfProcessCallbackDll);
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
|
||||
/* ---------------------------------------------- */
|
||||
#if defined(__aarch64__)
|
||||
/* ---------------------------------------------- */
|
||||
|
||||
.globl __chkstk
|
||||
__chkstk:
|
||||
@ -33,68 +32,8 @@ L_chkstk_tail:
|
||||
L_chkstk_done:
|
||||
ret
|
||||
|
||||
.globl _(tinyc_getbp)
|
||||
_(tinyc_getbp):
|
||||
mov x0, x29
|
||||
ret
|
||||
|
||||
.globl _(mingw_getsp)
|
||||
_(mingw_getsp):
|
||||
mov x0, sp
|
||||
ret
|
||||
|
||||
.globl _(__mingw_setjmp)
|
||||
_(__mingw_setjmp):
|
||||
/* _JUMP_BUFFER layout matches win32/include/setjmp.h for _ARM64_:
|
||||
0x00 Frame, 0x08 Reserved, 0x10-0x68 X19-X30, 0x70 Sp,
|
||||
0x78 Fpcr/Fpsr, 0x80-0xB8 D8-D15. */
|
||||
str xzr, [x0] /* Frame = 0 */
|
||||
stp x19, x20, [x0, 16]
|
||||
stp x21, x22, [x0, 32]
|
||||
stp x23, x24, [x0, 48]
|
||||
stp x25, x26, [x0, 64]
|
||||
stp x27, x28, [x0, 80]
|
||||
stp x29, x30, [x0, 96]
|
||||
mov x2, sp
|
||||
str x2, [x0, 112] /* Sp */
|
||||
mrs x2, FPCR
|
||||
str w2, [x0, 120] /* Fpcr */
|
||||
mrs x2, FPSR
|
||||
str w2, [x0, 124] /* Fpsr */
|
||||
stp d8, d9, [x0, 128]
|
||||
stp d10, d11, [x0, 144]
|
||||
stp d12, d13, [x0, 160]
|
||||
stp d14, d15, [x0, 176]
|
||||
mov x0, 0
|
||||
ret
|
||||
|
||||
.globl _(__mingw_longjmp)
|
||||
_(__mingw_longjmp):
|
||||
ldp x19, x20, [x0, 16]
|
||||
ldp x21, x22, [x0, 32]
|
||||
ldp x23, x24, [x0, 48]
|
||||
ldp x25, x26, [x0, 64]
|
||||
ldp x27, x28, [x0, 80]
|
||||
ldp x29, x30, [x0, 96]
|
||||
ldr x2, [x0, 112] /* Sp */
|
||||
mov sp, x2
|
||||
ldr w2, [x0, 120] /* Fpcr */
|
||||
msr FPCR, x2
|
||||
ldr w2, [x0, 124] /* Fpsr */
|
||||
msr FPSR, x2
|
||||
ldp d8, d9, [x0, 128]
|
||||
ldp d10, d11, [x0, 144]
|
||||
ldp d12, d13, [x0, 160]
|
||||
ldp d14, d15, [x0, 176]
|
||||
mov x0, x1
|
||||
cbnz x0, L_longjmp_done
|
||||
mov x0, 1
|
||||
L_longjmp_done:
|
||||
ret
|
||||
|
||||
/* ---------------------------------------------- */
|
||||
#elif !defined(__x86_64__)
|
||||
/* ---------------------------------------------- */
|
||||
#elif defined(__i386__)
|
||||
|
||||
.globl _(__chkstk)
|
||||
_(__chkstk):
|
||||
@ -118,8 +57,7 @@ P0:
|
||||
jmp *4(%eax)
|
||||
|
||||
/* ---------------------------------------------- */
|
||||
#else
|
||||
/* ---------------------------------------------- */
|
||||
#else /* __x86_64__ */
|
||||
|
||||
.globl _(__chkstk)
|
||||
_(__chkstk):
|
||||
@ -143,14 +81,6 @@ P0:
|
||||
mov (%rax),%rcx /* restore ecx */
|
||||
jmp *8(%rax)
|
||||
|
||||
/* ---------------------------------------------- */
|
||||
/* setjmp/longjmp support */
|
||||
|
||||
.globl _(tinyc_getbp)
|
||||
_(tinyc_getbp):
|
||||
mov %rbp,%rax
|
||||
ret
|
||||
|
||||
/* ---------------------------------------------- */
|
||||
#endif
|
||||
/* ---------------------------------------------- */
|
||||
|
||||
@ -75,10 +75,11 @@ __attribute__((weak)) extern int __run_on_exit();
|
||||
int _runtmain(int argc, /* as tcc passed in */ char **argv)
|
||||
{
|
||||
int ret;
|
||||
#ifdef UNICODE
|
||||
#if defined UNICODE || defined __aarch64__
|
||||
_startupinfo start_info = {0};
|
||||
|
||||
__tgetmainargs(&__argc, &__targv, &_tenviron, _dowildcard, &start_info);
|
||||
__tgetmainargs(&__argc, &__targv, &_tenviron, 0, &start_info);
|
||||
#endif
|
||||
#ifdef UNICODE
|
||||
/* may be wrong when tcc has received wildcards (*.c) */
|
||||
if (argc < __argc) {
|
||||
__targv += __argc - argc;
|
||||
@ -93,6 +94,8 @@ int _runtmain(int argc, /* as tcc passed in */ char **argv)
|
||||
#endif
|
||||
run_ctors(__argc, __targv, _tenviron);
|
||||
ret = _tmain(__argc, __targv, _tenviron);
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
run_dtors();
|
||||
__run_on_exit(ret);
|
||||
return ret;
|
||||
|
||||
27
win32/lib/winex.c
Normal file
27
win32/lib/winex.c
Normal file
@ -0,0 +1,27 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* winex.c : extra stuff */
|
||||
|
||||
#if __aarch64__
|
||||
#include <stdlib.h>
|
||||
/* replaces environ from arm64-msvcrt.dll which does not exist */
|
||||
char **_environ;
|
||||
wchar_t **_wenviron;
|
||||
/* those do exist but have problems */
|
||||
int __argc;
|
||||
char **__argv;
|
||||
wchar_t **__wargv;
|
||||
#endif
|
||||
|
||||
#if __aarch64__ || __x86_64__
|
||||
/* MSVC x64 intrinsic */
|
||||
void __faststorefence(void)
|
||||
{
|
||||
#if __aarch64__
|
||||
/* ARM64: Data Memory Barrier (Inner Shareable) */
|
||||
__asm__("dmb ish");
|
||||
#elif __x86_64__
|
||||
/* x86-64: lock prefix to flush store buffer */
|
||||
__asm__("lock; orl $0,(%%rsp)" ::: "memory");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@ -266,14 +266,6 @@ ST_FUNC void gen_addr32(int r, Sym *sym, int c)
|
||||
gen_le32(c);
|
||||
}
|
||||
|
||||
/* output constant with relocation if 'r & VT_SYM' is true */
|
||||
ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c)
|
||||
{
|
||||
if (r & VT_SYM)
|
||||
greloca(cur_text_section, sym, ind, R_X86_64_64, c), c=0;
|
||||
gen_le64(c);
|
||||
}
|
||||
|
||||
/* output constant with relocation if 'r & VT_SYM' is true */
|
||||
ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user