diff --git a/Makefile b/Makefile index 22e775c..b229075 100644 --- a/Makefile +++ b/Makefile @@ -195,14 +195,14 @@ $(X)arm-gen.o : arm-asm.c # Host Tiny C Compiler tcc$(EXESUF): tcc.o $(LIBTCC) - $(CC) -o $@ $^ $(DEFINES) $(CFLAGS) $(LIBS) $(LDFLAGS) $(LINK_LIBTCC) + $(CC) -o $@ $^ $(LIBS) $(LDFLAGS) $(LINK_LIBTCC) # Cross Tiny C Compilers %-tcc$(EXESUF): FORCE @$(MAKE) --no-print-directory $@ CROSS_TARGET=$* ONE_SOURCE=$(or $(ONE_SOURCE),yes) $(CROSS_TARGET)-tcc$(EXESUF): $(TCC_FILES) - $(CC) -o $@ $^ $(DEFINES) $(CFLAGS) $(LIBS) $(LDFLAGS) + $(CC) -o $@ $^ $(LIBS) $(LDFLAGS) # profiling version tcc_p$(EXESUF): $($T_FILES) @@ -214,13 +214,14 @@ libtcc.a: $(LIBTCC_OBJ) # dynamic libtcc library libtcc.so: $(LIBTCC_OBJ) - $(CC) -shared -Wl,-soname,$@ -o $@ $^ $(CFLAGS) $(LDFLAGS) + $(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDFLAGS) libtcc.so: CFLAGS+=-fPIC +libtcc.so: LDFLAGS+=-fPIC # windows dynamic libtcc library libtcc.dll : $(LIBTCC_OBJ) - $(CC) -shared -o $@ $^ $(CFLAGS) $(LDFLAGS) + $(CC) -shared -o $@ $^ $(LDFLAGS) libtcc.def : libtcc.dll tcc$(EXESUF) ./tcc$(EXESUF) -impdef $< -o $@ @@ -229,12 +230,13 @@ libtcc.dll : DEFINES += -DLIBTCC_AS_DLL # TinyCC runtime libraries libtcc1.a : tcc$(EXESUF) FORCE - @$(MAKE) -C lib + @$(MAKE) -C lib DEFINES="$(DEF-$T)" # Cross libtcc1.a libtcc1-%.a : %-tcc$(EXESUF) FORCE - @$(MAKE) -C lib CROSS_TARGET=$* + @$(MAKE) -C lib DEFINES="$(DEF-$*)" CROSS_TARGET=$* +.PRECIOUS: libtcc1-%.a FORCE: # -------------------------------------------------------------------------- diff --git a/arm-gen.c b/arm-gen.c index 7512b61..a5dabd1 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -179,6 +179,7 @@ ST_FUNC void arm_init(struct TCCState *s) #define func_ldouble_type func_old_type ST_FUNC void arm_init(struct TCCState *s) { +#if 0 #if !defined (TCC_ARM_VFP) tcc_warning("Support for FPA is deprecated and will be removed in next" " release"); @@ -187,6 +188,7 @@ ST_FUNC void arm_init(struct TCCState *s) tcc_warning("Support for OABI is deprecated and will be removed in next" " release"); #endif +#endif } #endif diff --git a/lib/Makefile b/lib/Makefile index 00ab7dc..fe517e9 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -17,61 +17,54 @@ XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include XFLAGS = $(XFLAGS$(XCFG)) XCFG = $(or $(findstring -win,$T),-unx) -ifeq ($(X),) - BCHECK_O = bcheck.o - ifeq "$T" "arm" - XCC = $(CC) - XAR = $(AR) - XFLAGS = $(CFLAGS) -fPIC - endif +# using gcc ("make armlib-usegcc=no" to use tcc) +armlib-usegcc ?= no + +ifeq "$($(X)$(T)lib-usegcc)" "yes" + XCC = $(CC) + XAR = $(AR) + XFLAGS = $(CFLAGS) -fPIC +endif + +# only for native compiler +$(X)BCHECK_O = bcheck.o + +ifeq ($(CONFIG_musl),yes) + BCHECK_O = endif ifdef CONFIG_OSX XFLAGS += -D_ANSI_SOURCE endif -ifeq ($(CONFIG_musl),yes) - BCHECK_O = -endif - I386_O = libtcc1.o alloca86.o alloca86-bt.o X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o -ARM_O = libtcc1.o armeabi.o alloca-arm.o +ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o ARM64_O = lib-arm64.o WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o OBJ-i386 = $(I386_O) $(BCHECK_O) -TGT-i386 = -DTCC_TARGET_I386 - -OBJ-x86_64 = $(X86_64_O) $(BCHECK_O) -TGT-x86_64 = -DTCC_TARGET_X86_64 - -OBJ-x86_64-osx = $(X86_64_O) -TGT-x86_64-osx = -DTCC_TARGET_X86_64 -DTCC_TARGET_MACHO - -OBJ-arm = $(ARM_O) -TGT-arm = -DTCC_TARGET_ARM - -OBJ-arm64 = $(ARM64_O) -TGT-arm64 = -DTCC_TARGET_ARM64 - +OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) +OBJ-x86_64-osx = $(X86_64_O) va_list.o OBJ-i386-win32 = $(I386_O) chkstk.o bcheck.o $(WIN_O) -TGT-i386-win32 = -DTCC_TARGET_I386 -DTCC_TARGET_PE - OBJ-x86_64-win32 = $(X86_64_O) chkstk.o bcheck.o $(WIN_O) -TGT-x86_64-win32 = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE - +OBJ-arm64 = $(ARM64_O) +OBJ-arm = $(ARM_O) +OBJ-arm-fpa = $(ARM_O) +OBJ-arm-fpa-ld = $(ARM_O) +OBJ-arm-vfp = $(ARM_O) +OBJ-arm-eabi = $(ARM_O) +OBJ-arm-eabihf = $(ARM_O) OBJ-arm-wince = $(ARM_O) $(WIN_O) -TGT-arm-wince = -DTCC_TARGET_ARM -DTCC_TARGET_PE $(BIN) : $(patsubst %.o,$(X)%.o,$(OBJ-$T)) $(XAR) rcs $@ $^ $(X)%.o : %.c - $(XCC) -c $< -o $@ $(TGT-$T) $(XFLAGS) + $(XCC) -c $< -o $@ $(DEFINES) $(XFLAGS) $(X)%.o : %.S - $(XCC) -c $< -o $@ $(TGT-$T) $(XFLAGS) + $(XCC) -c $< -o $@ $(DEFINES) $(XFLAGS) $(X)crt1w.o : crt1.c $(X)wincrt1w.o : wincrt1.c diff --git a/lib/armflush.c b/lib/armflush.c new file mode 100644 index 0000000..eae3260 --- /dev/null +++ b/lib/armflush.c @@ -0,0 +1,58 @@ +/* armflush.c - flush the instruction cache + + __clear_cache is used in tccrun.c, It is a built-in + intrinsic with gcc. However tcc in order to compile + itself needs this function */ + +#ifdef __TINYC__ + +/* syscall wrapper */ +unsigned syscall(unsigned syscall_nr, ...); + +/* arm-tcc supports only fake asm currently */ +__asm__( + ".global syscall\n" + "syscall:\n" + ".int 0xe92d4080\n" // push {r7, lr} + ".int 0xe1a07000\n" // mov r7, r0 + ".int 0xe1a00001\n" // mov r0, r1 + ".int 0xe1a01002\n" // mov r1, r2 + ".int 0xe1a02003\n" // mov r2, r3 + ".int 0xef000000\n" // svc 0x00000000 + ".int 0xe8bd8080\n" // pop {r7, pc} + ); + +/* from unistd.h: */ +#if defined(__thumb__) || defined(__ARM_EABI__) +# define __NR_SYSCALL_BASE 0x0 +#else +# define __NR_SYSCALL_BASE 0x900000 +#endif +#define __ARM_NR_BASE (__NR_SYSCALL_BASE+0x0f0000) +#define __ARM_NR_cacheflush (__ARM_NR_BASE+2) + +#else + +#define _GNU_SOURCE +#include +#include +#include + +#endif + +/* Flushing for tccrun */ +void __clear_cache(void *beginning, void *end) +{ +/* __ARM_NR_cacheflush is kernel private and should not be used in user space. + * However, there is no ARM asm parser in tcc so we use it for now */ +#if 1 + syscall(__ARM_NR_cacheflush, beginning, end, 0); +#else + __asm__ ("push {r7}\n\t" + "mov r7, #0xf0002\n\t" + "mov r2, #0\n\t" + "swi 0\n\t" + "pop {r7}\n\t" + "ret"); +#endif +} diff --git a/lib/libtcc1.c b/lib/libtcc1.c index 9195489..0702a59 100644 --- a/lib/libtcc1.c +++ b/lib/libtcc1.c @@ -550,6 +550,13 @@ unsigned long long __fixunssfdi (float a1) return 0; } +long long __fixsfdi (float a1) +{ + long long ret; int s; + ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1); + return s ? ret : -ret; +} + unsigned long long __fixunsdfdi (double a1) { register union double_long dl1; @@ -575,6 +582,14 @@ unsigned long long __fixunsdfdi (double a1) return 0; } +long long __fixdfdi (double a1) +{ + long long ret; int s; + ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1); + return s ? ret : -ret; +} + +#ifndef TCC_TARGET_ARM unsigned long long __fixunsxfdi (long double a1) { register union ldouble_long dl1; @@ -598,121 +613,10 @@ unsigned long long __fixunsxfdi (long double a1) return 0; } -long long __fixsfdi (float a1) -{ - long long ret; int s; - ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1); - return s ? ret : -ret; -} - -long long __fixdfdi (double a1) -{ - long long ret; int s; - ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1); - return s ? ret : -ret; -} - long long __fixxfdi (long double a1) { long long ret; int s; ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1); return s ? ret : -ret; } - -#if defined(TCC_TARGET_X86_64) && !defined(_WIN64) - -#ifndef __TINYC__ -# include -# include -# include -# undef __va_start -# undef __va_arg -# undef __va_copy -# undef __va_end -#else -/* Avoid include files, they may not be available when cross compiling */ -extern void *memset(void *s, int c, __SIZE_TYPE__ n); -extern void abort(void); -#endif - -/* This should be in sync with our include/stdarg.h */ -enum __va_arg_type { - __va_gen_reg, __va_float_reg, __va_stack -}; - -/* GCC compatible definition of va_list. */ -typedef struct { - unsigned int gp_offset; - unsigned int fp_offset; - union { - unsigned int overflow_offset; - char *overflow_arg_area; - }; - char *reg_save_area; -} __va_list_struct; - -void __va_start(__va_list_struct *ap, void *fp) -{ - memset(ap, 0, sizeof(__va_list_struct)); - *ap = *(__va_list_struct *)((char *)fp - 16); - ap->overflow_arg_area = (char *)fp + ap->overflow_offset; - ap->reg_save_area = (char *)fp - 176 - 16; -} - -void *__va_arg(__va_list_struct *ap, - enum __va_arg_type arg_type, - int size, int align) -{ - size = (size + 7) & ~7; - align = (align + 7) & ~7; - switch (arg_type) { - case __va_gen_reg: - if (ap->gp_offset + size <= 48) { - ap->gp_offset += size; - return ap->reg_save_area + ap->gp_offset - size; - } - goto use_overflow_area; - - case __va_float_reg: - if (ap->fp_offset < 128 + 48) { - ap->fp_offset += 16; - return ap->reg_save_area + ap->fp_offset - 16; - } - size = 8; - goto use_overflow_area; - - case __va_stack: - use_overflow_area: - ap->overflow_arg_area += size; - ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align); - return ap->overflow_arg_area - size; - - default: /* should never happen */ - abort(); - } -} -#endif /* __x86_64__ */ - -#if defined TCC_TARGET_ARM && !defined __TINYC__ -#define _GNU_SOURCE -#include -#include -#include - -/* Flushing for tccrun */ -void __clear_cache(void *beginning, void *end) -{ -/* __ARM_NR_cacheflush is kernel private and should not be used in user space. - * However, there is no ARM asm parser in tcc so we use it for now */ -#if 1 - syscall(__ARM_NR_cacheflush, beginning, end, 0); -#else - __asm__ ("push {r7}\n\t" - "mov r7, #0xf0002\n\t" - "mov r2, #0\n\t" - "swi 0\n\t" - "pop {r7}\n\t" - "ret"); -#endif -} -#endif /* arm */ +#endif /* !ARM */ diff --git a/lib/va_list.c b/lib/va_list.c new file mode 100644 index 0000000..57dce0d --- /dev/null +++ b/lib/va_list.c @@ -0,0 +1,65 @@ +/* va_list.c - tinycc support for va_list on X86_64 */ + +#if defined TCC_TARGET_X86_64 + +/* Avoid include files, they may not be available when cross compiling */ +extern void *memset(void *s, int c, __SIZE_TYPE__ n); +extern void abort(void); + +/* This should be in sync with our include/stdarg.h */ +enum __va_arg_type { + __va_gen_reg, __va_float_reg, __va_stack +}; + +/* GCC compatible definition of va_list. */ +typedef struct { + unsigned int gp_offset; + unsigned int fp_offset; + union { + unsigned int overflow_offset; + char *overflow_arg_area; + }; + char *reg_save_area; +} __va_list_struct; + +void __va_start(__va_list_struct *ap, void *fp) +{ + memset(ap, 0, sizeof(__va_list_struct)); + *ap = *(__va_list_struct *)((char *)fp - 16); + ap->overflow_arg_area = (char *)fp + ap->overflow_offset; + ap->reg_save_area = (char *)fp - 176 - 16; +} + +void *__va_arg(__va_list_struct *ap, + enum __va_arg_type arg_type, + int size, int align) +{ + size = (size + 7) & ~7; + align = (align + 7) & ~7; + switch (arg_type) { + case __va_gen_reg: + if (ap->gp_offset + size <= 48) { + ap->gp_offset += size; + return ap->reg_save_area + ap->gp_offset - size; + } + goto use_overflow_area; + + case __va_float_reg: + if (ap->fp_offset < 128 + 48) { + ap->fp_offset += 16; + return ap->reg_save_area + ap->fp_offset - 16; + } + size = 8; + goto use_overflow_area; + + case __va_stack: + use_overflow_area: + ap->overflow_arg_area += size; + ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align); + return ap->overflow_arg_area - size; + + default: /* should never happen */ + abort(); + } +} +#endif diff --git a/tccgen.c b/tccgen.c index 424c4e0..3bcfa94 100644 --- a/tccgen.c +++ b/tccgen.c @@ -4578,9 +4578,12 @@ ST_FUNC void unary(void) #ifdef TCC_TARGET_PE case TOK_builtin_va_start: parse_builtin_params(0, "ee"); - if ((vtop->r & VT_VALMASK) != VT_LOCAL) - tcc_error("__builtin_va_start expects a local variable"); - vtop->r &= ~VT_LVAL; + r = vtop->r & VT_VALMASK; + if (r == VT_LLOCAL) + r = VT_LOCAL; + if (r != VT_LOCAL) + tcc_error("__builtin_va_start expects a local variable"); + vtop->r = r; vtop->type = char_pointer_type; vtop->c.i += 8; vstore(); @@ -6169,7 +6172,11 @@ static void init_putv(CType *type, Section *sec, unsigned long c) if (sizeof(long double) == LDOUBLE_SIZE) *(long double *)ptr = vtop->c.ld; else if (sizeof(double) == LDOUBLE_SIZE) - *(double *)ptr = vtop->c.ld; + *(double *)ptr = (double)vtop->c.ld; +#if (defined __i386__ || defined __x86_64__) && (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64) + else if (sizeof (long double) >= 10) + memcpy(memset(ptr, 0, LDOUBLE_SIZE), &vtop->c.ld, 10); +#endif else tcc_error("can't cross compile long double constants"); break; diff --git a/tests/abitest.c b/tests/abitest.c index 896e97b..580e921 100644 --- a/tests/abitest.c +++ b/tests/abitest.c @@ -637,10 +637,13 @@ int main(int argc, char **argv) { RUN_TEST(ret_longdouble_test); RUN_TEST(ret_2float_test); RUN_TEST(ret_2double_test); - /* RUN_TEST(ret_8plus2double_test); currently broken on x86_64 */ - /* RUN_TEST(ret_6plus2longlong_test); currently broken on x86_64 */ - /* RUN_TEST(ret_mixed_test); currently broken on x86_64 */ - /* RUN_TEST(ret_mixed2_test); currently broken on x86_64 */ +#if !defined __x86_64__ || defined _WIN32 + /* currently broken on x86_64 linux */ + RUN_TEST(ret_8plus2double_test); + RUN_TEST(ret_6plus2longlong_test); + RUN_TEST(ret_mixed_test); + RUN_TEST(ret_mixed2_test); +#endif RUN_TEST(ret_mixed3_test); RUN_TEST(reg_pack_test); RUN_TEST(reg_pack_longlong_test); diff --git a/tests/tcctest.c b/tests/tcctest.c index 3a4860a..bc08968 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -2044,13 +2044,6 @@ void bitfield_test(void) else printf("st1.f2 != -1\n"); -#ifndef __i386__ - /* on i386 we don't correctly support long long bit-fields. - The bitfields can straddle long long boundaries (at least with - GCC bitfield layout) and code generation isn't prepared for this - (would have to work with two words in that case). */ - /* bit sizes below must be bigger than 32 since GCC doesn't allow - long-long bitfields whose size is not bigger than int */ struct sbf2 { long long f1 : 45; long long : 2; @@ -2063,7 +2056,7 @@ void bitfield_test(void) st2.f3 = a; st2.f2++; printf("%lld %lld %lld\n", st2.f1, st2.f2, st2.f3); -#endif + #if 0 Disabled for now until further clarification re GCC compatibility struct sbf3 { @@ -2076,6 +2069,7 @@ void bitfield_test(void) } st3; printf("sizeof(st3) = %d\n", sizeof(st3)); #endif + struct sbf4 { int x : 31; char y : 2;