diff --git a/Makefile b/Makefile index e492d350..947f7574 100644 --- a/Makefile +++ b/Makefile @@ -90,8 +90,10 @@ NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP NATIVE_DEFINES_$(CONFIG_arm64) += -DTCC_TARGET_ARM64 NATIVE_DEFINES_$(CONFIG_riscv64) += -DTCC_TARGET_RISCV64 NATIVE_DEFINES_$(CONFIG_BSD) += -DTARGETOS_$(TARGETOS) +NATIVE_DEFINES_$(CONFIG_Android) += -DTARGETOS_ANDROID NATIVE_DEFINES_$(CONFIG_pie) += -DCONFIG_TCC_PIE NATIVE_DEFINES_$(CONFIG_pic) += -DCONFIG_TCC_PIC +NATIVE_DEFINES_$(CONFIG_new-dtags) += -DCONFIG_NEW_DTAGS NATIVE_DEFINES_no_$(CONFIG_bcheck) += -DCONFIG_TCC_BCHECK=0 NATIVE_DEFINES_no_$(CONFIG_backtrace) += -DCONFIG_TCC_BACKTRACE=0 NATIVE_DEFINES += $(NATIVE_DEFINES_yes) $(NATIVE_DEFINES_no_no) diff --git a/configure b/configure index cd96ea30..00879451 100755 --- a/configure +++ b/configure @@ -27,8 +27,7 @@ mandir="" infodir="" sysroot="" cross_prefix="" -test -z "$CC" && CC="gcc" -test -z "$cc" && cc="$CC" +cc="gcc" ar="ar" bigendian="no" mingw32="no" @@ -46,16 +45,20 @@ confvars= suggest="yes" gcc_major=0 gcc_minor=0 -cc_name="$cc" +cc_name="gcc" ar_set= darwin= -cpu= cpuver= dwarf= +# use CC from environment when set +test -n "$CC" && cc="$CC" + # OS specific -cpu_sys=`uname -m` +cpu=`uname -m` +cpu_sys="$cpu" targetos=`uname` +test "$(uname -o)" = "Android" && targetos=Android case $targetos in Darwin) @@ -73,6 +76,20 @@ case $targetos in DragonFly|OpenBSD|FreeBSD|NetBSD) confvars="$confvars BSD ldl=no" ;; + Android) + confvars="$confvars Android pie new-dtags" + if test -n "$TERMUX_VERSION"; then + prefix="$PREFIX" # "/data/data/com.termux/files/usr" + sysroot="$PREFIX" + test "$cpu" = "aarch64" -o "$cpu" = "x86_64" && S="64" || S="" + tcc_sysincludepaths="{B}/include:{R}/include/\\\"CONFIG_TRIPLET\\\":{R}/include" + tcc_libpaths="{B}:{R}/lib:/system/lib${S}" + tcc_crtprefix="{R}/lib" + tcc_elfinterp="/system/bin/linker${S}" + use_triplet="yes" + tcc_switches="-Wl,-rpath=$sysroot/lib,-section-alignment=0x1000" + fi + ;; *) ;; esac @@ -153,6 +170,8 @@ for opt do ;; --with-selinux) confvars="$confvars selinux" ;; + --tcc-switches=*) tcc_switches=`echo $opt | cut -d '=' -f 2-` + ;; --config-mingw32*) mingw32=$(echo "$opt=yes" | cut -d '=' -f 2) ;; --config-*) confvars="$confvars ${opt#--config-}"; suggest="no" @@ -176,9 +195,6 @@ if test "$darwin" = "yes" -a "$cpu" = "x86_64" -a "$cpu_sys" = "arm64"; then LDFLAGS="$LDFLAGS -arch $cpu" fi -# checking for cpu -test -z "$cpu" && cpu="$cpu_sys" - case "$cpu" in x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386) cpu="i386" @@ -325,6 +341,7 @@ Advanced options (experts only): --crtprefix=... specify locations of crt?.o, colon separated --elfinterp=... specify elf interpreter --triplet=... specify system library/include directory triplet + --tcc-switches=... specify implicit switches passed to tcc --config-uClibc,-musl enable system specific configurations --config-mingw32 build on windows using msys, busybox, etc. @@ -349,8 +366,8 @@ if test -z "$cross_prefix" ; then fi if test "$mingw32" = "no" ; then - if test -z "$triplet"; then - if test -n "$_triplet" -a -f "/usr/lib/$_triplet/crti.o" ; then + if test -z "$triplet" -a -n "$_triplet"; then + if test -f "/usr/lib/$_triplet/crti.o" -o -n "$use_triplet" ; then triplet="$_triplet" fi fi @@ -372,8 +389,7 @@ if test -z "$cross_prefix" ; then confvars="$confvars arm_eabihf arm_vfp" elif test "${_triplet%eabi}" != "$_triplet" ; then confvars="$confvars arm_eabi arm_vfp" - fi - if grep -s -q "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo ; then + elif grep -s -q "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo ; then confvars="$confvars arm_vfp" fi fi @@ -496,6 +512,7 @@ print_mak CONFIG_TCC_SYSINCLUDEPATHS "$tcc_sysincludepaths" print_mak CONFIG_TCC_LIBPATHS "$tcc_libpaths" print_mak CONFIG_TCC_CRTPREFIX "$tcc_crtprefix" print_mak CONFIG_TCC_ELFINTERP "$tcc_elfinterp" +print_mak CONFIG_TCC_SWITCHES "$tcc_switches" print_mak CONFIG_LDDIR "$tcc_lddir" print_mak CONFIG_TRIPLET "$triplet" print_mak TCC_CPU_VERSION "$cpuver" num diff --git a/conftest.c b/conftest.c index e8e1220a..ad7275cf 100644 --- a/conftest.c +++ b/conftest.c @@ -21,6 +21,8 @@ const char *platform_macros[] = { "__OpenBSD__", "TARGETOS_OpenBSD", "__NetBSD__", "TARGETOS_NetBSD", "__linux__", "TARGETOS_Linux", + "__ANDROID__", "TARGETOS_ANDROID", + "__SIZEOF_POINTER__", "PTR_SIZE", "__SIZEOF_LONG__", "LONG_SIZE", 0 @@ -206,15 +208,21 @@ int main(int argc, char **argv) # define TRIPLET_OS "unknown" #endif +#if defined __ANDROID__ +# define ABI_PREFIX "android" +#else +# define ABI_PREFIX "gnu" +#endif + /* Define calling convention and ABI */ #if defined (__ARM_EABI__) # if defined (__ARM_PCS_VFP) -# define TRIPLET_ABI "gnueabihf" +# define TRIPLET_ABI ABI_PREFIX"eabihf" # else -# define TRIPLET_ABI "gnueabi" +# define TRIPLET_ABI ABI_PREFIX"eabi" # endif #else -# define TRIPLET_ABI "gnu" +# define TRIPLET_ABI ABI_PREFIX #endif #if defined _WIN32 diff --git a/include/tccdefs.h b/include/tccdefs.h index 83e3c388..585dfa20 100644 --- a/include/tccdefs.h +++ b/include/tccdefs.h @@ -125,6 +125,13 @@ #define __FINITE_MATH_ONLY__ 1 #define _FORTIFY_SOURCE 0 +#elif defined __ANDROID__ + #define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD + #define __PRETTY_FUNCTION__ __FUNCTION__ + #define __has_builtin(x) 0 + #define _Nonnull + #define _Nullable + #else /* Linux */ diff --git a/lib/bcheck.c b/lib/bcheck.c index 729f0b5d..9216d0f7 100644 --- a/lib/bcheck.c +++ b/lib/bcheck.c @@ -161,7 +161,7 @@ static pthread_spinlock_t bounds_spin; #define HAVE_TLS_FUNC (1) #define HAVE_TLS_VAR (0) #endif -#ifdef TCC_MUSL +#if defined TCC_MUSL || defined __ANDROID__ # undef HAVE_CTYPE #endif #endif @@ -1174,7 +1174,8 @@ void __attribute__((destructor)) __bound_exit(void) if (inited) { #if !defined(_WIN32) && !defined(__APPLE__) && !defined TCC_MUSL && \ - !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__) + !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \ + !defined(__ANDROID__) if (print_heap) { extern void __libc_freeres (void); __libc_freeres (); diff --git a/libtcc.c b/libtcc.c index 652f5129..66baaa82 100644 --- a/libtcc.c +++ b/libtcc.c @@ -496,6 +496,8 @@ static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char * c = p[1], p += 2; if (c == 'B') cstr_cat(&str, s->tcc_lib_path, -1); + if (c == 'R') + cstr_cat(&str, CONFIG_SYSROOT, -1); if (c == 'f' && file) { /* substitute current file's dir */ const char *f = file->true_filename; @@ -810,7 +812,9 @@ LIBTCCAPI TCCState *tcc_new(void) #ifdef TCC_TARGET_ARM s->float_abi = ARM_FLOAT_ABI; #endif - +#ifdef CONFIG_NEW_DTAGS + s->enable_new_dtags = 1; +#endif s->ppfp = stdout; /* might be used in error() before preprocess_start() */ s->include_stack_ptr = s->include_stack; @@ -943,6 +947,11 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) tcc_add_crt(s, "crtbeginS.o"); else tcc_add_crt(s, "crtbegin.o"); +#elif defined TARGETOS_ANDROID + if (output_type != TCC_OUTPUT_DLL) + tcc_add_crt(s, "crtbegin_dynamic.o"); + else + tcc_add_crt(s, "crtbegin_so.o"); #else if (output_type != TCC_OUTPUT_DLL) tcc_add_crt(s, "crt1.o"); diff --git a/tcc.c b/tcc.c index 2569e2a4..fe530e39 100644 --- a/tcc.c +++ b/tcc.c @@ -281,6 +281,9 @@ int main(int argc0, char **argv0) redo: argc = argc0, argv = argv0; s = s1 = tcc_new(); +#ifdef CONFIG_TCC_SWITCHES + tcc_set_options(s, CONFIG_TCC_SWITCHES); +#endif opt = tcc_parse_args(s, &argc, &argv, 1); if (n == 0) { diff --git a/tccelf.c b/tccelf.c index e6d5bc0f..532785f3 100644 --- a/tccelf.c +++ b/tccelf.c @@ -857,7 +857,7 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve) #if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE /* dlsym() needs the undecorated name. */ void *addr = dlsym(RTLD_DEFAULT, &name[s1->leading_underscore]); -#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD +#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD || TARGETOS_ANDROID if (addr == NULL) { int i; for (i = 0; i < s1->nb_loaded_dlls; i++) @@ -1526,6 +1526,11 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) # if !TARGETOS_OpenBSD tcc_add_crt(s1, "crtn.o"); # endif +#elif TARGETOS_ANDROID + if (s1->output_type == TCC_OUTPUT_DLL) + tcc_add_crt(s1, "crtend_so.o"); + else + tcc_add_crt(s1, "crtend_android.o"); #else tcc_add_crt(s1, "crtn.o"); #endif @@ -2272,22 +2277,15 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, ehdr.e_ident[4] = ELFCLASSW; ehdr.e_ident[5] = ELFDATA2LSB; ehdr.e_ident[6] = EV_CURRENT; + #if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD; -#endif -#ifdef TCC_TARGET_ARM -#ifdef TCC_ARM_EABI - ehdr.e_ident[EI_OSABI] = 0; - ehdr.e_flags = EF_ARM_EABI_VER4; - if (file_type & (TCC_OUTPUT_EXE | TCC_OUTPUT_DLL)) - ehdr.e_flags |= EF_ARM_HASENTRY; - if (s1->float_abi == ARM_HARD_FLOAT) - ehdr.e_flags |= EF_ARM_VFP_FLOAT; - else - ehdr.e_flags |= EF_ARM_SOFT_FLOAT; -#else +#elif defined TCC_TARGET_ARM && defined TCC_ARM_EABI + ehdr.e_flags = EF_ARM_EABI_VER5; + ehdr.e_flags |= s1->float_abi == ARM_HARD_FLOAT + ? EF_ARM_VFP_FLOAT : EF_ARM_SOFT_FLOAT; +#elif defined TCC_TARGET_ARM ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM; -#endif #elif defined TCC_TARGET_RISCV64 ehdr.e_flags = EF_RISCV_FLOAT_ABI_DOUBLE; #endif diff --git a/tccgen.c b/tccgen.c index 55242099..1a3daff7 100644 --- a/tccgen.c +++ b/tccgen.c @@ -8266,7 +8266,7 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) sym = type.ref; if (sym->f.func_type == FUNC_OLD && l == VT_CONST) decl0(VT_CMP, 0, sym); -#ifdef TCC_TARGET_MACHO +#if defined TCC_TARGET_MACHO || defined TARGETOS_ANDROID if (sym->f.func_alwinl && ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))) { diff --git a/tccpp.c b/tccpp.c index 31c3a2b3..e033a29b 100644 --- a/tccpp.c +++ b/tccpp.c @@ -3713,6 +3713,9 @@ static const char * const target_os_defs = # else "__linux__\0" "__linux\0" +# if TARGETOS_ANDROID + "__ANDROID__\0" +# endif # endif "__unix__\0" "__unix\0" @@ -3724,17 +3727,22 @@ static void putdef(CString *cs, const char *p) cstr_printf(cs, "#define %s%s\n", p, &" 1"[!!strchr(p, ' ')*2]); } +static void putdefs(CString *cs, const char *p) +{ + while (*p) + putdef(cs, p), p = strchr(p, 0) + 1; +} + static void tcc_predefs(TCCState *s1, CString *cs, int is_asm) { int a, b, c; - const char *defs[] = { target_machine_defs, target_os_defs, NULL }; - const char *p; sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c); cstr_printf(cs, "#define __TINYC__ %d\n", a*10000 + b*100 + c); - for (a = 0; defs[a]; ++a) - for (p = defs[a]; *p; p = strchr(p, 0) + 1) - putdef(cs, p); + + putdefs(cs, target_machine_defs); + putdefs(cs, target_os_defs); + #ifdef TCC_TARGET_ARM if (s1->float_abi == ARM_HARD_FLOAT) putdef(cs, "__ARM_PCS_VFP"); diff --git a/tccrun.c b/tccrun.c index 40326495..826e52ca 100644 --- a/tccrun.c +++ b/tccrun.c @@ -390,7 +390,7 @@ static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned lon tcc_error("mprotect failed: did you mean to configure --with-selinux?"); /* XXX: BSD sometimes dump core with bad system call */ -# if (TCC_TARGET_ARM && !TARGETOS_BSD) || TCC_TARGET_ARM64 +# if (defined TCC_TARGET_ARM && !TARGETOS_BSD) || defined TCC_TARGET_ARM64 if (mode == 0 || mode == 3) { void __clear_cache(void *beginning, void *end); __clear_cache(ptr, (char *)ptr + length); diff --git a/tests/Makefile b/tests/Makefile index aec40544..2405e954 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -35,8 +35,8 @@ endif ifeq (,$(filter arm64 i386 x86_64,$(ARCH))) TESTS := $(filter-out vla_test-run,$(TESTS)) endif -ifeq ($(CONFIG_arm_eabi),yes) - TESTS := $(filter-out test3,$(TESTS)) +ifeq (-$(CONFIG_arm_eabi)-$(CONFIG_arm_vfp)-,-yes--) + TESTS := $(filter-out test3 test1b,$(TESTS)) endif ifeq (,$(filter i386 x86_64,$(ARCH))) TESTS := $(filter-out asm-c-connect-test,$(TESTS)) @@ -250,7 +250,7 @@ abitest-% : abitest-%.exe ./$< $(TCCFLAGS) abitest: abitest-cc -ifneq ($(CONFIG_arm_eabi),yes) # not ARM soft-float +ifneq (-$(CONFIG_arm_eabi)-$(CONFIG_arm_vfp)-,-yes--) abitest: abitest-tcc endif @@ -261,6 +261,8 @@ vla_test-run: vla_test$(EXESUF) @echo ------------ $@ ------------ ./vla_test$(EXESUF) +.PHONY: abitest vla_test + asm-c-connect$(EXESUF): asm-c-connect-1.c asm-c-connect-2.c $(TCC) -o $@ $^ diff --git a/tests/tcctest.c b/tests/tcctest.c index 5848ab80..51eea486 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -21,14 +21,19 @@ typedef __SIZE_TYPE__ uintptr_t; #endif -#if defined(_WIN32) || \ - (defined(__arm__) && \ - (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__))) +#if defined(_WIN32) \ + || (defined(__arm__) \ + && (defined(__FreeBSD__) \ + || defined(__OpenBSD__) \ + || defined(__NetBSD__) \ + || defined __ANDROID__)) #define LONG_LONG_FORMAT "%lld" #define ULONG_LONG_FORMAT "%llu" +#define XLONG_LONG_FORMAT "%llx" #else #define LONG_LONG_FORMAT "%Ld" #define ULONG_LONG_FORMAT "%Lu" +#define XLONG_LONG_FORMAT "%Lx" #endif // MinGW has 80-bit rather than 64-bit long double which isn't compatible with TCC or MSVC @@ -2265,7 +2270,7 @@ double ftab1[3] = { 1.2, 3.4, -5.6 }; void float_test(void) { -#if !defined(__arm__) || defined(__ARM_PCS_VFP) +#if !defined(__arm__) || defined(__ARM_PCS_VFP) || defined __ANDROID__ volatile float fa, fb; volatile double da, db; int a; @@ -2531,7 +2536,7 @@ void longlong_test(void) b = 0x12345678; a = -1; c = a + b; - printf("%Lx\n", c); + printf(XLONG_LONG_FORMAT"\n", c); #endif /* long long reg spill test */ diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 776c7276..44c28fe3 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -9,7 +9,7 @@ TESTS = $(patsubst %.c,%.test,\ # some tests do not pass on all platforms, remove them for now SKIP = 34_array_assignment.test # array assignment is not in C standard -ifeq ($(CONFIG_arm_eabi),yes) # not ARM soft-float +ifeq (-$(CONFIG_arm_eabi)-$(CONFIG_arm_vfp)-,-yes--) SKIP += 22_floating_point.test endif ifdef CONFIG_OSX @@ -27,12 +27,12 @@ ifeq (,$(filter i386 x86_64,$(ARCH))) SKIP += 125_atomic_misc.test # currently only x86 supported endif ifeq ($(CONFIG_backtrace),no) - SKIP += 112_backtrace.test SKIP += 113_btdll.test CONFIG_bcheck = no # no bcheck without backtrace endif ifeq ($(CONFIG_bcheck),no) + SKIP += 112_backtrace.test SKIP += 114_bound_signal.test SKIP += 115_bound_setjmp.test SKIP += 116_bound_setjmp2.test