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=<old-tccdir>/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 1d5e386b0a.

  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=<tcc program to use>
- use $(wildcard ...) for install to allow installing just
  a cross compiler for example
      make cross-arm
      make install
- use name <target>-libtcc1.a

build-tcc.bat:
- add  options: -clean, -b bindir
master
grischka 2017-10-11 18:13:43 +02:00
parent faa9744f5d
commit da8c62f75d
30 changed files with 433 additions and 663 deletions

113
Makefile
View File

@ -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 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)) 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 # build cross compilers & libs
cross: $(LIBTCC1_CROSS) $(PROGS_CROSS) cross: $(LIBTCC1_CROSS) $(PROGS_CROSS)
# build specific cross compiler & lib # build specific cross compiler & lib
cross-%: %-tcc$(EXESUF) libtcc1-%.a ; cross-%: %-tcc$(EXESUF) %-libtcc1.a ;
install: install$(CFGWIN) install: ; @$(MAKE) --no-print-directory install$(CFGWIN)
uninstall: uninstall$(CFGWIN) install-strip: ; @$(MAKE) --no-print-directory install$(CFGWIN) CONFIG_strip=yes
uninstall: ; @$(MAKE) --no-print-directory uninstall$(CFGWIN)
ifdef CONFIG_cross ifdef CONFIG_cross
all : cross all : cross
@ -143,10 +144,10 @@ DEFINES += $(DEF-$(or $(findstring win,$T),unx))
ifneq ($(X),) ifneq ($(X),)
ifeq ($(CONFIG_WIN32),yes) ifeq ($(CONFIG_WIN32),yes)
DEF-win += -DTCC_LIBTCC1="\"libtcc1-$T.a\"" DEF-win += -DTCC_LIBTCC1="\"$(X)libtcc1.a\""
DEF-unx += -DTCC_LIBTCC1="\"lib/libtcc1-$T.a\"" DEF-unx += -DTCC_LIBTCC1="\"lib/$(X)libtcc1.a\""
else else
DEF-all += -DTCC_LIBTCC1="\"libtcc1-$T.a\"" DEF-all += -DTCC_LIBTCC1="\"$(X)libtcc1.a\""
DEF-win += -DCONFIG_TCCDIR="\"$(tccdir)/win32\"" DEF-win += -DCONFIG_TCCDIR="\"$(tccdir)/win32\""
endif endif
endif endif
@ -217,21 +218,22 @@ libtcc.so: LDFLAGS+=-fPIC
# windows dynamic libtcc library # windows dynamic libtcc library
libtcc.dll : $(LIBTCC_OBJ) libtcc.dll : $(LIBTCC_OBJ)
$(CC) -shared -o $@ $^ $(LDFLAGS) $(CC) -shared -o $@ $^ $(LDFLAGS)
libtcc.def : libtcc.dll tcc$(EXESUF)
./tcc$(EXESUF) -impdef $< -o $@
libtcc.dll : DEFINES += -DLIBTCC_AS_DLL 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 # TinyCC runtime libraries
libtcc1.a : tcc$(EXESUF) FORCE libtcc1.a : tcc$(EXESUF) FORCE
@$(MAKE) -C lib DEFINES="$(DEF-$T)" @$(MAKE) -C lib DEFINES='$(DEF-$T)'
# Cross libtcc1.a # Cross libtcc1.a
libtcc1-%.a : %-tcc$(EXESUF) FORCE %-libtcc1.a : %-tcc$(EXESUF) FORCE
@$(MAKE) -C lib DEFINES="$(DEF-$*)" CROSS_TARGET=$* @$(MAKE) -C lib DEFINES='$(DEF-$*)' CROSS_TARGET=$*
.PRECIOUS: libtcc1-%.a .PRECIOUS: %-libtcc1.a
FORCE: FORCE:
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
@ -252,35 +254,29 @@ tcc-doc.info: tcc-doc.texi
INSTALL = install -m644 INSTALL = install -m644
INSTALLBIN = install -m755 $(STRIP_$(CONFIG_strip)) INSTALLBIN = install -m755 $(STRIP_$(CONFIG_strip))
STRIP_yes = -s STRIP_yes = -s
install-strip: install
install-strip: CONFIG_strip = yes
TRY-INSTALL = $(if $(wildcard $1),mkdir -p $2 && $(INSTALL) $1 $2) LIBTCC1_W = $(filter %-win32-libtcc1.a %-wince-libtcc1.a,$(LIBTCC1_CROSS))
LIBTCC1_W = $(wildcard $(filter %-win32.a %-wince.a,$(LIBTCC1_CROSS))) LIBTCC1_U = $(filter-out $(LIBTCC1_W),$(LIBTCC1_CROSS))
LIBTCC1_U = $(wildcard $(filter-out $(LIBTCC1_W),$(LIBTCC1_CROSS))) IB = $(if $1,mkdir -p $2 && $(INSTALLBIN) $1 $2)
PROGS_X = $(wildcard $(PROGS_CROSS)) 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 progs & libs
install-unx: install-unx:
mkdir -p "$(bindir)" $(call IBw,$(PROGS) $(PROGS_CROSS),"$(bindir)")
$(INSTALLBIN) $(PROGS) $(PROGS_X) "$(bindir)" $(call IFw,$(LIBTCC1) $(LIBTCC1_U),"$(tccdir)")
mkdir -p "$(tccdir)" $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
$(INSTALL) $(LIBTCC1) $(LIBTCC1_U) "$(tccdir)" $(call $(if $(findstring .so,$(LIBTCC)),IBw,IFw),$(LIBTCC),"$(libdir)")
mkdir -p "$(tccdir)/include" $(call IF,$(TOPSRC)/libtcc.h,"$(includedir)")
$(INSTALL) $(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h "$(tccdir)/include" $(call IFw,tcc.1,"$(mandir)/man1")
mkdir -p "$(libdir)" $(call IFw,tcc-doc.info,"$(infodir)")
$(INSTALL) $(LIBTCC) "$(libdir)" $(call IFw,tcc-doc.html,"$(docdir)")
mkdir -p "$(includedir)" ifneq "$(wildcard $(LIBTCC1_W))" ""
$(INSTALL) $(TOPSRC)/libtcc.h "$(includedir)" $(call IFw,$(TOPSRC)/win32/lib/*.def $(LIBTCC1_W),"$(tccdir)/win32/lib")
$(call TRY-INSTALL,tcc.1,"$(mandir)/man1") $(call IR,$(TOPSRC)/win32/include,"$(tccdir)/win32/include")
$(call TRY-INSTALL,tcc-doc.info,"$(infodir)") $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/win32/include")
$(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"
endif endif
# uninstall # uninstall
@ -293,32 +289,31 @@ uninstall-unx:
# install progs & libs on windows # install progs & libs on windows
install-win: install-win:
mkdir -p "$(tccdir)" $(call IBw,$(PROGS) $(PROGS_CROSS) $(subst libtcc.a,,$(LIBTCC)),"$(bindir)")
$(INSTALL) $(PROGS) $(subst libtcc.a,,$(LIBTCC)) $(PROGS_X) "$(tccdir)" $(call IF,$(TOPSRC)/win32/lib/*.def,"$(tccdir)/lib")
mkdir -p "$(tccdir)/lib" $(call IFw,libtcc1.a $(LIBTCC1_W),"$(tccdir)/lib")
$(INSTALL) $(TOPSRC)/win32/lib/*.def "$(tccdir)/lib" $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
$(INSTALL) libtcc1.a $(LIBTCC1_W) "$(tccdir)/lib" $(call IR,$(TOPSRC)/win32/include,"$(tccdir)/include")
mkdir -p "$(tccdir)/include" $(call IR,$(TOPSRC)/win32/examples,"$(tccdir)/examples")
cp -r $(TOPSRC)/win32/include/. "$(tccdir)/include" $(call IF,$(TOPSRC)/tests/libtcc_test.c,"$(tccdir)/examples")
$(INSTALL) $(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h "$(tccdir)/include" $(call IFw,$(TOPSRC)/libtcc.h $(subst .dll,.def,$(LIBTCC)),"$(libdir)")
mkdir -p "$(tccdir)/examples" $(call IFw,$(TOPSRC)/win32/tcc-win32.txt tcc-doc.html,"$(docdir)")
cp -r $(TOPSRC)/win32/examples/. "$(tccdir)/examples" ifneq "$(wildcard $(LIBTCC1_U))" ""
$(INSTALL) $(TOPSRC)/tests/libtcc_test.c "$(tccdir)/examples" $(call IFw,$(LIBTCC1_U),"$(tccdir)/lib")
mkdir -p "$(tccdir)/libtcc" $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/lib/include")
$(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"
endif endif
# the msys-git shell works to configure && make except it does not have install # 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 : INSTALL = cp
install-win : INSTALLBIN = cp
endif
# uninstall on windows # uninstall on windows
uninstall-win: 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)" rm -r "$(tccdir)"
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------

68
configure vendored
View File

@ -56,7 +56,6 @@ case $targetos in
DLLSUF=".dylib" DLLSUF=".dylib"
;; ;;
MINGW*|MSYS*|CYGWIN*) MINGW*|MSYS*|CYGWIN*)
confvars="$confvars WIN32"
mingw32=yes mingw32=yes
;; ;;
DragonFly|OpenBSD|FreeBSD|NetBSD) DragonFly|OpenBSD|FreeBSD|NetBSD)
@ -126,8 +125,6 @@ for opt do
;; ;;
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2` --cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
;; ;;
--enable-mingw32) confvars="$confvars WIN32"; mingw32="yes"
;;
--enable-cross) confvars="$confvars cross" --enable-cross) confvars="$confvars cross"
;; ;;
--disable-static) confvars="$confvars static=no" --disable-static) confvars="$confvars static=no"
@ -142,6 +139,8 @@ for opt do
;; ;;
--with-selinux) confvars="$confvars selinux" --with-selinux) confvars="$confvars selinux"
;; ;;
--config-mingw32*) mingw32=$(echo "$opt=yes" | cut -d '=' -f 2)
;;
--config-*) confvars="$confvars ${opt#--config-}"; suggest="no" --config-*) confvars="$confvars ${opt#--config-}"; suggest="no"
;; ;;
--help|-h) show_help="yes" --help|-h) show_help="yes"
@ -216,22 +215,12 @@ if test "$mingw32" = "yes" ; then
if test "$cc" = gcc; then if test "$cc" = gcc; then
test -z "$LDFLAGS" && LDFLAGS="-static" test -z "$LDFLAGS" && LDFLAGS="-static"
fi fi
if test x"$tccdir" = x""; then test -z "$prefix" && prefix="C:/Program Files/tcc"
tccdir="tcc" test -z "$tccdir" && tccdir="${prefix}"
fi test -z "$bindir" && bindir="${tccdir}"
if test -z "$prefix" ; then test -z "$docdir" && docdir="${tccdir}/doc"
prefix="C:/Program Files/${tccdir}" test -z "$libdir" && libdir="${tccdir}/libtcc"
fi confvars="$confvars WIN32"
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"
LIBSUF=".lib" LIBSUF=".lib"
EXESUF=".exe" EXESUF=".exe"
DLLSUF=".dll" DLLSUF=".dll"
@ -263,12 +252,11 @@ else
if test x"$tccdir" = x""; then if test x"$tccdir" = x""; then
tccdir="${libdir}/tcc" tccdir="${libdir}/tcc"
fi fi
if test x"$includedir" = x""; then
includedir="${prefix}/include"
fi
fi # mingw32 fi # mingw32
if test x"$includedir" = x""; then
includedir="${prefix}/include"
fi
if test x"$show_help" = "xyes" ; then if test x"$show_help" = "xyes" ; then
cat << EOF cat << EOF
Usage: configure [options] Usage: configure [options]
@ -302,7 +290,6 @@ Advanced options (experts only):
--enable-static make libtcc.a instead of libtcc.dll (win32) --enable-static make libtcc.a instead of libtcc.dll (win32)
--disable-rpath disable use of -rpath with the above --disable-rpath disable use of -rpath with the above
--with-libgcc use libgcc_s.so.1 instead of libtcc1.a --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 --enable-cross build cross compilers
--with-selinux use mmap for executable memory (with tcc -run) --with-selinux use mmap for executable memory (with tcc -run)
--sysincludepaths=... specify system include paths, colon separated --sysincludepaths=... specify system include paths, colon separated
@ -310,7 +297,7 @@ Advanced options (experts only):
--crtprefix=... specify locations of crt?.o, colon separated --crtprefix=... specify locations of crt?.o, colon separated
--elfinterp=... specify elf interpreter --elfinterp=... specify elf interpreter
--triplet=... specify system library/include directory triplet --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 EOF
#echo "NOTE: The object files are build at the place where configure is launched" #echo "NOTE: The object files are build at the place where configure is launched"
exit 1 exit 1
@ -320,15 +307,14 @@ cc="${cross_prefix}${cc}"
ar="${cross_prefix}${ar}" ar="${cross_prefix}${ar}"
strip="${cross_prefix}${strip}" 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 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)" bigendian="$($CONFTEST bigendian)"
if test "$mingw32" = "no" ; then if test "$mingw32" = "no" ; then
@ -401,13 +387,13 @@ fi
fcho() { if test -n "$2"; then echo "$1$2"; fi } fcho() { if test -n "$2"; then echo "$1$2"; fi }
echo "Binary directory $bindir" fcho "Binary directory " "$bindir"
echo "TinyCC directory $tccdir" fcho "TinyCC directory " "$tccdir"
echo "Library directory $libdir" fcho "Library directory " "$libdir"
echo "Include directory $includedir" fcho "Include directory " "$includedir"
echo "Manual directory $mandir" fcho "Manual directory " "$mandir"
echo "Info directory $infodir" fcho "Info directory " "$infodir"
echo "Doc directory $docdir" fcho "Doc directory " "$docdir"
fcho "Target root prefix " "$sysroot" fcho "Target root prefix " "$sysroot"
echo "Source path $source_path" echo "Source path $source_path"
echo "C compiler $cc ($gcc_major.$gcc_minor)" 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 CONFIG_TRIPLET "$triplet"
print_mak_int TCC_CPU_VERSION "$cpuver" 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 if test "$cpu" = "aarch64" ; then
echo "ARCH=arm64" >> config.mak echo "ARCH=arm64" >> config.mak
else else

View File

@ -16,12 +16,7 @@ typedef struct {
char *reg_save_area; char *reg_save_area;
} __va_list_struct; } __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]; 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_start(__va_list_struct *ap, void *fp);
void *__va_arg(__va_list_struct *ap, int arg_type, int size, int align); void *__va_arg(__va_list_struct *ap, int arg_type, int size, int align);

View File

@ -7,20 +7,20 @@ include $(TOP)/Makefile
VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib
T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown) T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown)
X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-) 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) XTCC ?= $(TOP)/$(X)tcc$(EXESUF)
XCC = $(TCC) XCC = $(XTCC)
XAR = $(TCC) -ar XAR = $(XTCC) -ar
XFLAGS-unx = -B$(TOPSRC) XFLAGS-unx = -B$(TOPSRC)
XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include
XFLAGS = $(XFLAGS$(XCFG)) XFLAGS = $(XFLAGS$(XCFG))
XCFG = $(or $(findstring -win,$T),-unx) XCFG = $(or $(findstring -win,$T),-unx)
# in order to use gcc, tyoe: make <target>lib-usegcc=yes # in order to use gcc, tyoe: make <target>-libtcc1-usegcc=yes
armlib-usegcc ?= no arm-libtcc1-usegcc ?= no
ifeq "$($(X)$(T)lib-usegcc)" "yes" ifeq "$($(T)-libtcc1-usegcc)" "yes"
XCC = $(CC) XCC = $(CC)
XAR = $(AR) XAR = $(AR)
XFLAGS = $(CFLAGS) -fPIC XFLAGS = $(CFLAGS) -fPIC

View File

@ -104,10 +104,8 @@ static void tcc_set_lib_path_w32(TCCState *s)
char path[1024], *p; char path[1024], *p;
GetModuleFileNameA(tcc_module, path, sizeof path); GetModuleFileNameA(tcc_module, path, sizeof path);
p = tcc_basename(normalize_slashes(strlwr(path))); p = tcc_basename(normalize_slashes(strlwr(path)));
if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5)) if (p > path)
p -= 5; --p;
else if (p > path)
p--;
*p = 0; *p = 0;
tcc_set_lib_path(s, path); 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; CString str;
cstr_new(&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] == '}') { if (c == '{' && p[1] && p[2] == '}') {
c = p[1], p += 2; c = p[1], p += 2;
if (c == 'B') if (c == 'B')
@ -804,6 +802,8 @@ LIBTCCAPI TCCState *tcc_new(void)
#endif #endif
#elif defined(TCC_TARGET_ARM64) #elif defined(TCC_TARGET_ARM64)
tcc_define_symbol(s, "__aarch64__", NULL); tcc_define_symbol(s, "__aarch64__", NULL);
#elif defined TCC_TARGET_C67
tcc_define_symbol(s, "__C67__", NULL);
#endif #endif
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
@ -827,13 +827,13 @@ LIBTCCAPI TCCState *tcc_new(void)
# if defined(__FreeBSD_kernel__) # if defined(__FreeBSD_kernel__)
tcc_define_symbol(s, "__FreeBSD_kernel__", NULL); tcc_define_symbol(s, "__FreeBSD_kernel__", NULL);
# endif # endif
#endif
# if defined(__NetBSD__) # if defined(__NetBSD__)
tcc_define_symbol(s, "__NetBSD__", "__NetBSD__"); tcc_define_symbol(s, "__NetBSD__", "__NetBSD__");
# endif # endif
# if defined(__OpenBSD__) # if defined(__OpenBSD__)
tcc_define_symbol(s, "__OpenBSD__", "__OpenBSD__"); tcc_define_symbol(s, "__OpenBSD__", "__OpenBSD__");
# endif # endif
#endif
/* TinyCC & gcc defines */ /* TinyCC & gcc defines */
#if PTR_SIZE == 4 #if PTR_SIZE == 4
@ -853,14 +853,6 @@ LIBTCCAPI TCCState *tcc_new(void)
tcc_define_symbol(s, "__LP64__", NULL); tcc_define_symbol(s, "__LP64__", NULL);
#endif #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 #ifdef TCC_TARGET_PE
tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short"); tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
tcc_define_symbol(s, "__WINT_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)", tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)",
"name proto __asm__ (#alias) __THROW"); "name proto __asm__ (#alias) __THROW");
# endif # 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. */ /* Some GCC builtins that are simple to express as macros. */
tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x"); tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x");
#endif /* ndef TCC_TARGET_PE */ #endif /* ndef TCC_TARGET_PE */
@ -906,7 +903,6 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
/* free include paths */ /* free include paths */
dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes); 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->include_paths, &s1->nb_include_paths);
dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths); dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
dynarray_reset(&s1->cmd_include_files, &s1->nb_cmd_include_files); 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) { if (!s->nostdinc) {
/* default include paths */ /* default include paths */
/* -isystem paths have already been handled */ /* -isystem paths have already been handled */
tcc_add_tccinclude_path(s, CONFIG_TCC_TCCINCLUDEPATHS);
tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS); 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; 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) LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
{ {
tcc_split_path(s, &s->include_paths, &s->nb_include_paths, 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 }, { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "f", TCC_OPTION_f, 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 }, { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
{ "iwithprefix", TCC_OPTION_iwithprefix, TCC_OPTION_HAS_ARG },
{ "include", TCC_OPTION_include, TCC_OPTION_HAS_ARG }, { "include", TCC_OPTION_include, TCC_OPTION_HAS_ARG },
{ "nostdinc", TCC_OPTION_nostdinc, 0 }, { "nostdinc", TCC_OPTION_nostdinc, 0 },
{ "nostdlib", TCC_OPTION_nostdlib, 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 last_o = -1;
int x; int x;
CString linker_arg; /* collect -Wl options */ CString linker_arg; /* collect -Wl options */
char buf[1024];
int tool = 0, arg_start = 0, noaction = optind; int tool = 0, arg_start = 0, noaction = optind;
char **argv = *pargv; char **argv = *pargv;
int argc = *pargc; int argc = *pargc;
@ -1827,10 +1814,6 @@ reparse:
case TCC_OPTION_isystem: case TCC_OPTION_isystem:
tcc_add_sysinclude_path(s, optarg); tcc_add_sysinclude_path(s, optarg);
break; break;
case TCC_OPTION_iwithprefix:
snprintf(buf, sizeof buf, "{B}/%s", optarg);
tcc_add_tccinclude_path(s, buf);
break;
case TCC_OPTION_include: case TCC_OPTION_include:
dynarray_add(&s->cmd_include_files, dynarray_add(&s->cmd_include_files,
&s->nb_cmd_include_files, tcc_strdup(optarg)); &s->nb_cmd_include_files, tcc_strdup(optarg));

View File

@ -32,9 +32,6 @@ LIBTCCAPI void tcc_set_options(TCCState *s, const char *str);
/*****************************/ /*****************************/
/* preprocessor */ /* preprocessor */
/* add in tcc include path, searched before anything else */
LIBTCCAPI int tcc_add_tccinclude_path(TCCState *s, const char *pathname);
/* add include path */ /* add include path */
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname); LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname);

5
tcc.c
View File

@ -86,7 +86,6 @@ static const char help2[] =
" -Wp,-opt same as -opt\n" " -Wp,-opt same as -opt\n"
" -include file include 'file' above each input file\n" " -include file include 'file' above each input file\n"
" -isystem dir add 'dir' to system include path\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" " -static link to static libraries (not recommended)\n"
" -dumpversion print version\n" " -dumpversion print version\n"
" -print-search-dirs print search paths\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); printf("install: %s\n", s->tcc_lib_path);
/* print_dirs("programs", NULL, 0); */ /* 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("include", s->sysinclude_paths, s->nb_sysinclude_paths);
print_dirs("libraries", s->library_paths, s->nb_library_paths); print_dirs("libraries", s->library_paths, s->nb_library_paths);
#ifndef TCC_TARGET_PE #ifndef TCC_TARGET_PE
@ -197,7 +195,7 @@ static void set_environment(TCCState *s)
path = getenv("C_INCLUDE_PATH"); path = getenv("C_INCLUDE_PATH");
if(path != NULL) { if(path != NULL) {
tcc_add_include_path(s, path); tcc_add_sysinclude_path(s, path);
} }
path = getenv("CPATH"); path = getenv("CPATH");
if(path != NULL) { if(path != NULL) {
@ -278,6 +276,7 @@ redo:
return 0; return 0;
if (opt == OPT_PRINT_DIRS) { if (opt == OPT_PRINT_DIRS) {
/* initialize search dirs */ /* initialize search dirs */
set_environment(s);
tcc_set_output_type(s, TCC_OUTPUT_MEMORY); tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
print_search_dirs(s); print_search_dirs(s);
return 0; return 0;

35
tcc.h
View File

@ -101,10 +101,12 @@ extern long double strtold (const char *__nptr, char **__endptr);
# define IS_DIRSEP(c) (c == '/' || c == '\\') # define IS_DIRSEP(c) (c == '/' || c == '\\')
# define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2]))) # define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2])))
# define PATHCMP stricmp # define PATHCMP stricmp
# define PATHSEP ";"
#else #else
# define IS_DIRSEP(c) (c == '/') # define IS_DIRSEP(c) (c == '/')
# define IS_ABSPATH(p) IS_DIRSEP(p[0]) # define IS_ABSPATH(p) IS_DIRSEP(p[0])
# define PATHCMP strcmp # define PATHCMP strcmp
# define PATHSEP ":"
#endif #endif
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -195,21 +197,14 @@ extern long double strtold (const char *__nptr, char **__endptr);
/* Below: {B} is substituted by CONFIG_TCCDIR (rsp. -B option) */ /* Below: {B} is substituted by CONFIG_TCCDIR (rsp. -B option) */
/* system include paths */ /* 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 CONFIG_TCC_SYSINCLUDEPATHS
# ifndef TCC_TARGET_PE # ifdef TCC_TARGET_PE
# define CONFIG_TCC_SYSINCLUDEPATHS \ # define CONFIG_TCC_SYSINCLUDEPATHS "{B}/include"PATHSEP"{B}/include/winapi"
ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/include") \
":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/include")
# else # 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
#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" #define TCC_LIBGCC USE_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1"
#endif #endif
#ifdef TCC_TARGET_PE
#define PATHSEP ';'
#else
#define PATHSEP ':'
#endif
/* -------------------------------------------- */ /* -------------------------------------------- */
#include "libtcc.h" #include "libtcc.h"
@ -722,10 +711,7 @@ struct TCCState {
DLLReference **loaded_dlls; DLLReference **loaded_dlls;
int nb_loaded_dlls; int nb_loaded_dlls;
/* include paths, search order */ /* include paths */
char **tccinclude_paths;
int nb_tccinclude_paths;
char **include_paths; char **include_paths;
int nb_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_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_output_file(TCCState * s1, const char *filename);
ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value); 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); ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
#endif #endif
#ifdef TCC_TARGET_X86_64 #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_IMPORT 0x20
# define ST_PE_STDCALL 0x40 # define ST_PE_STDCALL 0x40
#endif #endif
/* ------------ tccrun.c ----------------- */ /* ------------ tccrun.c ----------------- */
#ifdef TCC_IS_NATIVE #ifdef TCC_IS_NATIVE
#ifdef CONFIG_TCC_STATIC #ifdef CONFIG_TCC_STATIC

View File

@ -75,6 +75,8 @@ ST_FUNC Sym* get_asm_sym(int name, Sym *csym)
sym->type.t &= ~VT_EXTERN; sym->type.t &= ~VT_EXTERN;
/* Mark that this asm symbol doesn't need to be fed back. */ /* Mark that this asm symbol doesn't need to be fed back. */
sym->a.dllimport = 1; sym->a.dllimport = 1;
} else {
sym->type.t |= VT_STATIC;
} }
} }
return sym; return sym;

218
tccelf.c
View File

@ -828,6 +828,12 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
switch(type) { switch(type) {
#if defined(TCC_TARGET_I386) #if defined(TCC_TARGET_I386)
case R_386_32: 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) #elif defined(TCC_TARGET_X86_64)
case R_X86_64_32: case R_X86_64_32:
case R_X86_64_32S: 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) ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
{ {
int sym_index = ELFW(R_SYM) (rel->r_info); 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)) { for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
name = (char *) s1->dynsymtab_section->link->data + esym->st_name; name = (char *) s1->dynsymtab_section->link->data + esym->st_name;
sym_index = find_elf_sym(symtab_section, 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]; sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
if (sym_index && sym->st_shndx != SHN_UNDEF) if (sym_index && sym->st_shndx != SHN_UNDEF
set_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info, && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
0, sym->st_shndx, name); set_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
else if (esym->st_shndx == SHN_UNDEF) { sym->st_info, 0, sym->st_shndx, name);
} else if (esym->st_shndx == SHN_UNDEF) {
/* weak symbols can stay undefined */ /* weak symbols can stay undefined */
if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK) if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
tcc_warning("undefined dynamic symbol '%s'", name); 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 /* Allocate strings for section names and decide if an unallocated section
should be output. should be output.
NOTE: the strsec section comes last, so its size is also correct ! */ 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; int i;
Section *s; Section *s;
int textrel = 0;
/* Allocate strings for section names */ /* Allocate strings for section names */
for(i = 1; i < s1->nb_sections; i++) { 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 */ patch them */
if (file_type == TCC_OUTPUT_DLL && if (file_type == TCC_OUTPUT_DLL &&
s->sh_type == SHT_RELX && s->sh_type == SHT_RELX &&
!(s->sh_flags & SHF_ALLOC)) { !(s->sh_flags & SHF_ALLOC) &&
/* gr: avoid bogus relocs for empty (debug) sections */ (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC) &&
if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC) prepare_dynamic_rel(s1, s)) {
prepare_dynamic_rel(s1, s); if (s1->sections[s->sh_info]->sh_flags & SHF_EXECINSTR)
else if (s1->do_debug) textrel = 1;
s->sh_size = s->data_offset;
} else if (s1->do_debug || } else if (s1->do_debug ||
file_type == TCC_OUTPUT_OBJ || file_type == TCC_OUTPUT_OBJ ||
(s->sh_flags & SHF_ALLOC) || (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); s->sh_name = put_elf_str(strsec, s->name);
} }
strsec->sh_size = strsec->data_offset; strsec->sh_size = strsec->data_offset;
return textrel;
} }
/* Info to be copied in dynamic section */ /* Info to be copied in dynamic section */
struct dyn_inf { struct dyn_inf {
Section *dynamic; Section *dynamic;
Section *dynstr; Section *dynstr;
unsigned long dyn_rel_off; unsigned long data_offset;
addr_t rel_addr; addr_t rel_addr;
addr_t rel_size; addr_t rel_size;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #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 the program header table itself if needed. These are done later as
they require section layout to be done first. */ they require section layout to be done first. */
if (interp) if (interp)
ph += 1 + HAVE_PHDR; ph += 2;
/* dynamic relocation table information, for .dynamic section */ /* dynamic relocation table information, for .dynamic section */
dyninf->rel_addr = dyninf->rel_size = 0; 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) { if (interp) {
ph = &phdr[0]; ph = &phdr[0];
if (HAVE_PHDR) ph->p_type = PT_PHDR;
{ ph->p_offset = sizeof(ElfW(Ehdr));
int len = phnum * sizeof(ElfW(Phdr)); ph->p_filesz = ph->p_memsz = phnum * sizeof(ElfW(Phdr));
ph->p_vaddr = interp->sh_addr - ph->p_filesz;
ph->p_type = PT_PHDR; ph->p_paddr = ph->p_vaddr;
ph->p_offset = sizeof(ElfW(Ehdr)); ph->p_flags = PF_R | PF_X;
ph->p_vaddr = interp->sh_addr - len; ph->p_align = 4; /* interp->sh_addralign; */
ph->p_paddr = ph->p_vaddr; ph++;
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_INTERP; ph->p_type = PT_INTERP;
ph->p_offset = interp->sh_offset; ph->p_offset = interp->sh_offset;
@ -1727,12 +1720,9 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
sections */ sections */
static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf) static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
{ {
Section *dynamic; Section *dynamic = dyninf->dynamic;
dynamic = dyninf->dynamic;
/* put dynamic section entries */ /* 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_HASH, s1->dynsym->hash->sh_addr);
put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr); put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr);
put_dt(dynamic, DT_SYMTAB, s1->dynsym->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(Phdr) *phdr;
ElfW(Sym) *sym; ElfW(Sym) *sym;
Section *strsec, *interp, *dynamic, *dynstr; Section *strsec, *interp, *dynamic, *dynstr;
int textrel;
file_type = s1->output_type; file_type = s1->output_type;
s1->nb_errors = 0; s1->nb_errors = 0;
ret = -1;
/* if linking, also link in runtime libraries (libc, libgcc, etc.) */
if (file_type != TCC_OUTPUT_OBJ) {
tcc_add_runtime(s1);
}
phdr = NULL; phdr = NULL;
sec_order = NULL; sec_order = NULL;
interp = dynamic = dynstr = NULL; /* avoid warning */ interp = dynamic = dynstr = NULL; /* avoid warning */
textrel = 0;
if (file_type != TCC_OUTPUT_OBJ) { if (file_type != TCC_OUTPUT_OBJ) {
/* if linking, also link in runtime libraries (libc, libgcc, etc.) */
tcc_add_runtime(s1);
relocate_common_syms(); relocate_common_syms();
tcc_add_linker_symbols(s1); tcc_add_linker_symbols(s1);
if (!s1->static_link) { if (!s1->static_link) {
@ -2057,53 +2045,70 @@ static int elf_output_file(TCCState *s1, const char *filename)
if (file_type == TCC_OUTPUT_EXE) { if (file_type == TCC_OUTPUT_EXE) {
bind_exe_dynsyms(s1); bind_exe_dynsyms(s1);
if (s1->nb_errors)
if (s1->nb_errors) {
ret = -1;
goto the_end; goto the_end;
}
bind_libs_dynsyms(s1); 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); 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 */ /* we add a section for symbols */
strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0); strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
put_elf_str(strsec, ""); 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 */ /* compute number of sections */
shnum = s1->nb_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 = tcc_malloc(sizeof(int) * shnum);
sec_order[0] = 0; 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 */ /* compute section to program header mapping */
file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf, file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf,
sec_order); sec_order);
/* Fill remaining program header and finalize relocation related to dynamic /* Fill remaining program header and finalize relocation related to dynamic
linking. */ linking. */
if (phnum > 0) { if (file_type != TCC_OUTPUT_OBJ) {
fill_unloadable_phdr(phdr, phnum, interp, dynamic); fill_unloadable_phdr(phdr, phnum, interp, dynamic);
if (dynamic) { if (dynamic) {
dyninf.dynamic = dynamic; dynamic->data_offset = dyninf.data_offset;
dyninf.dynstr = dynstr;
fill_dynamic(s1, &dyninf); fill_dynamic(s1, &dyninf);
/* put in GOT the dynamic section address and relocate PLT */ /* 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 /* if building executable or DLL, then relocate each section
except the GOT which is already relocated */ except the GOT which is already relocated */
if (file_type != TCC_OUTPUT_OBJ) {
ret = final_sections_reloc(s1); ret = final_sections_reloc(s1);
if (ret) if (ret)
goto the_end; goto the_end;
tidy_section_headers(s1, sec_order); tidy_section_headers(s1, sec_order);
}
/* Perform relocation to GOT or PLT entries */ /* Perform relocation to GOT or PLT entries */
if (file_type == TCC_OUTPUT_EXE && s1->static_link) if (file_type == TCC_OUTPUT_EXE && s1->static_link)
fill_got(s1); fill_got(s1);
else if (s1->got) else if (s1->got)
fill_local_got_entries(s1); fill_local_got_entries(s1);
}
/* Create the ELF file with name 'filename' */ /* Create the ELF file with name 'filename' */
ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order); ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order);

View File

@ -116,6 +116,12 @@ ST_FUNC int ieee_finite(double d)
return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31; 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) ST_FUNC void test_lvalue(void)
{ {
if (!(vtop->r & VT_LVAL)) 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; parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_TOK_STR;
next(); next();
decl(VT_CONST); decl(VT_CONST);
if (tok != TOK_EOF)
expect("declaration");
gen_inline_functions(s1); gen_inline_functions(s1);
check_vstack(); check_vstack();
/* end of translation unit info */ /* end of translation unit info */
@ -2411,6 +2414,9 @@ static void gen_cast(CType *type)
df = is_float(dbt); df = is_float(dbt);
c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
p = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM); 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) { if (c) {
/* constant case: we can do it now */ /* constant case: we can do it now */
/* XXX: in ISOC, cannot do it if error in convert */ /* XXX: in ISOC, cannot do it if error in convert */
@ -3096,6 +3102,8 @@ ST_FUNC void vstore(void)
/* ... and discard */ /* ... and discard */
vpop(); vpop();
} }
} else if (dbt == VT_VOID) {
--vtop;
} else { } else {
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
/* bound check case */ /* bound check case */
@ -5925,7 +5933,10 @@ static void block(int *bsym, int *csym, int is_expr)
if (tok != ';') { if (tok != ';') {
gexpr(); gexpr();
gen_assign_cast(&func_vt); gen_assign_cast(&func_vt);
gfunc_return(&func_vt); if ((func_vt.t & VT_BTYPE) == VT_VOID)
vtop--;
else
gfunc_return(&func_vt);
} }
skip(';'); skip(';');
/* jump unless last stmt in top-level block */ /* 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; *(double *)ptr = vtop->c.d;
break; break;
case VT_LDOUBLE: 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 */ if (sizeof (long double) >= 10) /* zero pad ten-byte LD */
memcpy(ptr, &vtop->c.ld, 10); memcpy(ptr, &vtop->c.ld, 10);
#ifdef __TINYC__ #ifdef __TINYC__
@ -7091,17 +7102,22 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
next(); next();
continue; continue;
} }
if (l == VT_CONST && if (l != VT_CONST)
(tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) { break;
if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
/* global asm block */ /* global asm block */
asm_global_instr(); asm_global_instr();
continue; continue;
} }
/* special test for old K&R protos without explicit int if (tok >= TOK_UIDENT) {
type. Only accepted when defining global data */ /* special test for old K&R protos without explicit int
if (l != VT_CONST || tok < TOK_UIDENT) type. Only accepted when defining global data */
btype.t = VT_INT;
} else {
if (tok != TOK_EOF)
expect("declaration");
break; break;
btype.t = VT_INT; }
} }
if (tok == ';') { if (tok == ';') {
if ((btype.t & VT_BTYPE) == VT_STRUCT) { if ((btype.t & VT_BTYPE) == VT_STRUCT) {

35
tccpe.c
View File

@ -26,10 +26,12 @@
#ifndef _WIN32 #ifndef _WIN32
#define stricmp strcasecmp #define stricmp strcasecmp
#define strnicmp strncasecmp #define strnicmp strncasecmp
#include <sys/stat.h> /* chmod() */
#endif #endif
#ifdef TCC_TARGET_X86_64 #ifdef TCC_TARGET_X86_64
# define ADDR3264 ULONGLONG # define ADDR3264 ULONGLONG
# define PE_IMAGE_REL IMAGE_REL_BASED_DIR64
# define REL_TYPE_DIRECT R_X86_64_64 # define REL_TYPE_DIRECT R_X86_64_64
# define R_XXX_THUNKFIX R_X86_64_PC32 # define R_XXX_THUNKFIX R_X86_64_PC32
# define R_XXX_RELATIVE R_X86_64_RELATIVE # define R_XXX_RELATIVE R_X86_64_RELATIVE
@ -38,6 +40,7 @@
#elif defined TCC_TARGET_ARM #elif defined TCC_TARGET_ARM
# define ADDR3264 DWORD # define ADDR3264 DWORD
# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW
# define REL_TYPE_DIRECT R_ARM_ABS32 # define REL_TYPE_DIRECT R_ARM_ABS32
# define R_XXX_THUNKFIX R_ARM_ABS32 # define R_XXX_THUNKFIX R_ARM_ABS32
# define R_XXX_RELATIVE R_ARM_RELATIVE # define R_XXX_RELATIVE R_ARM_RELATIVE
@ -46,6 +49,7 @@
#elif defined TCC_TARGET_I386 #elif defined TCC_TARGET_I386
# define ADDR3264 DWORD # define ADDR3264 DWORD
# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW
# define REL_TYPE_DIRECT R_386_32 # define REL_TYPE_DIRECT R_386_32
# define R_XXX_THUNKFIX R_386_32 # define R_XXX_THUNKFIX R_386_32
# define R_XXX_RELATIVE R_386_RELATIVE # define R_XXX_RELATIVE R_386_RELATIVE
@ -54,22 +58,6 @@
#endif #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 #ifndef IMAGE_NT_SIGNATURE
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
/* definitions below are from winnt.h */ /* 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_MIPS_JMPADDR 5
#define IMAGE_REL_BASED_SECTION 6 #define IMAGE_REL_BASED_SECTION 6
#define IMAGE_REL_BASED_REL32 7 #define IMAGE_REL_BASED_REL32 7
#define IMAGE_REL_BASED_DIR64 10
#pragma pack(pop) #pragma pack(pop)
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
#endif /* ndef IMAGE_NT_SIGNATURE */ #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 struct pe_header
{ {
IMAGE_DOS_HEADER doshdr; IMAGE_DOS_HEADER doshdr;
@ -281,7 +274,6 @@ struct pe_rsrc_reloc {
DWORD size; DWORD size;
WORD type; WORD type;
}; };
#pragma pack(pop) #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); fseek(op, offsetof(struct pe_header, opthdr.CheckSum), SEEK_SET);
pe_fwrite(&pe_header.opthdr.CheckSum, sizeof pe_header.opthdr.CheckSum, op, NULL); pe_fwrite(&pe_header.opthdr.CheckSum, sizeof pe_header.opthdr.CheckSum, op, NULL);
fclose (op); fclose (op);
#ifndef _WIN32
chmod(pe->filename, 0777);
#endif
if (2 == pe->s1->verbose) if (2 == pe->s1->verbose)
printf("-------------------------------\n"); 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 */ if ((addr -= offset) < (1<<12)) { /* one block spans 4k addresses */
WORD *wp = section_ptr_add(pe->reloc, sizeof (WORD)); WORD *wp = section_ptr_add(pe->reloc, sizeof (WORD));
*wp = addr | IMAGE_REL_BASED_HIGHLOW<<12; *wp = addr | PE_IMAGE_REL<<12;
++count; ++count;
continue; 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 */ /* 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) ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2)
{ {
int r2; int r2;

49
tccpp.c
View File

@ -591,7 +591,7 @@ ST_FUNC int handle_eob(void)
/* only tries to read if really end of buffer */ /* only tries to read if really end of buffer */
if (bf->buf_ptr >= bf->buf_end) { if (bf->buf_ptr >= bf->buf_end) {
if (bf->fd != -1) { if (bf->fd >= 0) {
#if defined(PARSE_DEBUG) #if defined(PARSE_DEBUG)
len = 1; len = 1;
#else #else
@ -1803,8 +1803,7 @@ ST_FUNC void preprocess(int is_bof)
/* store current file in stack, but increment stack later below */ /* store current file in stack, but increment stack later below */
*s1->include_stack_ptr = file; *s1->include_stack_ptr = file;
i = tok == TOK_INCLUDE_NEXT ? file->include_next_index : 0; i = tok == TOK_INCLUDE_NEXT ? file->include_next_index : 0;
n = 2 + s1->nb_tccinclude_paths + s1->nb_include_paths + n = 2 + s1->nb_include_paths + s1->nb_sysinclude_paths;
s1->nb_sysinclude_paths;
for (; i < n; ++i) { for (; i < n; ++i) {
char buf1[sizeof file->filename]; char buf1[sizeof file->filename];
CachedInclude *e; CachedInclude *e;
@ -1826,14 +1825,8 @@ ST_FUNC void preprocess(int is_bof)
} else { } else {
/* search in all the include paths */ /* search in all the include paths */
int k, j = i - 2; int j = i - 2, k = j - s1->nb_include_paths;
path = k < 0 ? s1->include_paths[j] : s1->sysinclude_paths[k];
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];
pstrcpy(buf1, sizeof(buf1), path); pstrcpy(buf1, sizeof(buf1), path);
pstrcat(buf1, sizeof(buf1), "/"); pstrcat(buf1, sizeof(buf1), "/");
} }
@ -2635,6 +2628,8 @@ static inline void next_nomacro1(void)
tcc_close(); tcc_close();
s1->include_stack_ptr--; s1->include_stack_ptr--;
p = file->buf_ptr; p = file->buf_ptr;
if (p == file->buffer)
tok_flags = TOK_FLAG_BOF|TOK_FLAG_BOL;
goto redo_no_start; goto redo_no_start;
} }
} }
@ -2968,7 +2963,7 @@ maybe_newline:
keep_tok_flags: keep_tok_flags:
file->buf_ptr = p; file->buf_ptr = p;
#if defined(PARSE_DEBUG) #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 #endif
} }
@ -3585,7 +3580,8 @@ ST_INLN void unget_tok(int last_tok)
ST_FUNC void preprocess_start(TCCState *s1, int is_asm) ST_FUNC void preprocess_start(TCCState *s1, int is_asm)
{ {
char *buf; CString cstr;
int i;
s1->include_stack_ptr = s1->include_stack; s1->include_stack_ptr = s1->include_stack;
s1->ifdef_stack_ptr = s1->ifdef_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('$', s1->dollars_in_identifiers ? IS_ID : 0);
set_idnum('.', is_asm ? IS_ID : 0); set_idnum('.', is_asm ? IS_ID : 0);
buf = tcc_malloc(3 + strlen(file->filename)); cstr_new(&cstr);
sprintf(buf, "\"%s\"", file->filename); cstr_cat(&cstr, "\"", -1);
tcc_define_symbol(s1, "__BASE_FILE__", buf); cstr_cat(&cstr, file->filename, -1);
tcc_free(buf); cstr_cat(&cstr, "\"", 0);
tcc_define_symbol(s1, "__BASE_FILE__", cstr.data);
if (s1->nb_cmd_include_files) { cstr_reset(&cstr);
CString cstr; for (i = 0; i < s1->nb_cmd_include_files; i++) {
int i; cstr_cat(&cstr, "#include \"", -1);
cstr_new(&cstr); cstr_cat(&cstr, s1->cmd_include_files[i], -1);
for (i = 0; i < s1->nb_cmd_include_files; i++) { cstr_cat(&cstr, "\"\n", -1);
cstr_cat(&cstr, "#include \"", -1); }
cstr_cat(&cstr, s1->cmd_include_files[i], -1); if (cstr.size) {
cstr_cat(&cstr, "\"\n", -1);
}
*s1->include_stack_ptr++ = file; *s1->include_stack_ptr++ = file;
tcc_open_bf(s1, "<command line>", cstr.size); tcc_open_bf(s1, "<command line>", cstr.size);
memcpy(file->buffer, cstr.data, cstr.size); memcpy(file->buffer, cstr.data, cstr.size);
cstr_free(&cstr);
} }
cstr_free(&cstr);
if (is_asm) if (is_asm)
tcc_define_symbol(s1, "__ASSEMBLER__", NULL); tcc_define_symbol(s1, "__ASSEMBLER__", NULL);

View File

@ -45,15 +45,13 @@ static void set_exception_handler(void);
#endif #endif
static void set_pages_executable(void *ptr, unsigned long length); 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 #ifdef _WIN64
static void *win64_add_function_table(TCCState *s1); static void *win64_add_function_table(TCCState *s1);
static void win64_del_function_table(void *); static void win64_del_function_table(void *);
#endif #endif
// #define HAVE_SELINUX
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Do all relocations (needed before using tcc_get_symbol()) /* Do all relocations (needed before using tcc_get_symbol())
Returns -1 on error. */ Returns -1 on error. */
@ -61,25 +59,36 @@ static void win64_del_function_table(void *);
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
{ {
int size; int size;
addr_t ptr_diff = 0;
if (TCC_RELOCATE_AUTO != ptr) 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) if (size < 0)
return -1; return -1;
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
/* Use mmap instead of malloc for Selinux. */ {
ptr = mmap (NULL, size, PROT_READ|PROT_WRITE, /* Using mmap instead of malloc */
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); void *prx;
if (ptr == MAP_FAILED) char tmpfname[] = "/tmp/.tccrunXXXXXX";
tcc_error("tccrun: could not map memory"); 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, (void*)(addr_t)size);
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, prx);
ptr_diff = (char*)prx - (char*)ptr;
}
#else #else
ptr = tcc_malloc(size); ptr = tcc_malloc(size);
#endif #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); dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr);
return 0; return 0;
} }
@ -91,6 +100,7 @@ ST_FUNC void tcc_run_free(TCCState *s1)
for (i = 0; i < s1->nb_runtime_mem; ++i) { for (i = 0; i < s1->nb_runtime_mem; ++i) {
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
unsigned size = (unsigned)(addr_t)s1->runtime_mem[i++]; unsigned size = (unsigned)(addr_t)s1->runtime_mem[i++];
munmap(s1->runtime_mem[i++], size);
munmap(s1->runtime_mem[i], size); munmap(s1->runtime_mem[i], size);
#else #else
#ifdef _WIN64 #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, /* relocate code. Return -1 on error, required size if ptr is NULL,
otherwise copy code into buffer passed by the caller */ 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; Section *s;
unsigned offset, length, fill, i, k; 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)) if (k != !(s->sh_flags & SHF_EXECINSTR))
continue; continue;
offset += fill; 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 0
if (mem) if (mem)
printf("%-16s +%02lx %p %04x\n", printf("%-16s +%02lx %p %04x\n",
@ -242,13 +257,15 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
continue; continue;
length = s->data_offset; length = s->data_offset;
ptr = (void*)s->sh_addr; 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) if (NULL == s->data || s->sh_type == SHT_NOBITS)
memset(ptr, 0, length); memset(ptr, 0, length);
else else
memcpy(ptr, s->data, length); memcpy(ptr, s->data, length);
/* mark executable sections as executable in memory */ /* mark executable sections as executable in memory */
if (s->sh_flags & SHF_EXECINSTR) if (s->sh_flags & SHF_EXECINSTR)
set_pages_executable(ptr, length); set_pages_executable((char*)ptr + ptr_diff, length);
} }
return 0; return 0;
} }
@ -263,15 +280,17 @@ static void set_pages_executable(void *ptr, unsigned long length)
VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect); VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
#else #else
void __clear_cache(void *beginning, void *end); void __clear_cache(void *beginning, void *end);
# ifndef HAVE_SELINUX
addr_t start, end; addr_t start, end;
#ifndef PAGESIZE # ifndef PAGESIZE
# define PAGESIZE 4096 # define PAGESIZE 4096
#endif # endif
start = (addr_t)ptr & ~(PAGESIZE - 1); start = (addr_t)ptr & ~(PAGESIZE - 1);
end = (addr_t)ptr + length; end = (addr_t)ptr + length;
end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
if (mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC)) if (mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC))
tcc_error("mprotect failed: did you mean to configure --with-selinux?"); tcc_error("mprotect failed: did you mean to configure --with-selinux?");
# endif
# if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 # if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64
__clear_cache(ptr, (char *)ptr + length); __clear_cache(ptr, (char *)ptr + length);
# endif # endif

View File

@ -120,6 +120,8 @@
DEF(TOK_FASTCALL1, "fastcall") DEF(TOK_FASTCALL1, "fastcall")
DEF(TOK_FASTCALL2, "__fastcall") DEF(TOK_FASTCALL2, "__fastcall")
DEF(TOK_FASTCALL3, "__fastcall__") DEF(TOK_FASTCALL3, "__fastcall__")
DEF(TOK_REGPARM1, "regparm")
DEF(TOK_REGPARM2, "__regparm__")
DEF(TOK_MODE, "__mode__") DEF(TOK_MODE, "__mode__")
DEF(TOK_MODE_QI, "__QI__") DEF(TOK_MODE_QI, "__QI__")
@ -134,23 +136,19 @@
DEF(TOK_NORETURN2, "__noreturn__") DEF(TOK_NORETURN2, "__noreturn__")
DEF(TOK_VISIBILITY1, "visibility") DEF(TOK_VISIBILITY1, "visibility")
DEF(TOK_VISIBILITY2, "__visibility__") DEF(TOK_VISIBILITY2, "__visibility__")
DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p") DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
DEF(TOK_builtin_choose_expr, "__builtin_choose_expr") DEF(TOK_builtin_choose_expr, "__builtin_choose_expr")
DEF(TOK_builtin_constant_p, "__builtin_constant_p") DEF(TOK_builtin_constant_p, "__builtin_constant_p")
DEF(TOK_builtin_frame_address, "__builtin_frame_address") DEF(TOK_builtin_frame_address, "__builtin_frame_address")
DEF(TOK_builtin_return_address, "__builtin_return_address") DEF(TOK_builtin_return_address, "__builtin_return_address")
DEF(TOK_builtin_expect, "__builtin_expect") DEF(TOK_builtin_expect, "__builtin_expect")
#ifdef TCC_TARGET_X86_64 /*DEF(TOK_builtin_va_list, "__builtin_va_list")*/
#ifdef TCC_TARGET_PE #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
DEF(TOK_builtin_va_start, "__builtin_va_start") 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") DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types")
#endif #elif defined TCC_TARGET_ARM64
#endif
DEF(TOK_REGPARM1, "regparm")
DEF(TOK_REGPARM2, "__regparm__")
#ifdef TCC_TARGET_ARM64
DEF(TOK___va_start, "__va_start") DEF(TOK___va_start, "__va_start")
DEF(TOK___va_arg, "__va_arg") DEF(TOK___va_arg, "__va_arg")
#endif #endif

View File

@ -234,8 +234,12 @@ vla_test-run: vla_test$(EXESUF)
cross-test : cross-test :
@echo ------------ $@ ------------ @echo ------------ $@ ------------
$(TOP)/i386-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok" $(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-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-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)/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)/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" $(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"

View File

@ -1,3 +1,2 @@
# `modelist' label. Each video mode record looks like:
.text .text
endtext: endtext:

View File

@ -12,7 +12,7 @@ return n(A)n(++)n(+)n(+)n(B);
return n(0x1E)n(-1); return n(0x1E)n(-1);
// unlike gcc but correct // 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 // 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);

View File

@ -3,5 +3,3 @@ return A+++B;
return A+ ++B; return A+ ++B;
return A+++ +B; return A+++ +B;
return 0x1E -1; return 0x1E -1;
XXX: return x+x-1 +1 -2;
XXX: return x x 1 2 x;

View File

@ -12,7 +12,7 @@ TESTS = $(call files,c) $(call files,S)
all test : $(sort $(TESTS)) 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 source directory in warnings/errors (out-of-tree builds)
FILTER = 2>&1 | sed 's,$(SRC)/,,g' FILTER = 2>&1 | sed 's,$(SRC)/,,g'
@ -40,7 +40,7 @@ clean:
rm -f *.output rm -f *.output
02.test : DIFF_OPTS += -w 02.test : DIFF_OPTS += -w
15.test : DIFF_OPTS += -I"^XXX:" # 15.test : DIFF_OPTS += -I"^XXX:"
# diff options: # diff options:
# -b ighore space changes # -b ighore space changes

View File

@ -3235,6 +3235,7 @@ void asm_local_statics (void)
} }
#endif #endif
static
unsigned int set; unsigned int set;
void fancy_copy (unsigned *in, unsigned *out) 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"); asm volatile ("mov %0,(%1)" : : "r" (*in), "r" (out) : "memory");
} }
#ifdef __x86_64__ #if defined __x86_64__ && !defined _WIN64
void clobber_r12(void) void clobber_r12(void)
{ {
asm volatile("mov $1, %%r12" ::: "r12"); asm volatile("mov $1, %%r12" ::: "r12");
@ -3256,7 +3257,7 @@ void clobber_r12(void)
void test_high_clobbers(void) void test_high_clobbers(void)
{ {
#ifdef __x86_64__ #if defined __x86_64__ && !defined _WIN64
register long val asm("r12"); register long val asm("r12");
long val2; long val2;
/* This tests if asm clobbers correctly save/restore callee saved /* 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. */ correctly capture the data flow, but good enough for us. */
asm volatile("mov $0x4542, %%r12" : "=r" (val):: "memory"); asm volatile("mov $0x4542, %%r12" : "=r" (val):: "memory");
clobber_r12(); clobber_r12();
#ifndef _WIN64
asm volatile("mov %%r12, %0" : "=r" (val2) : "r" (val): "memory"); asm volatile("mov %%r12, %0" : "=r" (val2) : "r" (val): "memory");
printf("asmhc: 0x%x\n", val2); printf("asmhc: 0x%x\n", val2);
#endif #endif
#endif
} }
static long cpu_number; static long cpu_number;

View File

@ -70,7 +70,7 @@
{ {
struct M P __s { struct M P __s {
int a; int a;
char b; signed char b;
int x : 12, y : 4, : 0, : 4, z : 3; int x : 12, y : 4, : 0, : 4, z : 3;
char d; char d;
}; };

View File

@ -78,7 +78,7 @@ te1:;
tl += &&te1 - &&ts1; tl += &&te1 - &&ts1;
printf("size of data/text:\n %s/%s\n", printf("size of data/text:\n %s/%s\n",
dl ? "non-zero":"zero", tl ? "non-zero":"zero"); dl ? "non-zero":"zero", tl ? "non-zero":"zero");
printf("# %d/%d\n", dl, tl); /*printf("# %d/%d\n", dl, tl);*/
} }
#endif #endif

View File

@ -17,9 +17,7 @@ data:
333 44 555555 6 7 333 44 555555 6 7
size of data/text: size of data/text:
non-zero/non-zero non-zero/non-zero
# 111/193
[test_data_suppression_on] [test_data_suppression_on]
size of data/text: size of data/text:
zero/zero zero/zero
# 0/0

View File

@ -70,7 +70,7 @@ all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ;
T1 = $(TCC) $(FLAGS) $< -o a.exe && ./a.exe $(ARGS) T1 = $(TCC) $(FLAGS) $< -o a.exe && ./a.exe $(ARGS)
T2 = $(TCC) $(FLAGS) -run $< $(ARGS) T2 = $(TCC) $(FLAGS) -run $< $(ARGS)
T3 = $(FILTER) >$*.output 2>&1 || true \ T3 = $(FILTER) >$*.output 2>&1 || true \
&& diff -Nbu -I "^\#" $(filter %.expect,$^) $*.output \ && diff -Nbu $(filter %.expect,$^) $*.output \
&& rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS)) && rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS))
# run single test and update .expect file, e.g. "make tests2.37+" # run single test and update .expect file, e.g. "make tests2.37+"

View File

@ -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

View File

@ -4,13 +4,31 @@
@echo off @echo off
setlocal setlocal
if (%1)==(-clean) goto :cleanup
set CC=gcc -Os -s -static set CC=gcc
set /p VERSION= < ..\VERSION set /p VERSION= < ..\VERSION
set INST= set INST=
set BIN=
set DOC=no set DOC=no
set EXES_ONLY=no
goto :a0 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 :usage
echo usage: build-tcc.bat [ options ... ] echo usage: build-tcc.bat [ options ... ]
echo 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 -c "prog options" use prog with options to compile tcc
echo -t 32/64 force 32/64 bit default target echo -t 32/64 force 32/64 bit default target
echo -v "version" set tcc version 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 -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 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 :cl
@echo off @echo off
set CMD=cl set CMD=cl
@ -37,52 +80,16 @@ echo on
%CMD% -O1 -W2 -Zi -MT -GS- -nologo -link -opt:ref,icf %CMD% -O1 -W2 -Zi -MT -GS- -nologo -link -opt:ref,icf
@exit /B %ERRORLEVEL% @exit /B %ERRORLEVEL%
:a2 @rem ------------------------------------------------------
shift @rem main program
: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
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 :p1
if not %T%_==_ goto :p2 if not %T%_==_ goto :p2
set T=32 set T=32
if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=64 if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=64
if %PROCESSOR_ARCHITEW6432%_==AMD64_ set T=64 if %PROCESSOR_ARCHITEW6432%_==AMD64_ set T=64
:p2 :p2
if "%CC:~-3%"=="gcc" set CC=%CC% -Os -s -static
set D32=-DTCC_TARGET_PE -DTCC_TARGET_I386 set D32=-DTCC_TARGET_PE -DTCC_TARGET_I386
set D64=-DTCC_TARGET_PE -DTCC_TARGET_X86_64 set D64=-DTCC_TARGET_PE -DTCC_TARGET_X86_64
set P32=i386-win32 set P32=i386-win32
@ -91,13 +98,14 @@ if %T%==64 goto :t64
set D=%D32% set D=%D32%
set DX=%D64% set DX=%D64%
set PX=%P64% set PX=%P64%
goto :t96 goto :p3
:t64 :t64
set D=%D64% set D=%D64%
set DX=%D32% set DX=%D32%
set PX=%P32% set PX=%P32%
:t96 goto :p3
:p3
@echo on @echo on
:config.h :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 tcc.exe ..\tcc.c libtcc.dll %D% -DONE_SOURCE"=0"
%CC% -o %PX%-tcc.exe ..\tcc.c %DX% %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 libtcc mkdir libtcc
if not exist doc mkdir doc if not exist doc mkdir doc
@ -170,8 +178,11 @@ for %%f in (*.o *.def) do @del %%f
:copy-install :copy-install
@if (%INST%)==() goto :the_end @if (%INST%)==() goto :the_end
if not exist %INST% mkdir %INST% 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 @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 for %%f in (include examples libtcc doc) do @xcopy>nul /s/i/q/y %%f %INST%\%%f
:the_end :the_end

View File

@ -16,11 +16,6 @@
#define _PC_53 0x00010000 // 53 bits #define _PC_53 0x00010000 // 53 bits
#define _PC_64 0x00000000 // 64 bits #define _PC_64 0x00000000 // 64 bits
typedef struct
{
int newmode;
} _startupinfo;
#ifdef _UNICODE #ifdef _UNICODE
#define __tgetmainargs __wgetmainargs #define __tgetmainargs __wgetmainargs
#define _tstart _wstart #define _tstart _wstart
@ -33,6 +28,7 @@ typedef struct
#define _runtmain _runmain #define _runtmain _runmain
#endif #endif
typedef struct { int newmode; } _startupinfo;
int __cdecl __tgetmainargs(int *pargc, _TCHAR ***pargv, _TCHAR ***penv, int globb, _startupinfo*); int __cdecl __tgetmainargs(int *pargc, _TCHAR ***pargv, _TCHAR ***penv, int globb, _startupinfo*);
void __cdecl __set_app_type(int apptype); void __cdecl __set_app_type(int apptype);
unsigned int __cdecl _controlfp(unsigned int new_value, unsigned int mask); unsigned int __cdecl _controlfp(unsigned int new_value, unsigned int mask);
@ -44,23 +40,19 @@ int _dowildcard;
void _tstart(void) void _tstart(void)
{ {
__TRY__ __TRY__
int ret; _startupinfo start_info = {0};
_startupinfo start_info;
// Sets the current application type // Sets the current application type
__set_app_type(_CONSOLE_APP); __set_app_type(_CONSOLE_APP);
// Set default FP precision to 53 bits (8-byte double) // Set default FP precision to 53 bits (8-byte double)
// _MCW_PC (Precision control) is not supported on // _MCW_PC (Precision control) is not supported on ARM
// the ARM and x64 architectures #if defined __i386__ || defined __x86_64__
#ifdef __i386
_controlfp(_PC_53, _MCW_PC); _controlfp(_PC_53, _MCW_PC);
#endif #endif
start_info.newmode = 0;
__tgetmainargs( &__argc, &__targv, &_tenviron, _dowildcard, &start_info); __tgetmainargs( &__argc, &__targv, &_tenviron, _dowildcard, &start_info);
ret = _tmain(__argc, __targv, _tenviron); exit(_tmain(__argc, __targv, _tenviron));
exit(ret);
} }
int _runtmain(int argc, /* as tcc passed in */ char **argv) 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; __argc = argc;
__targv = argv; __targv = argv;
#endif #endif
#if defined __i386__ || defined __x86_64__
#ifdef __i386
_controlfp(_PC_53, _MCW_PC); _controlfp(_PC_53, _MCW_PC);
#endif #endif
return _tmain(__argc, __targv, _tenviron); return _tmain(__argc, __targv, _tenviron);

View File

@ -23,71 +23,53 @@ int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int);
#define _runtwinmain _runwinmain #define _runtwinmain _runwinmain
#endif #endif
typedef struct typedef struct { int newmode; } _startupinfo;
{
int newmode;
} _startupinfo; // CLI Vs GUI
int __cdecl __tgetmainargs(int *pargc, _TCHAR ***pargv, _TCHAR ***penv, int globb, _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) int _twinstart(void)
{ {
__TRY__ __TRY__
_TCHAR *szCmd, *p;
STARTUPINFO startinfo;
_startupinfo start_info_con = {0}; _startupinfo start_info_con = {0};
int fShow;
int ret;
__set_app_type(__GUI_APP); __set_app_type(__GUI_APP);
_controlfp(0x10000, 0x30000);
start_info_con.newmode = 0;
__tgetmainargs(&__argc, &__targv, &_tenviron, 0, &start_info_con); __tgetmainargs(&__argc, &__targv, &_tenviron, 0, &start_info_con);
exit(go_winmain(__argc > 1 ? __targv[1] : NULL));
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);
} }
int _runtwinmain(int argc, /* as tcc passed in */ char **argv) int _runtwinmain(int argc, /* as tcc passed in */ char **argv)
{ {
_TCHAR *szCmd, *p;
#ifdef UNICODE #ifdef UNICODE
_startupinfo start_info = {0}; _startupinfo start_info = {0};
__tgetmainargs(&__argc, &__targv, &_tenviron, 0, &start_info); __tgetmainargs(&__argc, &__targv, &_tenviron, 0, &start_info);
/* may be wrong when tcc has received wildcards (*.c) */ /* may be wrong when tcc has received wildcards (*.c) */
if (argc < __argc) { if (argc < __argc)
__targv += __argc - argc; __targv += __argc - argc, __argc = argc;
__argc = argc;
}
#else #else
__argc = argc; __argc = argc, __targv = argv;
__targv = argv;
#endif #endif
return go_winmain(__argc > 1 ? __targv[1] : NULL);
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);
} }

View File

@ -108,6 +108,8 @@
------------------------ ------------------------
* You can use the MinGW and MSYS tools available at * You can use the MinGW and MSYS tools available at
http://www.mingw.org http://www.mingw.org
http://www.mingw-w64.org
http://www.msys2.org
Untar the TCC archive and type in the MSYS shell: Untar the TCC archive and type in the MSYS shell:
./configure [--prefix installpath] ./configure [--prefix installpath]
@ -116,29 +118,22 @@
The default install location is c:\Program Files\tcc 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 * Alternatively you can compile TCC with just GCC from MinGW using
> build-tcc.bat (from the win32 directory) > build-tcc.bat (from the win32 directory)
Also MSVC can be used with the "VSTools Developer Command Prompt": Also MSVC can be used with the "VSTools Developer Command Prompt":
> build-tcc.bat -c cl > 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 > build-tcc.bat -c some-tcc-dir\tcc.exe
Also you can copy/install everything into another directory: Also you can copy/install everything into another directory:
> build-tcc.bat -i <dir> > build-tcc.bat -i <dir>
* 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: Limitations:
------------ ------------
- On the object file level, currently TCC supports only the ELF format, - On the object file level, currently TCC supports only the ELF format,