From da8c62f75d893449e232944fc62566c020b4d010 Mon Sep 17 00:00:00 2001 From: grischka Date: Wed, 11 Oct 2017 18:13:43 +0200 Subject: [PATCH] various stuff win32/Makefile ("for cygwin") removed - On cygwin, the normal ./configure && make can be used with either cygwin's "GCC for Win32 Toolchain" ./configure --cross-prefix=i686-w64-mingw32- or with an existing tcc: ./configure --cc=/tcc.exe tcctest.c: - exclude test_high_clobbers() on _WIN64 (does not work) tests2/95_bitfield.c: - use 'signed char' for ARM (where default 'char' is unsigned) tests: - remove -I "expr" diff option to allow tests with busybox-diff. libtcc.c, tcc.c: - removed -iwithprefix option. It is supposed to be combined with -iprefix which we don't have either. tccgen.c: - fix assignments and return of 'void', as in void f() { void *p, *q; *p = *q: return *p; } This appears to be allowed but should do nothing. tcc.h, libtcc.c, tccpp.c: - Revert "Introduce VIP sysinclude paths which are always searched first" This reverts commit 1d5e386b0a78393ac6b670c209a185849ec798a1. The patch was giving tcc's system includes priority over -I which is not how it should be. tccelf.c: - add DT_TEXTREL tag only if text relocations are actually used (which is likely not the case on x86_64) - prepare_dynamic_rel(): avoid relocation of unresolved (weak) symbols tccrun.c: - for HAVE_SELINUX, use two mappings to the same (real) file. (it was so once except the RX mapping wasn't used at all). tccpe.c: - fix relocation constant used for x86_64 (by Andrei E. Warentin) - #ifndef _WIN32 do "chmod 755 ..." to get runnable exes on cygwin. tccasm.c: - keep forward asm labels static, otherwise they will endup in dynsym eventually. configure, Makefile: - mingw32: respect ./configure options --bindir --docdir --libdir - allow overriding tcc when building libtcc1.a and libtcc.def with make XTCC= - use $(wildcard ...) for install to allow installing just a cross compiler for example make cross-arm make install - use name -libtcc1.a build-tcc.bat: - add options: -clean, -b bindir --- Makefile | 113 +++++++------- configure | 68 ++++----- include/stdarg.h | 5 - lib/Makefile | 14 +- libtcc.c | 39 ++--- libtcc.h | 3 - tcc.c | 5 +- tcc.h | 35 ++--- tccasm.c | 2 + tccelf.c | 218 ++++++++++++--------------- tccgen.c | 38 +++-- tccpe.c | 35 ++--- tccpp.c | 49 +++--- tccrun.c | 53 ++++--- tcctok.h | 16 +- tests/Makefile | 4 + tests/pp/13.expect | 1 - tests/pp/15.c | 4 +- tests/pp/15.expect | 2 - tests/pp/Makefile | 4 +- tests/tcctest.c | 7 +- tests/tests2/95_bitfields.c | 2 +- tests/tests2/96_nodata_wanted.c | 2 +- tests/tests2/96_nodata_wanted.expect | 2 - tests/tests2/Makefile | 2 +- win32/Makefile | 148 ------------------ win32/build-tcc.bat | 105 +++++++------ win32/lib/crt1.c | 21 +-- win32/lib/wincrt1.c | 80 ++++------ win32/tcc-win32.txt | 19 +-- 30 files changed, 433 insertions(+), 663 deletions(-) delete mode 100644 win32/Makefile diff --git a/Makefile b/Makefile index 3a5c000..8888149 100644 --- a/Makefile +++ b/Makefile @@ -98,16 +98,17 @@ TCC_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince c67 LIBTCC1_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince PROGS_CROSS = $(foreach X,$(TCC_X),$X-tcc$(EXESUF)) -LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),libtcc1-$X.a) +LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),$X-libtcc1.a) # build cross compilers & libs cross: $(LIBTCC1_CROSS) $(PROGS_CROSS) # build specific cross compiler & lib -cross-%: %-tcc$(EXESUF) libtcc1-%.a ; +cross-%: %-tcc$(EXESUF) %-libtcc1.a ; -install: install$(CFGWIN) -uninstall: uninstall$(CFGWIN) +install: ; @$(MAKE) --no-print-directory install$(CFGWIN) +install-strip: ; @$(MAKE) --no-print-directory install$(CFGWIN) CONFIG_strip=yes +uninstall: ; @$(MAKE) --no-print-directory uninstall$(CFGWIN) ifdef CONFIG_cross all : cross @@ -143,10 +144,10 @@ DEFINES += $(DEF-$(or $(findstring win,$T),unx)) ifneq ($(X),) ifeq ($(CONFIG_WIN32),yes) -DEF-win += -DTCC_LIBTCC1="\"libtcc1-$T.a\"" -DEF-unx += -DTCC_LIBTCC1="\"lib/libtcc1-$T.a\"" +DEF-win += -DTCC_LIBTCC1="\"$(X)libtcc1.a\"" +DEF-unx += -DTCC_LIBTCC1="\"lib/$(X)libtcc1.a\"" else -DEF-all += -DTCC_LIBTCC1="\"libtcc1-$T.a\"" +DEF-all += -DTCC_LIBTCC1="\"$(X)libtcc1.a\"" DEF-win += -DCONFIG_TCCDIR="\"$(tccdir)/win32\"" endif endif @@ -217,21 +218,22 @@ libtcc.so: LDFLAGS+=-fPIC # windows dynamic libtcc library libtcc.dll : $(LIBTCC_OBJ) $(CC) -shared -o $@ $^ $(LDFLAGS) - -libtcc.def : libtcc.dll tcc$(EXESUF) - ./tcc$(EXESUF) -impdef $< -o $@ - libtcc.dll : DEFINES += -DLIBTCC_AS_DLL +# import file for windows libtcc.dll +libtcc.def : libtcc.dll tcc$(EXESUF) + $(XTCC) -impdef $< -o $@ +XTCC ?= ./tcc$(EXESUF) + # TinyCC runtime libraries libtcc1.a : tcc$(EXESUF) FORCE - @$(MAKE) -C lib DEFINES="$(DEF-$T)" + @$(MAKE) -C lib DEFINES='$(DEF-$T)' # Cross libtcc1.a -libtcc1-%.a : %-tcc$(EXESUF) FORCE - @$(MAKE) -C lib DEFINES="$(DEF-$*)" CROSS_TARGET=$* +%-libtcc1.a : %-tcc$(EXESUF) FORCE + @$(MAKE) -C lib DEFINES='$(DEF-$*)' CROSS_TARGET=$* -.PRECIOUS: libtcc1-%.a +.PRECIOUS: %-libtcc1.a FORCE: # -------------------------------------------------------------------------- @@ -252,35 +254,29 @@ tcc-doc.info: tcc-doc.texi INSTALL = install -m644 INSTALLBIN = install -m755 $(STRIP_$(CONFIG_strip)) STRIP_yes = -s -install-strip: install -install-strip: CONFIG_strip = yes -TRY-INSTALL = $(if $(wildcard $1),mkdir -p $2 && $(INSTALL) $1 $2) -LIBTCC1_W = $(wildcard $(filter %-win32.a %-wince.a,$(LIBTCC1_CROSS))) -LIBTCC1_U = $(wildcard $(filter-out $(LIBTCC1_W),$(LIBTCC1_CROSS))) -PROGS_X = $(wildcard $(PROGS_CROSS)) +LIBTCC1_W = $(filter %-win32-libtcc1.a %-wince-libtcc1.a,$(LIBTCC1_CROSS)) +LIBTCC1_U = $(filter-out $(LIBTCC1_W),$(LIBTCC1_CROSS)) +IB = $(if $1,mkdir -p $2 && $(INSTALLBIN) $1 $2) +IBw = $(call IB,$(wildcard $1),$2) +IF = $(if $1,mkdir -p $2 && $(INSTALL) $1 $2) +IFw = $(call IF,$(wildcard $1),$2) +IR = mkdir -p $2 && cp -r $1/. $2 # install progs & libs install-unx: - mkdir -p "$(bindir)" - $(INSTALLBIN) $(PROGS) $(PROGS_X) "$(bindir)" - mkdir -p "$(tccdir)" - $(INSTALL) $(LIBTCC1) $(LIBTCC1_U) "$(tccdir)" - mkdir -p "$(tccdir)/include" - $(INSTALL) $(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h "$(tccdir)/include" - mkdir -p "$(libdir)" - $(INSTALL) $(LIBTCC) "$(libdir)" - mkdir -p "$(includedir)" - $(INSTALL) $(TOPSRC)/libtcc.h "$(includedir)" - $(call TRY-INSTALL,tcc.1,"$(mandir)/man1") - $(call TRY-INSTALL,tcc-doc.info,"$(infodir)") - $(call TRY-INSTALL,tcc-doc.html,"$(docdir)") -ifneq "$(LIBTCC1_W)" "" - mkdir -p "$(tccdir)/win32/lib" - $(INSTALL) $(TOPSRC)/win32/lib/*.def $(LIBTCC1_W) "$(tccdir)/win32/lib" - mkdir -p "$(tccdir)/win32/include" - cp -r $(TOPSRC)/win32/include/. "$(tccdir)/win32/include" - $(INSTALL) $(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h "$(tccdir)/win32/include" + $(call IBw,$(PROGS) $(PROGS_CROSS),"$(bindir)") + $(call IFw,$(LIBTCC1) $(LIBTCC1_U),"$(tccdir)") + $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include") + $(call $(if $(findstring .so,$(LIBTCC)),IBw,IFw),$(LIBTCC),"$(libdir)") + $(call IF,$(TOPSRC)/libtcc.h,"$(includedir)") + $(call IFw,tcc.1,"$(mandir)/man1") + $(call IFw,tcc-doc.info,"$(infodir)") + $(call IFw,tcc-doc.html,"$(docdir)") +ifneq "$(wildcard $(LIBTCC1_W))" "" + $(call IFw,$(TOPSRC)/win32/lib/*.def $(LIBTCC1_W),"$(tccdir)/win32/lib") + $(call IR,$(TOPSRC)/win32/include,"$(tccdir)/win32/include") + $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/win32/include") endif # uninstall @@ -293,32 +289,31 @@ uninstall-unx: # install progs & libs on windows install-win: - mkdir -p "$(tccdir)" - $(INSTALL) $(PROGS) $(subst libtcc.a,,$(LIBTCC)) $(PROGS_X) "$(tccdir)" - mkdir -p "$(tccdir)/lib" - $(INSTALL) $(TOPSRC)/win32/lib/*.def "$(tccdir)/lib" - $(INSTALL) libtcc1.a $(LIBTCC1_W) "$(tccdir)/lib" - mkdir -p "$(tccdir)/include" - cp -r $(TOPSRC)/win32/include/. "$(tccdir)/include" - $(INSTALL) $(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h "$(tccdir)/include" - mkdir -p "$(tccdir)/examples" - cp -r $(TOPSRC)/win32/examples/. "$(tccdir)/examples" - $(INSTALL) $(TOPSRC)/tests/libtcc_test.c "$(tccdir)/examples" - mkdir -p "$(tccdir)/libtcc" - $(INSTALL) $(TOPSRC)/libtcc.h $(subst .dll,.def,$(LIBTCC)) "$(tccdir)/libtcc" - mkdir -p "$(tccdir)/doc" - $(INSTALL) $(TOPSRC)/win32/tcc-win32.txt $(wildcard tcc-doc.html) "$(tccdir)/doc" -ifneq "$(LIBTCC1_U)" "" - $(INSTALL) $(LIBTCC1_U) "$(tccdir)/lib" - mkdir -p "$(tccdir)/lib/include"; - $(INSTALL) $(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h "$(tccdir)/lib/include" + $(call IBw,$(PROGS) $(PROGS_CROSS) $(subst libtcc.a,,$(LIBTCC)),"$(bindir)") + $(call IF,$(TOPSRC)/win32/lib/*.def,"$(tccdir)/lib") + $(call IFw,libtcc1.a $(LIBTCC1_W),"$(tccdir)/lib") + $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include") + $(call IR,$(TOPSRC)/win32/include,"$(tccdir)/include") + $(call IR,$(TOPSRC)/win32/examples,"$(tccdir)/examples") + $(call IF,$(TOPSRC)/tests/libtcc_test.c,"$(tccdir)/examples") + $(call IFw,$(TOPSRC)/libtcc.h $(subst .dll,.def,$(LIBTCC)),"$(libdir)") + $(call IFw,$(TOPSRC)/win32/tcc-win32.txt tcc-doc.html,"$(docdir)") +ifneq "$(wildcard $(LIBTCC1_U))" "" + $(call IFw,$(LIBTCC1_U),"$(tccdir)/lib") + $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/lib/include") endif # the msys-git shell works to configure && make except it does not have install +ifeq ($(CONFIG_WIN32)-$(shell which install >/dev/null 2>&1 || echo no),yes-no) install-win : INSTALL = cp +install-win : INSTALLBIN = cp +endif # uninstall on windows uninstall-win: + @rm -fv $(foreach P,$(PROGS) $(PROGS_CROSS) libtcc.dll,"$(bindir)/$P") + @rm -fv $(foreach F,tcc-doc.html tcc-win32.txt,"$(docdir)/$F") + @rm -fv $(foreach F,libtcc.h libtcc.def libtcc.a,"$(libdir)/$F") rm -r "$(tccdir)" # -------------------------------------------------------------------------- diff --git a/configure b/configure index 78f2072..1ee3acb 100755 --- a/configure +++ b/configure @@ -56,7 +56,6 @@ case $targetos in DLLSUF=".dylib" ;; MINGW*|MSYS*|CYGWIN*) - confvars="$confvars WIN32" mingw32=yes ;; DragonFly|OpenBSD|FreeBSD|NetBSD) @@ -126,8 +125,6 @@ for opt do ;; --cpu=*) cpu=`echo $opt | cut -d '=' -f 2` ;; - --enable-mingw32) confvars="$confvars WIN32"; mingw32="yes" - ;; --enable-cross) confvars="$confvars cross" ;; --disable-static) confvars="$confvars static=no" @@ -142,6 +139,8 @@ for opt do ;; --with-selinux) confvars="$confvars selinux" ;; + --config-mingw32*) mingw32=$(echo "$opt=yes" | cut -d '=' -f 2) + ;; --config-*) confvars="$confvars ${opt#--config-}"; suggest="no" ;; --help|-h) show_help="yes" @@ -216,22 +215,12 @@ if test "$mingw32" = "yes" ; then if test "$cc" = gcc; then test -z "$LDFLAGS" && LDFLAGS="-static" fi - if test x"$tccdir" = x""; then - tccdir="tcc" - fi - if test -z "$prefix" ; then - prefix="C:/Program Files/${tccdir}" - fi - if test -z "$sharedir" ; then - sharedir="${prefix}" - fi - execprefix="$prefix" - bindir="${prefix}" - tccdir="${prefix}" - libdir="${prefix}/lib" - docdir="${sharedir}/doc" - mandir="${sharedir}/man" - infodir="${sharedir}/info" + test -z "$prefix" && prefix="C:/Program Files/tcc" + test -z "$tccdir" && tccdir="${prefix}" + test -z "$bindir" && bindir="${tccdir}" + test -z "$docdir" && docdir="${tccdir}/doc" + test -z "$libdir" && libdir="${tccdir}/libtcc" + confvars="$confvars WIN32" LIBSUF=".lib" EXESUF=".exe" DLLSUF=".dll" @@ -263,12 +252,11 @@ else if test x"$tccdir" = x""; then tccdir="${libdir}/tcc" fi + if test x"$includedir" = x""; then + includedir="${prefix}/include" + fi fi # mingw32 -if test x"$includedir" = x""; then - includedir="${prefix}/include" -fi - if test x"$show_help" = "xyes" ; then cat << EOF Usage: configure [options] @@ -302,7 +290,6 @@ Advanced options (experts only): --enable-static make libtcc.a instead of libtcc.dll (win32) --disable-rpath disable use of -rpath with the above --with-libgcc use libgcc_s.so.1 instead of libtcc1.a - --enable-mingw32 build windows version on linux with mingw32 --enable-cross build cross compilers --with-selinux use mmap for executable memory (with tcc -run) --sysincludepaths=... specify system include paths, colon separated @@ -310,7 +297,7 @@ Advanced options (experts only): --crtprefix=... specify locations of crt?.o, colon separated --elfinterp=... specify elf interpreter --triplet=... specify system library/include directory triplet - --config-uClibc,-musl... enable specific configuration for some systems + --config-uClibc,-musl,-mingw32... enable system specific configurations EOF #echo "NOTE: The object files are build at the place where configure is launched" exit 1 @@ -320,15 +307,14 @@ cc="${cross_prefix}${cc}" ar="${cross_prefix}${ar}" strip="${cross_prefix}${strip}" -CONFTEST=./conftest$EXESUF -if ! $cc -o $CONFTEST $source_path/conftest.c 2>/dev/null ; then - echo "configure: error: '$cc' failed to compile conftest.c." -else - gcc_major="$($CONFTEST version)" - gcc_minor="$($CONFTEST minor)" -fi - if test -z "$cross_prefix" ; then + CONFTEST=./conftest$EXESUF + if ! $cc -o $CONFTEST $source_path/conftest.c 2>/dev/null ; then + echo "configure: error: '$cc' failed to compile conftest.c." + else + gcc_major="$($CONFTEST version)" + gcc_minor="$($CONFTEST minor)" + fi bigendian="$($CONFTEST bigendian)" if test "$mingw32" = "no" ; then @@ -401,13 +387,13 @@ fi fcho() { if test -n "$2"; then echo "$1$2"; fi } -echo "Binary directory $bindir" -echo "TinyCC directory $tccdir" -echo "Library directory $libdir" -echo "Include directory $includedir" -echo "Manual directory $mandir" -echo "Info directory $infodir" -echo "Doc directory $docdir" +fcho "Binary directory " "$bindir" +fcho "TinyCC directory " "$tccdir" +fcho "Library directory " "$libdir" +fcho "Include directory " "$includedir" +fcho "Manual directory " "$mandir" +fcho "Info directory " "$infodir" +fcho "Doc directory " "$docdir" fcho "Target root prefix " "$sysroot" echo "Source path $source_path" echo "C compiler $cc ($gcc_major.$gcc_minor)" @@ -471,8 +457,6 @@ print_mak CONFIG_LDDIR "$tcc_lddir" print_mak CONFIG_TRIPLET "$triplet" print_mak_int TCC_CPU_VERSION "$cpuver" -echo "#define GCC_MAJOR $gcc_major" >> $TMPH -echo "#define GCC_MINOR $gcc_minor" >> $TMPH if test "$cpu" = "aarch64" ; then echo "ARCH=arm64" >> config.mak else diff --git a/include/stdarg.h b/include/stdarg.h index a42acae..10ce733 100644 --- a/include/stdarg.h +++ b/include/stdarg.h @@ -16,12 +16,7 @@ typedef struct { char *reg_save_area; } __va_list_struct; -/* Avoid conflicting definition for va_list on musl libc */ -#if !defined __DEFINED_va_list || defined __TCC_NEEDS_va_list typedef __va_list_struct va_list[1]; -#undef __DEFINED_va_list -#define __DEFINED_va_list -#endif void __va_start(__va_list_struct *ap, void *fp); void *__va_arg(__va_list_struct *ap, int arg_type, int size, int align); diff --git a/lib/Makefile b/lib/Makefile index 3b582d4..0c1ec54 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -7,20 +7,20 @@ include $(TOP)/Makefile VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown) X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-) -BIN = $(TOP)/libtcc1$(if $(CROSS_TARGET),-$(CROSS_TARGET)).a +BIN = $(TOP)/$(X)libtcc1.a -TCC = $(TOP)/$(X)tcc$(EXESUF) -XCC = $(TCC) -XAR = $(TCC) -ar +XTCC ?= $(TOP)/$(X)tcc$(EXESUF) +XCC = $(XTCC) +XAR = $(XTCC) -ar XFLAGS-unx = -B$(TOPSRC) XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include XFLAGS = $(XFLAGS$(XCFG)) XCFG = $(or $(findstring -win,$T),-unx) -# in order to use gcc, tyoe: make lib-usegcc=yes -armlib-usegcc ?= no +# in order to use gcc, tyoe: make -libtcc1-usegcc=yes +arm-libtcc1-usegcc ?= no -ifeq "$($(X)$(T)lib-usegcc)" "yes" +ifeq "$($(T)-libtcc1-usegcc)" "yes" XCC = $(CC) XAR = $(AR) XFLAGS = $(CFLAGS) -fPIC diff --git a/libtcc.c b/libtcc.c index 9ef538e..43a07ef 100644 --- a/libtcc.c +++ b/libtcc.c @@ -104,10 +104,8 @@ static void tcc_set_lib_path_w32(TCCState *s) char path[1024], *p; GetModuleFileNameA(tcc_module, path, sizeof path); p = tcc_basename(normalize_slashes(strlwr(path))); - if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5)) - p -= 5; - else if (p > path) - p--; + if (p > path) + --p; *p = 0; tcc_set_lib_path(s, path); } @@ -440,7 +438,7 @@ static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char * CString str; cstr_new(&str); - for (p = in; c = *p, c != '\0' && c != PATHSEP; ++p) { + for (p = in; c = *p, c != '\0' && c != PATHSEP[0]; ++p) { if (c == '{' && p[1] && p[2] == '}') { c = p[1], p += 2; if (c == 'B') @@ -804,6 +802,8 @@ LIBTCCAPI TCCState *tcc_new(void) #endif #elif defined(TCC_TARGET_ARM64) tcc_define_symbol(s, "__aarch64__", NULL); +#elif defined TCC_TARGET_C67 + tcc_define_symbol(s, "__C67__", NULL); #endif #ifdef TCC_TARGET_PE @@ -827,13 +827,13 @@ LIBTCCAPI TCCState *tcc_new(void) # if defined(__FreeBSD_kernel__) tcc_define_symbol(s, "__FreeBSD_kernel__", NULL); # endif -#endif # if defined(__NetBSD__) tcc_define_symbol(s, "__NetBSD__", "__NetBSD__"); # endif # if defined(__OpenBSD__) tcc_define_symbol(s, "__OpenBSD__", "__OpenBSD__"); # endif +#endif /* TinyCC & gcc defines */ #if PTR_SIZE == 4 @@ -853,14 +853,6 @@ LIBTCCAPI TCCState *tcc_new(void) tcc_define_symbol(s, "__LP64__", NULL); #endif -#if defined(TCC_MUSL) - tcc_define_symbol(s, "__TCC_NEEDS_va_list", ""); - tcc_define_symbol(s, "__builtin_va_list", "va_list"); - tcc_define_symbol(s, "__DEFINED_va_list", ""); - tcc_define_symbol(s, "__DEFINED___isoc_va_list", ""); - tcc_define_symbol(s, "__isoc_va_list", "void *"); -#endif /* TCC_MUSL */ - #ifdef TCC_TARGET_PE tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short"); tcc_define_symbol(s, "__WINT_TYPE__", "unsigned short"); @@ -887,6 +879,11 @@ LIBTCCAPI TCCState *tcc_new(void) tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", "name proto __asm__ (#alias) __THROW"); # endif +# if defined(TCC_MUSL) + tcc_define_symbol(s, "__DEFINED_va_list", ""); + tcc_define_symbol(s, "__DEFINED___isoc_va_list", ""); + tcc_define_symbol(s, "__isoc_va_list", "void *"); +# endif /* TCC_MUSL */ /* Some GCC builtins that are simple to express as macros. */ tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x"); #endif /* ndef TCC_TARGET_PE */ @@ -906,7 +903,6 @@ LIBTCCAPI void tcc_delete(TCCState *s1) /* free include paths */ dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes); - dynarray_reset(&s1->tccinclude_paths, &s1->nb_tccinclude_paths); dynarray_reset(&s1->include_paths, &s1->nb_include_paths); dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths); dynarray_reset(&s1->cmd_include_files, &s1->nb_cmd_include_files); @@ -947,7 +943,6 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) if (!s->nostdinc) { /* default include paths */ /* -isystem paths have already been handled */ - tcc_add_tccinclude_path(s, CONFIG_TCC_TCCINCLUDEPATHS); tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS); } @@ -985,12 +980,6 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) return 0; } -LIBTCCAPI int tcc_add_tccinclude_path(TCCState *s, const char *pathname) -{ - tcc_split_path(s, &s->tccinclude_paths, &s->nb_tccinclude_paths, pathname); - return 0; -} - LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname) { tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname); @@ -1547,7 +1536,6 @@ static const TCCOption tcc_options[] = { { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG }, - { "iwithprefix", TCC_OPTION_iwithprefix, TCC_OPTION_HAS_ARG }, { "include", TCC_OPTION_include, TCC_OPTION_HAS_ARG }, { "nostdinc", TCC_OPTION_nostdinc, 0 }, { "nostdlib", TCC_OPTION_nostdlib, 0 }, @@ -1682,7 +1670,6 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind) int last_o = -1; int x; CString linker_arg; /* collect -Wl options */ - char buf[1024]; int tool = 0, arg_start = 0, noaction = optind; char **argv = *pargv; int argc = *pargc; @@ -1827,10 +1814,6 @@ reparse: case TCC_OPTION_isystem: tcc_add_sysinclude_path(s, optarg); break; - case TCC_OPTION_iwithprefix: - snprintf(buf, sizeof buf, "{B}/%s", optarg); - tcc_add_tccinclude_path(s, buf); - break; case TCC_OPTION_include: dynarray_add(&s->cmd_include_files, &s->nb_cmd_include_files, tcc_strdup(optarg)); diff --git a/libtcc.h b/libtcc.h index fc37251..a1b31e3 100644 --- a/libtcc.h +++ b/libtcc.h @@ -32,9 +32,6 @@ LIBTCCAPI void tcc_set_options(TCCState *s, const char *str); /*****************************/ /* preprocessor */ -/* add in tcc include path, searched before anything else */ -LIBTCCAPI int tcc_add_tccinclude_path(TCCState *s, const char *pathname); - /* add include path */ LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname); diff --git a/tcc.c b/tcc.c index 53ee84e..c347a06 100644 --- a/tcc.c +++ b/tcc.c @@ -86,7 +86,6 @@ static const char help2[] = " -Wp,-opt same as -opt\n" " -include file include 'file' above each input file\n" " -isystem dir add 'dir' to system include path\n" - " -iwithprefix dir set tcc's private include/library subdir\n" " -static link to static libraries (not recommended)\n" " -dumpversion print version\n" " -print-search-dirs print search paths\n" @@ -181,7 +180,6 @@ static void print_search_dirs(TCCState *s) { printf("install: %s\n", s->tcc_lib_path); /* print_dirs("programs", NULL, 0); */ - print_dirs("tcc-include", s->tccinclude_paths, s->nb_tccinclude_paths); print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths); print_dirs("libraries", s->library_paths, s->nb_library_paths); #ifndef TCC_TARGET_PE @@ -197,7 +195,7 @@ static void set_environment(TCCState *s) path = getenv("C_INCLUDE_PATH"); if(path != NULL) { - tcc_add_include_path(s, path); + tcc_add_sysinclude_path(s, path); } path = getenv("CPATH"); if(path != NULL) { @@ -278,6 +276,7 @@ redo: return 0; if (opt == OPT_PRINT_DIRS) { /* initialize search dirs */ + set_environment(s); tcc_set_output_type(s, TCC_OUTPUT_MEMORY); print_search_dirs(s); return 0; diff --git a/tcc.h b/tcc.h index 32bb608..da26298 100644 --- a/tcc.h +++ b/tcc.h @@ -101,10 +101,12 @@ extern long double strtold (const char *__nptr, char **__endptr); # define IS_DIRSEP(c) (c == '/' || c == '\\') # define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2]))) # define PATHCMP stricmp +# define PATHSEP ";" #else # define IS_DIRSEP(c) (c == '/') # define IS_ABSPATH(p) IS_DIRSEP(p[0]) # define PATHCMP strcmp +# define PATHSEP ":" #endif /* -------------------------------------------- */ @@ -195,21 +197,14 @@ extern long double strtold (const char *__nptr, char **__endptr); /* Below: {B} is substituted by CONFIG_TCCDIR (rsp. -B option) */ /* system include paths */ -#ifndef CONFIG_TCC_TCCINCLUDEPATHS -# ifdef TCC_TARGET_PE -# define CONFIG_TCC_TCCINCLUDEPATHS "{B}/include;{B}/include/winapi" -# else -# define CONFIG_TCC_TCCINCLUDEPATHS "{B}/include" -# endif -#endif - #ifndef CONFIG_TCC_SYSINCLUDEPATHS -# ifndef TCC_TARGET_PE -# define CONFIG_TCC_SYSINCLUDEPATHS \ - ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/include") \ - ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/include") +# ifdef TCC_TARGET_PE +# define CONFIG_TCC_SYSINCLUDEPATHS "{B}/include"PATHSEP"{B}/include/winapi" # else -# define CONFIG_TCC_SYSINCLUDEPATHS "" +# define CONFIG_TCC_SYSINCLUDEPATHS \ + "{B}/include" \ + ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/include") \ + ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/include") # endif #endif @@ -283,12 +278,6 @@ extern long double strtold (const char *__nptr, char **__endptr); #define TCC_LIBGCC USE_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1" #endif -#ifdef TCC_TARGET_PE -#define PATHSEP ';' -#else -#define PATHSEP ':' -#endif - /* -------------------------------------------- */ #include "libtcc.h" @@ -722,10 +711,7 @@ struct TCCState { DLLReference **loaded_dlls; int nb_loaded_dlls; - /* include paths, search order */ - char **tccinclude_paths; - int nb_tccinclude_paths; - + /* include paths */ char **include_paths; int nb_include_paths; @@ -1616,7 +1602,7 @@ ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str); ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd); ST_FUNC int pe_output_file(TCCState * s1, const char *filename); ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value); -#ifndef TCC_TARGET_ARM +#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2); #endif #ifdef TCC_TARGET_X86_64 @@ -1628,7 +1614,6 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp); # define ST_PE_IMPORT 0x20 # define ST_PE_STDCALL 0x40 #endif - /* ------------ tccrun.c ----------------- */ #ifdef TCC_IS_NATIVE #ifdef CONFIG_TCC_STATIC diff --git a/tccasm.c b/tccasm.c index 1e20dc6..ac1618a 100644 --- a/tccasm.c +++ b/tccasm.c @@ -75,6 +75,8 @@ ST_FUNC Sym* get_asm_sym(int name, Sym *csym) sym->type.t &= ~VT_EXTERN; /* Mark that this asm symbol doesn't need to be fed back. */ sym->a.dllimport = 1; + } else { + sym->type.t |= VT_STATIC; } } return sym; diff --git a/tccelf.c b/tccelf.c index 225cd9d..22ce5df 100644 --- a/tccelf.c +++ b/tccelf.c @@ -828,6 +828,12 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) switch(type) { #if defined(TCC_TARGET_I386) case R_386_32: + if (!get_sym_attr(s1, sym_index, 0)->dyn_index + && ((ElfW(Sym)*)symtab_section->data + sym_index)->st_shndx == SHN_UNDEF) { + /* don't fixup unresolved (weak) symbols */ + rel->r_info = ELFW(R_INFO)(sym_index, R_386_RELATIVE); + break; + } #elif defined(TCC_TARGET_X86_64) case R_X86_64_32: case R_X86_64_32S: @@ -1238,14 +1244,6 @@ static void tcc_output_binary(TCCState *s1, FILE *f, } } -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -#define HAVE_PHDR 1 -#define EXTRA_RELITEMS 14 -#else -#define HAVE_PHDR 1 -#define EXTRA_RELITEMS 9 -#endif - ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) { int sym_index = ELFW(R_SYM) (rel->r_info); @@ -1413,13 +1411,12 @@ static void bind_libs_dynsyms(TCCState *s1) for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) { name = (char *) s1->dynsymtab_section->link->data + esym->st_name; sym_index = find_elf_sym(symtab_section, name); - /* XXX: avoid adding a symbol if already present because of - -rdynamic ? */ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - if (sym_index && sym->st_shndx != SHN_UNDEF) - set_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info, - 0, sym->st_shndx, name); - else if (esym->st_shndx == SHN_UNDEF) { + if (sym_index && sym->st_shndx != SHN_UNDEF + && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { + set_elf_sym(s1->dynsym, sym->st_value, sym->st_size, + sym->st_info, 0, sym->st_shndx, name); + } else if (esym->st_shndx == SHN_UNDEF) { /* weak symbols can stay undefined */ if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK) tcc_warning("undefined dynamic symbol '%s'", name); @@ -1451,10 +1448,11 @@ static void export_global_syms(TCCState *s1) /* Allocate strings for section names and decide if an unallocated section should be output. NOTE: the strsec section comes last, so its size is also correct ! */ -static void alloc_sec_names(TCCState *s1, int file_type, Section *strsec) +static int alloc_sec_names(TCCState *s1, int file_type, Section *strsec) { int i; Section *s; + int textrel = 0; /* Allocate strings for section names */ for(i = 1; i < s1->nb_sections; i++) { @@ -1463,12 +1461,11 @@ static void alloc_sec_names(TCCState *s1, int file_type, Section *strsec) patch them */ if (file_type == TCC_OUTPUT_DLL && s->sh_type == SHT_RELX && - !(s->sh_flags & SHF_ALLOC)) { - /* gr: avoid bogus relocs for empty (debug) sections */ - if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC) - prepare_dynamic_rel(s1, s); - else if (s1->do_debug) - s->sh_size = s->data_offset; + !(s->sh_flags & SHF_ALLOC) && + (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC) && + prepare_dynamic_rel(s1, s)) { + if (s1->sections[s->sh_info]->sh_flags & SHF_EXECINSTR) + textrel = 1; } else if (s1->do_debug || file_type == TCC_OUTPUT_OBJ || (s->sh_flags & SHF_ALLOC) || @@ -1480,13 +1477,14 @@ static void alloc_sec_names(TCCState *s1, int file_type, Section *strsec) s->sh_name = put_elf_str(strsec, s->name); } strsec->sh_size = strsec->data_offset; + return textrel; } /* Info to be copied in dynamic section */ struct dyn_inf { Section *dynamic; Section *dynstr; - unsigned long dyn_rel_off; + unsigned long data_offset; addr_t rel_addr; addr_t rel_size; #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) @@ -1542,7 +1540,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, the program header table itself if needed. These are done later as they require section layout to be done first. */ if (interp) - ph += 1 + HAVE_PHDR; + ph += 2; /* dynamic relocation table information, for .dynamic section */ dyninf->rel_addr = dyninf->rel_size = 0; @@ -1684,19 +1682,14 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, if (interp) { ph = &phdr[0]; - if (HAVE_PHDR) - { - int len = phnum * sizeof(ElfW(Phdr)); - - ph->p_type = PT_PHDR; - ph->p_offset = sizeof(ElfW(Ehdr)); - ph->p_vaddr = interp->sh_addr - len; - ph->p_paddr = ph->p_vaddr; - ph->p_filesz = ph->p_memsz = len; - ph->p_flags = PF_R | PF_X; - ph->p_align = 4; /* interp->sh_addralign; */ - ph++; - } + ph->p_type = PT_PHDR; + ph->p_offset = sizeof(ElfW(Ehdr)); + ph->p_filesz = ph->p_memsz = phnum * sizeof(ElfW(Phdr)); + ph->p_vaddr = interp->sh_addr - ph->p_filesz; + ph->p_paddr = ph->p_vaddr; + ph->p_flags = PF_R | PF_X; + ph->p_align = 4; /* interp->sh_addralign; */ + ph++; ph->p_type = PT_INTERP; ph->p_offset = interp->sh_offset; @@ -1727,12 +1720,9 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, sections */ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf) { - Section *dynamic; - - dynamic = dyninf->dynamic; + Section *dynamic = dyninf->dynamic; /* put dynamic section entries */ - dynamic->data_offset = dyninf->dyn_rel_off; put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr); put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr); put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr); @@ -2009,22 +1999,20 @@ static int elf_output_file(TCCState *s1, const char *filename) ElfW(Phdr) *phdr; ElfW(Sym) *sym; Section *strsec, *interp, *dynamic, *dynstr; + int textrel; file_type = s1->output_type; s1->nb_errors = 0; - - /* if linking, also link in runtime libraries (libc, libgcc, etc.) */ - if (file_type != TCC_OUTPUT_OBJ) { - tcc_add_runtime(s1); - } - + ret = -1; phdr = NULL; sec_order = NULL; interp = dynamic = dynstr = NULL; /* avoid warning */ + textrel = 0; if (file_type != TCC_OUTPUT_OBJ) { + /* if linking, also link in runtime libraries (libc, libgcc, etc.) */ + tcc_add_runtime(s1); relocate_common_syms(); - tcc_add_linker_symbols(s1); if (!s1->static_link) { @@ -2057,53 +2045,70 @@ static int elf_output_file(TCCState *s1, const char *filename) if (file_type == TCC_OUTPUT_EXE) { bind_exe_dynsyms(s1); - - if (s1->nb_errors) { - ret = -1; + if (s1->nb_errors) goto the_end; - } - bind_libs_dynsyms(s1); - } else /* shared library case: simply export all global symbols */ + } else { + /* shared library case: simply export all global symbols */ export_global_syms(s1); - - build_got_entries(s1); - - /* add a list of needed dlls */ - for(i = 0; i < s1->nb_loaded_dlls; i++) { - DLLReference *dllref = s1->loaded_dlls[i]; - if (dllref->level == 0) - put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name)); } - - if (s1->rpath) - put_dt(dynamic, s1->enable_new_dtags ? DT_RUNPATH : DT_RPATH, - put_elf_str(dynstr, s1->rpath)); - - /* XXX: currently, since we do not handle PIC code, we - must relocate the readonly segments */ - if (file_type == TCC_OUTPUT_DLL) { - if (s1->soname) - put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname)); - put_dt(dynamic, DT_TEXTREL, 0); - } - - if (s1->symbolic) - put_dt(dynamic, DT_SYMBOLIC, 0); - - /* add necessary space for other entries */ - dyninf.dyn_rel_off = dynamic->data_offset; - dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS; - } else { - /* still need to build got entries in case of static link */ - build_got_entries(s1); } + build_got_entries(s1); } /* we add a section for symbols */ strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0); put_elf_str(strsec, ""); + /* Allocate strings for section names */ + textrel = alloc_sec_names(s1, file_type, strsec); + + if (dynamic) { + /* add a list of needed dlls */ + for(i = 0; i < s1->nb_loaded_dlls; i++) { + DLLReference *dllref = s1->loaded_dlls[i]; + if (dllref->level == 0) + put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name)); + } + + if (s1->rpath) + put_dt(dynamic, s1->enable_new_dtags ? DT_RUNPATH : DT_RPATH, + put_elf_str(dynstr, s1->rpath)); + + if (file_type == TCC_OUTPUT_DLL) { + if (s1->soname) + put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname)); + /* XXX: currently, since we do not handle PIC code, we + must relocate the readonly segments */ + if (textrel) + put_dt(dynamic, DT_TEXTREL, 0); + } + + if (s1->symbolic) + put_dt(dynamic, DT_SYMBOLIC, 0); + + dyninf.dynamic = dynamic; + dyninf.dynstr = dynstr; + /* remember offset and reserve space for 2nd call below */ + dyninf.data_offset = dynamic->data_offset; + fill_dynamic(s1, &dyninf); + dynamic->sh_size = dynamic->data_offset; + dynstr->sh_size = dynstr->data_offset; + } + + /* compute number of program headers */ + if (file_type == TCC_OUTPUT_OBJ) + phnum = 0; + else if (file_type == TCC_OUTPUT_DLL) + phnum = 3; + else if (s1->static_link) + phnum = 2; + else + phnum = 5; + + /* allocate program segment headers */ + phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr))); + /* compute number of sections */ shnum = s1->nb_sections; @@ -2111,41 +2116,16 @@ static int elf_output_file(TCCState *s1, const char *filename) sec_order = tcc_malloc(sizeof(int) * shnum); sec_order[0] = 0; - /* compute number of program headers */ - switch(file_type) { - default: - case TCC_OUTPUT_OBJ: - phnum = 0; - break; - case TCC_OUTPUT_EXE: - if (!s1->static_link) - phnum = 4 + HAVE_PHDR; - else - phnum = 2; - break; - case TCC_OUTPUT_DLL: - phnum = 3; - break; - } - - /* Allocate strings for section names */ - alloc_sec_names(s1, file_type, strsec); - - /* allocate program segment headers */ - phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr))); - /* compute section to program header mapping */ file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf, sec_order); /* Fill remaining program header and finalize relocation related to dynamic linking. */ - if (phnum > 0) { + if (file_type != TCC_OUTPUT_OBJ) { fill_unloadable_phdr(phdr, phnum, interp, dynamic); if (dynamic) { - dyninf.dynamic = dynamic; - dyninf.dynstr = dynstr; - + dynamic->data_offset = dyninf.data_offset; fill_dynamic(s1, &dyninf); /* put in GOT the dynamic section address and relocate PLT */ @@ -2162,22 +2142,20 @@ static int elf_output_file(TCCState *s1, const char *filename) } } } - } - /* if building executable or DLL, then relocate each section - except the GOT which is already relocated */ - if (file_type != TCC_OUTPUT_OBJ) { + /* if building executable or DLL, then relocate each section + except the GOT which is already relocated */ ret = final_sections_reloc(s1); if (ret) goto the_end; tidy_section_headers(s1, sec_order); - } - /* Perform relocation to GOT or PLT entries */ - if (file_type == TCC_OUTPUT_EXE && s1->static_link) - fill_got(s1); - else if (s1->got) - fill_local_got_entries(s1); + /* Perform relocation to GOT or PLT entries */ + if (file_type == TCC_OUTPUT_EXE && s1->static_link) + fill_got(s1); + else if (s1->got) + fill_local_got_entries(s1); + } /* Create the ELF file with name 'filename' */ ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order); diff --git a/tccgen.c b/tccgen.c index 02e40de..7d554b5 100644 --- a/tccgen.c +++ b/tccgen.c @@ -116,6 +116,12 @@ ST_FUNC int ieee_finite(double d) return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31; } +/* compiling intel long double natively */ +#if (defined __i386__ || defined __x86_64__) \ + && (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64) +# define TCC_IS_NATIVE_387 +#endif + ST_FUNC void test_lvalue(void) { if (!(vtop->r & VT_LVAL)) @@ -267,9 +273,6 @@ ST_FUNC int tccgen_compile(TCCState *s1) parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_TOK_STR; next(); decl(VT_CONST); - if (tok != TOK_EOF) - expect("declaration"); - gen_inline_functions(s1); check_vstack(); /* end of translation unit info */ @@ -2411,6 +2414,9 @@ static void gen_cast(CType *type) df = is_float(dbt); c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; p = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM); +#if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_387 + c &= dbt != VT_LDOUBLE; +#endif if (c) { /* constant case: we can do it now */ /* XXX: in ISOC, cannot do it if error in convert */ @@ -3096,6 +3102,8 @@ ST_FUNC void vstore(void) /* ... and discard */ vpop(); } + } else if (dbt == VT_VOID) { + --vtop; } else { #ifdef CONFIG_TCC_BCHECK /* bound check case */ @@ -5925,7 +5933,10 @@ static void block(int *bsym, int *csym, int is_expr) if (tok != ';') { gexpr(); gen_assign_cast(&func_vt); - gfunc_return(&func_vt); + if ((func_vt.t & VT_BTYPE) == VT_VOID) + vtop--; + else + gfunc_return(&func_vt); } skip(';'); /* jump unless last stmt in top-level block */ @@ -6483,7 +6494,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c) *(double *)ptr = vtop->c.d; break; case VT_LDOUBLE: -#if (defined __i386__ || defined __x86_64__) && (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64) +#if defined TCC_IS_NATIVE_387 if (sizeof (long double) >= 10) /* zero pad ten-byte LD */ memcpy(ptr, &vtop->c.ld, 10); #ifdef __TINYC__ @@ -7091,17 +7102,22 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) next(); continue; } - if (l == VT_CONST && - (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) { + if (l != VT_CONST) + break; + if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) { /* global asm block */ asm_global_instr(); continue; } - /* special test for old K&R protos without explicit int - type. Only accepted when defining global data */ - if (l != VT_CONST || tok < TOK_UIDENT) + if (tok >= TOK_UIDENT) { + /* special test for old K&R protos without explicit int + type. Only accepted when defining global data */ + btype.t = VT_INT; + } else { + if (tok != TOK_EOF) + expect("declaration"); break; - btype.t = VT_INT; + } } if (tok == ';') { if ((btype.t & VT_BTYPE) == VT_STRUCT) { diff --git a/tccpe.c b/tccpe.c index 366f0e7..a67023d 100644 --- a/tccpe.c +++ b/tccpe.c @@ -26,10 +26,12 @@ #ifndef _WIN32 #define stricmp strcasecmp #define strnicmp strncasecmp +#include /* chmod() */ #endif #ifdef TCC_TARGET_X86_64 # define ADDR3264 ULONGLONG +# define PE_IMAGE_REL IMAGE_REL_BASED_DIR64 # define REL_TYPE_DIRECT R_X86_64_64 # define R_XXX_THUNKFIX R_X86_64_PC32 # define R_XXX_RELATIVE R_X86_64_RELATIVE @@ -38,6 +40,7 @@ #elif defined TCC_TARGET_ARM # define ADDR3264 DWORD +# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW # define REL_TYPE_DIRECT R_ARM_ABS32 # define R_XXX_THUNKFIX R_ARM_ABS32 # define R_XXX_RELATIVE R_ARM_RELATIVE @@ -46,6 +49,7 @@ #elif defined TCC_TARGET_I386 # define ADDR3264 DWORD +# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW # define REL_TYPE_DIRECT R_386_32 # define R_XXX_THUNKFIX R_386_32 # define R_XXX_RELATIVE R_386_RELATIVE @@ -54,22 +58,6 @@ #endif -#if 0 -#ifdef _WIN32 -void dbg_printf (const char *fmt, ...) -{ - char buffer[4000]; - va_list arg; - int x; - va_start(arg, fmt); - x = vsprintf (buffer, fmt, arg); - strcpy(buffer+x, "\n"); - OutputDebugString(buffer); -} -#endif -#endif - -/* ----------------------------------------------------------- */ #ifndef IMAGE_NT_SIGNATURE /* ----------------------------------------------------------- */ /* definitions below are from winnt.h */ @@ -241,14 +229,19 @@ typedef struct _IMAGE_BASE_RELOCATION { #define IMAGE_REL_BASED_MIPS_JMPADDR 5 #define IMAGE_REL_BASED_SECTION 6 #define IMAGE_REL_BASED_REL32 7 +#define IMAGE_REL_BASED_DIR64 10 #pragma pack(pop) /* ----------------------------------------------------------- */ #endif /* ndef IMAGE_NT_SIGNATURE */ /* ----------------------------------------------------------- */ -#pragma pack(push, 1) +#ifndef IMAGE_REL_BASED_DIR64 +# define IMAGE_REL_BASED_DIR64 10 +#endif + +#pragma pack(push, 1) struct pe_header { IMAGE_DOS_HEADER doshdr; @@ -281,7 +274,6 @@ struct pe_rsrc_reloc { DWORD size; WORD type; }; - #pragma pack(pop) /* ------------------------------------------------------------- */ @@ -732,6 +724,9 @@ static int pe_write(struct pe_info *pe) fseek(op, offsetof(struct pe_header, opthdr.CheckSum), SEEK_SET); pe_fwrite(&pe_header.opthdr.CheckSum, sizeof pe_header.opthdr.CheckSum, op, NULL); fclose (op); +#ifndef _WIN32 + chmod(pe->filename, 0777); +#endif if (2 == pe->s1->verbose) printf("-------------------------------\n"); @@ -1017,7 +1012,7 @@ static void pe_build_reloc (struct pe_info *pe) } if ((addr -= offset) < (1<<12)) { /* one block spans 4k addresses */ WORD *wp = section_ptr_add(pe->reloc, sizeof (WORD)); - *wp = addr | IMAGE_REL_BASED_HIGHLOW<<12; + *wp = addr | PE_IMAGE_REL<<12; ++count; continue; } @@ -1471,7 +1466,7 @@ static void pe_print_sections(TCCState *s1, const char *fname) /* ------------------------------------------------------------- */ /* helper function for load/store to insert one more indirection */ -#ifndef TCC_TARGET_ARM +#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2) { int r2; diff --git a/tccpp.c b/tccpp.c index 3d11dc3..76f9e42 100644 --- a/tccpp.c +++ b/tccpp.c @@ -591,7 +591,7 @@ ST_FUNC int handle_eob(void) /* only tries to read if really end of buffer */ if (bf->buf_ptr >= bf->buf_end) { - if (bf->fd != -1) { + if (bf->fd >= 0) { #if defined(PARSE_DEBUG) len = 1; #else @@ -1803,8 +1803,7 @@ ST_FUNC void preprocess(int is_bof) /* store current file in stack, but increment stack later below */ *s1->include_stack_ptr = file; i = tok == TOK_INCLUDE_NEXT ? file->include_next_index : 0; - n = 2 + s1->nb_tccinclude_paths + s1->nb_include_paths + - s1->nb_sysinclude_paths; + n = 2 + s1->nb_include_paths + s1->nb_sysinclude_paths; for (; i < n; ++i) { char buf1[sizeof file->filename]; CachedInclude *e; @@ -1826,14 +1825,8 @@ ST_FUNC void preprocess(int is_bof) } else { /* search in all the include paths */ - int k, j = i - 2; - - if (j < (k = s1->nb_tccinclude_paths)) - path = s1->tccinclude_paths[j]; - else if ((j -= k) < s1->nb_include_paths) - path = s1->include_paths[j]; - else if ((j -= s1->nb_include_paths) < s1->nb_sysinclude_paths) - path = s1->sysinclude_paths[j]; + int j = i - 2, k = j - s1->nb_include_paths; + path = k < 0 ? s1->include_paths[j] : s1->sysinclude_paths[k]; pstrcpy(buf1, sizeof(buf1), path); pstrcat(buf1, sizeof(buf1), "/"); } @@ -2635,6 +2628,8 @@ static inline void next_nomacro1(void) tcc_close(); s1->include_stack_ptr--; p = file->buf_ptr; + if (p == file->buffer) + tok_flags = TOK_FLAG_BOF|TOK_FLAG_BOL; goto redo_no_start; } } @@ -2968,7 +2963,7 @@ maybe_newline: keep_tok_flags: file->buf_ptr = p; #if defined(PARSE_DEBUG) - printf("token = %s\n", get_tok_str(tok, &tokc)); + printf("token = %d %s\n", tok, get_tok_str(tok, &tokc)); #endif } @@ -3585,7 +3580,8 @@ ST_INLN void unget_tok(int last_tok) ST_FUNC void preprocess_start(TCCState *s1, int is_asm) { - char *buf; + CString cstr; + int i; s1->include_stack_ptr = s1->include_stack; s1->ifdef_stack_ptr = s1->ifdef_stack; @@ -3601,25 +3597,24 @@ ST_FUNC void preprocess_start(TCCState *s1, int is_asm) set_idnum('$', s1->dollars_in_identifiers ? IS_ID : 0); set_idnum('.', is_asm ? IS_ID : 0); - buf = tcc_malloc(3 + strlen(file->filename)); - sprintf(buf, "\"%s\"", file->filename); - tcc_define_symbol(s1, "__BASE_FILE__", buf); - tcc_free(buf); + cstr_new(&cstr); + cstr_cat(&cstr, "\"", -1); + cstr_cat(&cstr, file->filename, -1); + cstr_cat(&cstr, "\"", 0); + tcc_define_symbol(s1, "__BASE_FILE__", cstr.data); - if (s1->nb_cmd_include_files) { - CString cstr; - int i; - cstr_new(&cstr); - for (i = 0; i < s1->nb_cmd_include_files; i++) { - cstr_cat(&cstr, "#include \"", -1); - cstr_cat(&cstr, s1->cmd_include_files[i], -1); - cstr_cat(&cstr, "\"\n", -1); - } + cstr_reset(&cstr); + for (i = 0; i < s1->nb_cmd_include_files; i++) { + cstr_cat(&cstr, "#include \"", -1); + cstr_cat(&cstr, s1->cmd_include_files[i], -1); + cstr_cat(&cstr, "\"\n", -1); + } + if (cstr.size) { *s1->include_stack_ptr++ = file; tcc_open_bf(s1, "", cstr.size); memcpy(file->buffer, cstr.data, cstr.size); - cstr_free(&cstr); } + cstr_free(&cstr); if (is_asm) tcc_define_symbol(s1, "__ASSEMBLER__", NULL); diff --git a/tccrun.c b/tccrun.c index 85957b8..b9a052b 100644 --- a/tccrun.c +++ b/tccrun.c @@ -45,15 +45,13 @@ static void set_exception_handler(void); #endif static void set_pages_executable(void *ptr, unsigned long length); -static int tcc_relocate_ex(TCCState *s1, void *ptr); +static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff); #ifdef _WIN64 static void *win64_add_function_table(TCCState *s1); static void win64_del_function_table(void *); #endif -// #define HAVE_SELINUX - /* ------------------------------------------------------------- */ /* Do all relocations (needed before using tcc_get_symbol()) Returns -1 on error. */ @@ -61,25 +59,36 @@ static void win64_del_function_table(void *); LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) { int size; + addr_t ptr_diff = 0; if (TCC_RELOCATE_AUTO != ptr) - return tcc_relocate_ex(s1, ptr); + return tcc_relocate_ex(s1, ptr, 0); - size = tcc_relocate_ex(s1, NULL); + size = tcc_relocate_ex(s1, NULL, 0); if (size < 0) return -1; #ifdef HAVE_SELINUX - /* Use mmap instead of malloc for Selinux. */ - ptr = mmap (NULL, size, PROT_READ|PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (ptr == MAP_FAILED) - tcc_error("tccrun: could not map memory"); +{ + /* Using mmap instead of malloc */ + void *prx; + char tmpfname[] = "/tmp/.tccrunXXXXXX"; + int fd = mkstemp(tmpfname); + unlink(tmpfname); + ftruncate(fd, size); + + ptr = mmap (NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + prx = mmap (NULL, size, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0); + if (ptr == MAP_FAILED || prx == MAP_FAILED) + tcc_error("tccrun: could not map memory"); dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size); + dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, prx); + ptr_diff = (char*)prx - (char*)ptr; +} #else ptr = tcc_malloc(size); #endif - tcc_relocate_ex(s1, ptr); /* no more errors expected */ + tcc_relocate_ex(s1, ptr, ptr_diff); /* no more errors expected */ dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr); return 0; } @@ -91,6 +100,7 @@ ST_FUNC void tcc_run_free(TCCState *s1) for (i = 0; i < s1->nb_runtime_mem; ++i) { #ifdef HAVE_SELINUX unsigned size = (unsigned)(addr_t)s1->runtime_mem[i++]; + munmap(s1->runtime_mem[i++], size); munmap(s1->runtime_mem[i], size); #else #ifdef _WIN64 @@ -166,7 +176,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) /* relocate code. Return -1 on error, required size if ptr is NULL, otherwise copy code into buffer passed by the caller */ -static int tcc_relocate_ex(TCCState *s1, void *ptr) +static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) { Section *s; unsigned offset, length, fill, i, k; @@ -199,7 +209,12 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr) if (k != !(s->sh_flags & SHF_EXECINSTR)) continue; offset += fill; - s->sh_addr = mem ? mem + offset : 0; + if (!mem) + s->sh_addr = 0; + else if (s->sh_flags & SHF_EXECINSTR) + s->sh_addr = mem + offset + ptr_diff; + else + s->sh_addr = mem + offset; #if 0 if (mem) printf("%-16s +%02lx %p %04x\n", @@ -242,13 +257,15 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr) continue; length = s->data_offset; ptr = (void*)s->sh_addr; + if (s->sh_flags & SHF_EXECINSTR) + ptr = (char*)ptr - ptr_diff; if (NULL == s->data || s->sh_type == SHT_NOBITS) memset(ptr, 0, length); else memcpy(ptr, s->data, length); /* mark executable sections as executable in memory */ if (s->sh_flags & SHF_EXECINSTR) - set_pages_executable(ptr, length); + set_pages_executable((char*)ptr + ptr_diff, length); } return 0; } @@ -263,15 +280,17 @@ static void set_pages_executable(void *ptr, unsigned long length) VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect); #else void __clear_cache(void *beginning, void *end); +# ifndef HAVE_SELINUX addr_t start, end; -#ifndef PAGESIZE -# define PAGESIZE 4096 -#endif +# ifndef PAGESIZE +# define PAGESIZE 4096 +# endif start = (addr_t)ptr & ~(PAGESIZE - 1); end = (addr_t)ptr + length; end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); if (mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC)) tcc_error("mprotect failed: did you mean to configure --with-selinux?"); +# endif # if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 __clear_cache(ptr, (char *)ptr + length); # endif diff --git a/tcctok.h b/tcctok.h index 5380ff3..317f64c 100644 --- a/tcctok.h +++ b/tcctok.h @@ -120,6 +120,8 @@ DEF(TOK_FASTCALL1, "fastcall") DEF(TOK_FASTCALL2, "__fastcall") DEF(TOK_FASTCALL3, "__fastcall__") + DEF(TOK_REGPARM1, "regparm") + DEF(TOK_REGPARM2, "__regparm__") DEF(TOK_MODE, "__mode__") DEF(TOK_MODE_QI, "__QI__") @@ -134,23 +136,19 @@ DEF(TOK_NORETURN2, "__noreturn__") DEF(TOK_VISIBILITY1, "visibility") DEF(TOK_VISIBILITY2, "__visibility__") + DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p") DEF(TOK_builtin_choose_expr, "__builtin_choose_expr") DEF(TOK_builtin_constant_p, "__builtin_constant_p") DEF(TOK_builtin_frame_address, "__builtin_frame_address") DEF(TOK_builtin_return_address, "__builtin_return_address") DEF(TOK_builtin_expect, "__builtin_expect") -#ifdef TCC_TARGET_X86_64 -#ifdef TCC_TARGET_PE + /*DEF(TOK_builtin_va_list, "__builtin_va_list")*/ +#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64 DEF(TOK_builtin_va_start, "__builtin_va_start") -#else +#elif defined TCC_TARGET_X86_64 DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types") -#endif -#endif - DEF(TOK_REGPARM1, "regparm") - DEF(TOK_REGPARM2, "__regparm__") - -#ifdef TCC_TARGET_ARM64 +#elif defined TCC_TARGET_ARM64 DEF(TOK___va_start, "__va_start") DEF(TOK___va_arg, "__va_arg") #endif diff --git a/tests/Makefile b/tests/Makefile index 39dee7f..6a61717 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -234,8 +234,12 @@ vla_test-run: vla_test$(EXESUF) cross-test : @echo ------------ $@ ------------ $(TOP)/i386-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok" + $(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/examples/ex3.c && echo "ok" $(TOP)/x86_64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok" + $(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/examples/ex3.c && echo "ok" $(TOP)/arm-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok" + $(TOP)/arm-wince-tcc$(EXESUF) $(TCCFLAGS-win) -c $(TOPSRC)/examples/ex3.c && echo "ok" + $(TOP)/arm64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok" $(TOP)/c67-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok" $(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok" $(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok" diff --git a/tests/pp/13.expect b/tests/pp/13.expect index 6eb2bec..c7a3230 100644 --- a/tests/pp/13.expect +++ b/tests/pp/13.expect @@ -1,3 +1,2 @@ -# `modelist' label. Each video mode record looks like: .text endtext: diff --git a/tests/pp/15.c b/tests/pp/15.c index 3bbc3ca..cf13f9a 100644 --- a/tests/pp/15.c +++ b/tests/pp/15.c @@ -12,7 +12,7 @@ return n(A)n(++)n(+)n(+)n(B); return n(0x1E)n(-1); // unlike gcc but correct -XXX: return n(x)+n(x)-n(1)+n(1)-2; +// XXX: return n(x)+n(x)-n(1)+n(1)-2; // unlike gcc, but cannot appear in valid C -XXX: return n(x)n(x)n(1)n(2)n(x); +// XXX: return n(x)n(x)n(1)n(2)n(x); diff --git a/tests/pp/15.expect b/tests/pp/15.expect index f652240..b4f885e 100644 --- a/tests/pp/15.expect +++ b/tests/pp/15.expect @@ -3,5 +3,3 @@ return A+++B; return A+ ++B; return A+++ +B; return 0x1E -1; -XXX: return x+x-1 +1 -2; -XXX: return x x 1 2 x; diff --git a/tests/pp/Makefile b/tests/pp/Makefile index 21c9969..687aa52 100644 --- a/tests/pp/Makefile +++ b/tests/pp/Makefile @@ -12,7 +12,7 @@ TESTS = $(call files,c) $(call files,S) all test : $(sort $(TESTS)) -DIFF_OPTS = -Nu -b -B -I "^\#" +DIFF_OPTS = -Nu -b -B # Filter source directory in warnings/errors (out-of-tree builds) FILTER = 2>&1 | sed 's,$(SRC)/,,g' @@ -40,7 +40,7 @@ clean: rm -f *.output 02.test : DIFF_OPTS += -w -15.test : DIFF_OPTS += -I"^XXX:" +# 15.test : DIFF_OPTS += -I"^XXX:" # diff options: # -b ighore space changes diff --git a/tests/tcctest.c b/tests/tcctest.c index 7877243..099fc35 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -3235,6 +3235,7 @@ void asm_local_statics (void) } #endif +static unsigned int set; void fancy_copy (unsigned *in, unsigned *out) @@ -3247,7 +3248,7 @@ void fancy_copy2 (unsigned *in, unsigned *out) asm volatile ("mov %0,(%1)" : : "r" (*in), "r" (out) : "memory"); } -#ifdef __x86_64__ +#if defined __x86_64__ && !defined _WIN64 void clobber_r12(void) { asm volatile("mov $1, %%r12" ::: "r12"); @@ -3256,7 +3257,7 @@ void clobber_r12(void) void test_high_clobbers(void) { -#ifdef __x86_64__ +#if defined __x86_64__ && !defined _WIN64 register long val asm("r12"); long val2; /* This tests if asm clobbers correctly save/restore callee saved @@ -3265,11 +3266,9 @@ void test_high_clobbers(void) correctly capture the data flow, but good enough for us. */ asm volatile("mov $0x4542, %%r12" : "=r" (val):: "memory"); clobber_r12(); -#ifndef _WIN64 asm volatile("mov %%r12, %0" : "=r" (val2) : "r" (val): "memory"); printf("asmhc: 0x%x\n", val2); #endif -#endif } static long cpu_number; diff --git a/tests/tests2/95_bitfields.c b/tests/tests2/95_bitfields.c index 683becf..f025c57 100644 --- a/tests/tests2/95_bitfields.c +++ b/tests/tests2/95_bitfields.c @@ -70,7 +70,7 @@ { struct M P __s { int a; - char b; + signed char b; int x : 12, y : 4, : 0, : 4, z : 3; char d; }; diff --git a/tests/tests2/96_nodata_wanted.c b/tests/tests2/96_nodata_wanted.c index b594938..cc211d3 100644 --- a/tests/tests2/96_nodata_wanted.c +++ b/tests/tests2/96_nodata_wanted.c @@ -78,7 +78,7 @@ te1:; tl += &&te1 - &&ts1; printf("size of data/text:\n %s/%s\n", dl ? "non-zero":"zero", tl ? "non-zero":"zero"); - printf("# %d/%d\n", dl, tl); + /*printf("# %d/%d\n", dl, tl);*/ } #endif diff --git a/tests/tests2/96_nodata_wanted.expect b/tests/tests2/96_nodata_wanted.expect index 6e54f24..2749109 100644 --- a/tests/tests2/96_nodata_wanted.expect +++ b/tests/tests2/96_nodata_wanted.expect @@ -17,9 +17,7 @@ data: 333 44 555555 6 7 size of data/text: non-zero/non-zero -# 111/193 [test_data_suppression_on] size of data/text: zero/zero -# 0/0 diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 6bff618..190b2d9 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -70,7 +70,7 @@ all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ; T1 = $(TCC) $(FLAGS) $< -o a.exe && ./a.exe $(ARGS) T2 = $(TCC) $(FLAGS) -run $< $(ARGS) T3 = $(FILTER) >$*.output 2>&1 || true \ - && diff -Nbu -I "^\#" $(filter %.expect,$^) $*.output \ + && diff -Nbu $(filter %.expect,$^) $*.output \ && rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS)) # run single test and update .expect file, e.g. "make tests2.37+" diff --git a/win32/Makefile b/win32/Makefile deleted file mode 100644 index 5bd60bd..0000000 --- a/win32/Makefile +++ /dev/null @@ -1,148 +0,0 @@ -# -# This Makefile builds native Windows tcc for both 32 and 64 bits generator. -# It requires Cygwin 64 and gcc to bootstrap a first tcc version which is used -# by a second stage to compile tcc it self. -# Generated binaries do not require cygwin to run. -# You can launch 'tarball' target to build a tar.gz you can install on any -# Windows machines. - -CPU = $(shell if `gcc -v 2>&1 | grep Target | grep -q x86_64`; then echo 64; else echo 32; fi) -VERSION = $(shell cat ../VERSION) -BOOTCC = gcc -CFLAGS = -s -static -fno-strict-aliasing -Wno-incompatible-pointer-types -DTCC_TARGET_PE -#WINPWD = `cygpath --mixed $(PWD)` -#@echo "#define CONFIG_TCCDIR \"$(WINPWD)\"" - -ifeq ($(CPU), 64) -NATIVE = -m$(CPU) -DTCC_TARGET_X86_64 -ARCH = x86_64 -else -NATIVE = -m$(CPU) -DTCC_TARGET_I386 -ARCH = i386 -endif - -TARGET = $(CPU) - -ifeq ($(TARGET), 64) -TFLAGS = -m$(TARGET) -DTCC_TARGET_X86_64 -TARCH = x86_64 -else -TFLAGS = -m$(TARGET) -DTCC_TARGET_I386 -TARCH = i386 -endif - -all: pre bootstrap libs rebuild - @chmod 775 *.exe - @ls -ls *.exe - -pre: - @echo ARCH=$(TARCH) 1> ../config.mak - @echo TARGETOS=Windows 1>> ../config.mak - @echo CONFIG_WIN32=yes 1>> ../config.mak - @echo TOPSRC=$$\(TOP\) 1>> ../config.mak - @echo "#define TCC_VERSION \"$(VERSION)\"" 1>../config.h - @echo "#ifdef TCC_TARGET_X86_64" 1>>../config.h - @echo "#define TCC_LIBTCC1 \"libtcc1-64.a\"" 1>>../config.h - @echo "#else" 1>>../config.h - @echo "#define TCC_LIBTCC1 \"libtcc1-32.a\"" 1>>../config.h - @echo "#endif" 1>>../config.h - @echo @set VERSION $(VERSION) 1>../config.texi - @rm -f *tcc.exe tiny_*.exe *tcc.dll lib/*.a - @rm -r -f libtcc doc - @mkdir libtcc - @mkdir doc - @cp ../include/*.h include - @cp ../tcclib.h include - @cp ../libtcc.h include - @cp tcc-win32.txt doc - @cp ../tests/libtcc_test.c examples - -PHONY += pre - -bootstrap: - @echo Bootstrapping 32bits and 64bits tools with $(BOOTCC) -m$(CPU) - @$(BOOTCC) $(CFLAGS) -DTCC_TARGET_I386 -o i386-win32-tcc.exe ../tcc.c - @$(BOOTCC) $(CFLAGS) -DTCC_TARGET_X86_64 -o x86_64-win32-tcc.exe ../tcc.c - @$(BOOTCC) $(CFLAGS) $(NATIVE) -o tcc.exe ../tcc.c - @$(BOOTCC) $(CFLAGS) $(NATIVE) -DLIBTCC_AS_DLL -o libtcc.dll -shared ../libtcc.c - -PHONY += bootstrap - -lib/libtcc1-32.a: - @echo Building $*.a with tcc -m32 - @./tcc -O2 -B. -m32 -DTCC_TARGET_PE -DTCC_TARGET_I386 -c ../lib/libtcc1.c - @./tcc -O2 -B. -m32 -DTCC_TARGET_PE -DTCC_TARGET_I386 -c ../lib/alloca86.S - @./tcc -O2 -B. -m32 -DTCC_TARGET_PE -DTCC_TARGET_I386 -c ../lib/alloca86-bt.S - @./tcc -O2 -B. -m32 -DTCC_TARGET_PE -DTCC_TARGET_I386 -c lib/crt1.c - @./tcc -O2 -B. -m32 -DTCC_TARGET_PE -DTCC_TARGET_I386 -c lib/crt1w.c - @./tcc -O2 -B. -m32 -DTCC_TARGET_PE -DTCC_TARGET_I386 -c lib/wincrt1.c - @./tcc -O2 -B. -m32 -DTCC_TARGET_PE -DTCC_TARGET_I386 -c lib/wincrt1w.c - @./tcc -O2 -B. -m32 -DTCC_TARGET_PE -DTCC_TARGET_I386 -c lib/dllcrt1.c - @./tcc -O2 -B. -m32 -DTCC_TARGET_PE -DTCC_TARGET_I386 -c lib/dllmain.c - @./tcc -O2 -B. -m32 -DTCC_TARGET_PE -DTCC_TARGET_I386 -c lib/chkstk.S - @./tcc -m32 -ar lib/libtcc1-32.a libtcc1.o alloca86.o alloca86-bt.o crt1.o wincrt1.o crt1w.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o - @rm *.o - -lib/libtcc1-64.a: - @echo Building $*.a with tcc -m64 - @./tcc -O2 -B. -m64 -DTCC_TARGET_PE -DTCC_TARGET_X86_64 -c ../lib/libtcc1.c - @./tcc -O2 -B. -m64 -DTCC_TARGET_PE -DTCC_TARGET_X86_64 -c ../lib/alloca86_64.S - @./tcc -O2 -B. -m64 -DTCC_TARGET_PE -DTCC_TARGET_X86_64 -c ../lib/alloca86_64-bt.S - @./tcc -O2 -B. -m64 -DTCC_TARGET_PE -DTCC_TARGET_X86_64 -c lib/crt1.c - @./tcc -O2 -B. -m64 -DTCC_TARGET_PE -DTCC_TARGET_X86_64 -c lib/crt1w.c - @./tcc -O2 -B. -m64 -DTCC_TARGET_PE -DTCC_TARGET_X86_64 -c lib/wincrt1.c - @./tcc -O2 -B. -m64 -DTCC_TARGET_PE -DTCC_TARGET_X86_64 -c lib/wincrt1w.c - @./tcc -O2 -B. -m64 -DTCC_TARGET_PE -DTCC_TARGET_X86_64 -c lib/dllcrt1.c - @./tcc -O2 -B. -m64 -DTCC_TARGET_PE -DTCC_TARGET_X86_64 -c lib/dllmain.c - @./tcc -O2 -B. -m64 -DTCC_TARGET_PE -DTCC_TARGET_X86_64 -c lib/chkstk.S - @./tcc -m64 -ar lib/libtcc1-64.a libtcc1.o alloca86_64.o alloca86_64-bt.o crt1.o wincrt1.o crt1w.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o - @rm *.o - -libs: lib/libtcc1-32.a lib/libtcc1-64.a - -PHONY += libs - -rebuild: - @echo Rebuild using tcc itself - default $(TARGET)bits - @./$(TARCH)-win32-tcc -O2 -B. $(TFLAGS) -DTCC_TARGET_PE -o tcc.exe ../tcc.c - @./tcc -O2 -B. $(TFLAGS) -DTCC_TARGET_PE -DLIBTCC_AS_DLL -o libtcc.dll -shared ../libtcc.c - @./tcc -O2 -B. -m32 -DTCC_TARGET_PE -DTCC_TARGET_I386 -o tmp-tcc.exe ../tcc.c && mv tmp-tcc.exe i386-win32-tcc.exe - @./tcc -O2 -B. -m$(TARGET) -DTCC_TARGET_PE -DTCC_TARGET_X86_64 -o tmp-tcc.exe ../tcc.c && mv tmp-tcc.exe x86_64-win32-tcc.exe - -PHONY += rebuild - -test: - @(cd ../tests; $(MAKE) -k TCC=$(PWD)/tcc hello-exe hello-run) - @(cd ../tests; $(MAKE) -k TCC=$(PWD)/tcc vla_test-run tests2-dir pp-dir) -ifeq ($(CPU), 64) - @(cd ../tests; $(MAKE) -k TCC=$(PWD)/i386-win32-tcc hello-exe hello-run) - @(cd ../tests; $(MAKE) -k TCC=$(PWD)/i386-win32-tcc vla_test-run tests2-dir pp-dir) -endif - -PHONY += test - -TARNAME = tcc-$(VERSION)-$(ARCH)-win32 - -tarball: - @rm -r -f $(TARNAME) - @mkdir $(TARNAME) - @cp -r doc $(TARNAME) - @cp -r examples $(TARNAME) - @cp -r include $(TARNAME) - @cp -r lib $(TARNAME) - @cp -r libtcc $(TARNAME) - @cp -r build-tcc.bat $(TARNAME) - @cp -r i386-win32-tcc.exe $(TARNAME) - @cp -r libtcc.def $(TARNAME) - @cp -r libtcc.dll $(TARNAME) - @cp -r Makefile $(TARNAME) - @cp -r tcc.exe $(TARNAME) - @cp -r tcc-win32.txt $(TARNAME) - @cp -r x86_64-win32-tcc.exe $(TARNAME) - @tar czf $(TARNAME).tar.gz $(TARNAME) - @rm -r -f $(TARNAME) - -PHONY += tarball - -clean: - rm -f *.o *.exe *.dll lib/*.a *.pdb *.obj *.exp *.def *.lib diff --git a/win32/build-tcc.bat b/win32/build-tcc.bat index 3c3a726..ceb4411 100644 --- a/win32/build-tcc.bat +++ b/win32/build-tcc.bat @@ -4,13 +4,31 @@ @echo off setlocal - -set CC=gcc -Os -s -static +if (%1)==(-clean) goto :cleanup +set CC=gcc set /p VERSION= < ..\VERSION set INST= +set BIN= set DOC=no +set EXES_ONLY=no goto :a0 - +:a2 +shift +:a3 +shift +:a0 +if not (%1)==(-c) goto :a1 +set CC=%~2 +if (%2)==(cl) set CC=@call :cl +goto :a2 +:a1 +if (%1)==(-t) set T=%2&& goto :a2 +if (%1)==(-v) set VERSION=%~2&& goto :a2 +if (%1)==(-i) set INST=%2&& goto :a2 +if (%1)==(-b) set BIN=%2&& goto :a2 +if (%1)==(-d) set DOC=yes&& goto :a3 +if (%1)==(-x) set EXES_ONLY=yes&& goto :a3 +if (%1)==() goto :p1 :usage echo usage: build-tcc.bat [ options ... ] echo options: @@ -18,10 +36,35 @@ 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 -v "version" set tcc version -echo -i dir install tcc into dir +echo -i tccdir install tcc into tccdir +echo -b bindir optionally install binaries into bindir elsewhere echo -d create tcc-doc.html too (needs makeinfo) +echo -x just create the executables +echo -clean delete all previously produced files and directories exit /B 1 +@rem ------------------------------------------------------ +@rem sub-routines + +:cleanup +set LOG=echo +%LOG% removing files: +for %%f in (*tcc.exe libtcc.dll lib\*.a) do call :del_file %%f +for %%f in (..\config.h ..\config.texi) do call :del_file %%f +for %%f in (include\*.h) do @if exist ..\%%f call :del_file %%f +for %%f in (include\tcclib.h examples\libtcc_test.c) do call :del_file %%f +for %%f in (*.o *.obj *.def *.pdb *.lib *.exp *.ilk) do call :del_file %%f +%LOG% removing directories: +for %%f in (doc libtcc) do call :del_dir %%f +%LOG% done. +exit /B 0 +:del_file +if exist %1 del %1 && %LOG% %1 +exit /B 0 +:del_dir +if exist %1 rmdir /Q/S %1 && %LOG% %1 +exit /B 0 + :cl @echo off set CMD=cl @@ -37,52 +80,16 @@ echo on %CMD% -O1 -W2 -Zi -MT -GS- -nologo -link -opt:ref,icf @exit /B %ERRORLEVEL% -:a2 -shift -:a1 -shift -:a0 -if not (%1)==(-c) goto :a3 -set CC=%~2 -if (%2)==(cl) set CC=@call :cl -goto :a2 -:a3 -if not (%1)==(-t) goto :a4 -set T=%2 -goto :a2 -:a4 -if not (%1)==(-v) goto :a5 -set VERSION=%~2 -goto :a2 -:a5 -if not (%1)==(-i) goto :a6 -set INST=%2 -goto :a2 -:a6 -if not (%1)==(-d) goto :a7 -set DOC=yes -goto :a1 -:a7 -if not (%1)==() goto :usage +@rem ------------------------------------------------------ +@rem main program -if not "%CC%"=="@call :cl" goto :p1 -set VSCOMNTOOLS=%VS150COMNTOOLS% -if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS% -if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS% -if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS% -if %T%_==32_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\vcvars32.bat" -if %T%_==64_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\amd64\vcvars64.bat" -if %T%_==_ set T=32& if %Platform%_==X64_ set T=64 -if %CLVARS%_==_ goto :p1 -if exist %CLVARS% call %CLVARS% :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% -Os -s -static set D32=-DTCC_TARGET_PE -DTCC_TARGET_I386 set D64=-DTCC_TARGET_PE -DTCC_TARGET_X86_64 set P32=i386-win32 @@ -91,13 +98,14 @@ if %T%==64 goto :t64 set D=%D32% set DX=%D64% set PX=%P64% -goto :t96 +goto :p3 :t64 set D=%D64% set DX=%D32% set PX=%P32% -:t96 +goto :p3 +:p3 @echo on :config.h @@ -116,7 +124,7 @@ for %%f in (*tcc.exe *tcc.dll) do @del %%f %CC% -o tcc.exe ..\tcc.c libtcc.dll %D% -DONE_SOURCE"=0" %CC% -o %PX%-tcc.exe ..\tcc.c %DX% -@if (%TCC_FILES%)==(no) goto :files-done +@if (%EXES_ONLY%)==(yes) goto :files-done if not exist libtcc mkdir libtcc if not exist doc mkdir doc @@ -170,8 +178,11 @@ for %%f in (*.o *.def) do @del %%f :copy-install @if (%INST%)==() goto :the_end if not exist %INST% mkdir %INST% +@if (%BIN%)==() set BIN=%INST% +if not exist %BIN% mkdir %BIN% +for %%f in (*tcc.exe *tcc.dll) do @copy>nul %%f %BIN%\%%f @if not exist %INST%\lib mkdir %INST%\lib -for %%f in (*tcc.exe *tcc.dll lib\*.a lib\*.def) do @copy>nul %%f %INST%\%%f +for %%f in (lib\*.a lib\*.def) do @copy>nul %%f %INST%\%%f for %%f in (include examples libtcc doc) do @xcopy>nul /s/i/q/y %%f %INST%\%%f :the_end diff --git a/win32/lib/crt1.c b/win32/lib/crt1.c index 53e5545..0e04fc0 100644 --- a/win32/lib/crt1.c +++ b/win32/lib/crt1.c @@ -16,11 +16,6 @@ #define _PC_53 0x00010000 // 53 bits #define _PC_64 0x00000000 // 64 bits -typedef struct -{ - int newmode; -} _startupinfo; - #ifdef _UNICODE #define __tgetmainargs __wgetmainargs #define _tstart _wstart @@ -33,6 +28,7 @@ typedef struct #define _runtmain _runmain #endif +typedef struct { int newmode; } _startupinfo; int __cdecl __tgetmainargs(int *pargc, _TCHAR ***pargv, _TCHAR ***penv, int globb, _startupinfo*); void __cdecl __set_app_type(int apptype); unsigned int __cdecl _controlfp(unsigned int new_value, unsigned int mask); @@ -44,23 +40,19 @@ int _dowildcard; void _tstart(void) { __TRY__ - int ret; - _startupinfo start_info; + _startupinfo start_info = {0}; // Sets the current application type __set_app_type(_CONSOLE_APP); // Set default FP precision to 53 bits (8-byte double) - // _MCW_PC (Precision control) is not supported on - // the ARM and x64 architectures -#ifdef __i386 + // _MCW_PC (Precision control) is not supported on ARM +#if defined __i386__ || defined __x86_64__ _controlfp(_PC_53, _MCW_PC); #endif - start_info.newmode = 0; __tgetmainargs( &__argc, &__targv, &_tenviron, _dowildcard, &start_info); - ret = _tmain(__argc, __targv, _tenviron); - exit(ret); + exit(_tmain(__argc, __targv, _tenviron)); } int _runtmain(int argc, /* as tcc passed in */ char **argv) @@ -78,8 +70,7 @@ int _runtmain(int argc, /* as tcc passed in */ char **argv) __argc = argc; __targv = argv; #endif - -#ifdef __i386 +#if defined __i386__ || defined __x86_64__ _controlfp(_PC_53, _MCW_PC); #endif return _tmain(__argc, __targv, _tenviron); diff --git a/win32/lib/wincrt1.c b/win32/lib/wincrt1.c index 83e2f74..ce3a63f 100644 --- a/win32/lib/wincrt1.c +++ b/win32/lib/wincrt1.c @@ -23,71 +23,53 @@ int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int); #define _runtwinmain _runwinmain #endif -typedef struct -{ - int newmode; -} _startupinfo; // CLI Vs GUI - +typedef struct { int newmode; } _startupinfo; int __cdecl __tgetmainargs(int *pargc, _TCHAR ***pargv, _TCHAR ***penv, int globb, _startupinfo*); +static int go_winmain(TCHAR *arg1) +{ + STARTUPINFO si; + _TCHAR *szCmd, *p; + int fShow; + + GetStartupInfo(&si); + if (si.dwFlags & STARTF_USESHOWWINDOW) + fShow = si.wShowWindow; + else + fShow = SW_SHOWDEFAULT; + + szCmd = NULL, p = GetCommandLine(); + if (arg1) + szCmd = _tcsstr(p, arg1); + if (NULL == szCmd) + szCmd = _tcsdup(__T("")); + else if (szCmd > p && szCmd[-1] == __T('"')) + --szCmd; +#if defined __i386__ || defined __x86_64__ + _controlfp(0x10000, 0x30000); +#endif + return _tWinMain(GetModuleHandle(NULL), NULL, szCmd, fShow); +} + int _twinstart(void) { __TRY__ - _TCHAR *szCmd, *p; - STARTUPINFO startinfo; _startupinfo start_info_con = {0}; - int fShow; - int ret; - __set_app_type(__GUI_APP); - _controlfp(0x10000, 0x30000); - - start_info_con.newmode = 0; __tgetmainargs(&__argc, &__targv, &_tenviron, 0, &start_info_con); - - p = GetCommandLine(); - if (__argc > 1) - szCmd = _tcsstr(p, __targv[1]); - if (NULL == szCmd) - szCmd = __T(""); - else if (szCmd > p && szCmd[-1] == __T('\"')) - --szCmd; - - GetStartupInfo(&startinfo); - fShow = startinfo.wShowWindow; - if (0 == (startinfo.dwFlags & STARTF_USESHOWWINDOW)) - fShow = SW_SHOWDEFAULT; - - ret = _tWinMain(GetModuleHandle(NULL), NULL, szCmd, fShow); - exit(ret); + exit(go_winmain(__argc > 1 ? __targv[1] : NULL)); } int _runtwinmain(int argc, /* as tcc passed in */ char **argv) { - _TCHAR *szCmd, *p; - #ifdef UNICODE _startupinfo start_info = {0}; - __tgetmainargs(&__argc, &__targv, &_tenviron, 0, &start_info); /* may be wrong when tcc has received wildcards (*.c) */ - if (argc < __argc) { - __targv += __argc - argc; - __argc = argc; - } + if (argc < __argc) + __targv += __argc - argc, __argc = argc; #else - __argc = argc; - __targv = argv; + __argc = argc, __targv = argv; #endif - - p = GetCommandLine(); - szCmd = NULL; - if (argc > 1) - szCmd = _tcsstr(p, __targv[1]); - if (NULL == szCmd) - szCmd = __T(""); - else if (szCmd > p && szCmd[-1] == __T('\"')) - --szCmd; - _controlfp(0x10000, 0x30000); - return _tWinMain(GetModuleHandle(NULL), NULL, szCmd, SW_SHOWDEFAULT); + return go_winmain(__argc > 1 ? __targv[1] : NULL); } diff --git a/win32/tcc-win32.txt b/win32/tcc-win32.txt index 3609684..751a8e0 100644 --- a/win32/tcc-win32.txt +++ b/win32/tcc-win32.txt @@ -108,6 +108,8 @@ ------------------------ * You can use the MinGW and MSYS tools available at http://www.mingw.org + http://www.mingw-w64.org + http://www.msys2.org Untar the TCC archive and type in the MSYS shell: ./configure [--prefix installpath] @@ -116,29 +118,22 @@ The default install location is c:\Program Files\tcc + Cygwin can be used too with its mingw cross-compiler installed: + ./configure --cross-prefix=i686-w64-mingw32- + (the prefix may vary) + * Alternatively you can compile TCC with just GCC from MinGW using > build-tcc.bat (from the win32 directory) Also MSVC can be used with the "VSTools Developer Command Prompt": > build-tcc.bat -c cl - or with a tcc (needs to be in a different directory) + or with an existing tcc (needs to be in a different directory) > build-tcc.bat -c some-tcc-dir\tcc.exe Also you can copy/install everything into another directory: > build-tcc.bat -i - * You can also bootstrap a native tcc Windows toolchain with cygwin. - https://www.cygwin.com/ - - Install Base, gcc, make - Launch Cygwin Terminal - > make - or to force 32bit executables (including 64bit backend) - > make TARGET=32 - or to force 64bit executables (including 32bit backend) - > make TARGET=64 - Limitations: ------------ - On the object file level, currently TCC supports only the ELF format,