So that the generated code, and more short

master
jiang 2014-04-29 16:05:16 +08:00
commit 2a8905c93b
78 changed files with 6652 additions and 3903 deletions

6
.gitignore vendored
View File

@ -36,10 +36,13 @@ p2.c
tcctest[1234]
test[1234].out
tests/tcclib.h
tests/tcctest.gcc
tests/tcctest.cc
tests/weaktest.*.o.txt
tests/tests2/fred.txt
tests/tests2/*.exe
tests/hello
tests/abitest-*cc
tests/vla_test
.gdb_history
tcc.1
tcc.pod
@ -53,6 +56,7 @@ lib/x86_64
lib/i386
lib/x86_64-win32
lib/i386-win32
lib/arm
tcc-doc.info
conftest*
tiny_libmaker

View File

@ -195,58 +195,53 @@ macro(make_tcc native_name cross_name cross_enabled definitions tcc_sources libt
endif()
endmacro()
make_tcc("Win32" i386-win32 TCC_BUILD_WIN32
make_tcc("Win32" i386-w64-mingw32 TCC_BUILD_WIN32
"TCC_TARGET_I386;TCC_TARGET_PE"
"${I386_SOURCES};tccpe.c"
tiny_libmaker_32 "${LIBTCC1_I386_SOURCES};${LIBTCC1_WIN_SOURCES}" "win32/include;win32/include/winapi"
)
make_tcc("Win64" x86_64-win32 TCC_BUILD_WIN64
make_tcc("Win64" x86_64-w64-mingw32 TCC_BUILD_WIN64
"TCC_TARGET_X86_64;TCC_TARGET_PE"
"${X86_64_SOURCES};tccpe.c"
tiny_libmaker_64 "lib/alloca86_64.S;${LIBTCC1_WIN_SOURCES}" "win32/include;win32/include/winapi"
)
make_tcc("WinCE" arm-win32 TCC_BUILD_WINCE
make_tcc("WinCE" arm-wince-mingw32ce TCC_BUILD_WINCE
"TCC_TARGET_ARM;TCC_ARM_VERSION=${TCC_ARM_VERSION};TCC_TARGET_PE"
"${ARM_SOURCES};tccpe.c"
"" "" ""
)
make_tcc("i386" i386 TCC_BUILD_I386
make_tcc("i386" i386-linux-gnu TCC_BUILD_I386
TCC_TARGET_I386
"${I386_SOURCES}"
tiny_libmaker_32 "${LIBTCC1_I386_SOURCES}" ""
)
make_tcc("x86_64" x86_64 TCC_BUILD_X64
make_tcc("x86_64" x86_64-linux-gnu TCC_BUILD_X64
TCC_TARGET_X86_64
"${X86_64_SOURCES}"
tiny_libmaker_64 "lib/alloca86_64.S" ""
)
set(ARM_DEFINITIONS TCC_TARGET_ARM TCC_ARM_VERSION=${TCC_ARM_VERSION})
make_tcc("ARM" arm TCC_BUILD_ARM
"${ARM_DEFINITIONS};WITHOUT_LIBTCC"
"${ARM_SOURCES}"
"" "" ""
)
make_tcc("" arm-eabihf TCC_BUILD_ARM_EABIHF
make_tcc("" arm-linux-gnueabihf TCC_BUILD_ARM_EABIHF
"${ARM_DEFINITIONS};TCC_ARM_EABI;TCC_ARM_HARDFLOAT"
"${ARM_SOURCES}"
"" "" ""
)
make_tcc("" arm-eabi TCC_BUILD_ARM_EABI
make_tcc("" arm-linux-gnueabi TCC_BUILD_ARM_EABI
"${ARM_DEFINITIONS};TCC_ARM_EABI"
"${ARM_SOURCES}"
"" "" ""
)
make_tcc("" arm-fpa TCC_BUILD_ARM_FPA
make_tcc("" arm-linux-fpa TCC_BUILD_ARM_FPA
"${ARM_DEFINITIONS}"
"${ARM_SOURCES}"
"" "" ""
)
make_tcc("" arm-fpa-ld TCC_BUILD_ARM_FPA_LD
make_tcc("" arm-linux-fpa-ld TCC_BUILD_ARM_FPA_LD
"${ARM_DEFINITIONS};LDOUBLE_SIZE=12"
"${ARM_SOURCES}"
"" "" ""
)
make_tcc("" arm-vfp TCC_BUILD_ARM_VFP
make_tcc("" arm-linux-gnu TCC_BUILD_ARM_VFP
"${ARM_DEFINITIONS};TCC_ARM_VFP"
"${ARM_SOURCES}"
"" "" ""

121
Changelog
View File

@ -1,7 +1,126 @@
Version 0.9.27:
Licensing:
- TinyCC partly relicensed to MIT license
User interface:
- define __STDC_HOSTED__ (Michael Matz, Urs Janssen)
- added support for CPATH, C_INCLUDE_PATH and LD_LIBRARY_PATH (Andrew Aladjev
and Urs Janssen)
- added option -norunsrc to control argv[0] with tcc -run (James Lyon)
- improve --with-libgcc configure help (grischka)
- improve error message when memory is full (grischka)
- improve wording about compiler switches in documentation (Thomas Preud'homme)
- use GNU triplet prefix for cross compiler names (Thomas Preud'homme)
- ignore unknown linker optimization and as-needed option (Austin English)
Features:
- added ABI tests with native compiler using libtcc (James Lyon)
- added CMake build system with support for cross-compilation (James Lyon)
- improved variable length array support (James Lyon)
- add the possibility to use noname functions by ordinal (YX Hao)
- add a install-strip target to install tcc (Thomas Preud'homme)
- add runtime selection of float ABI on ARM (Thomas Preud'homme)
- add shared lib support on x86-64 (Michael Matz)
Platforms:
- Support Debian GNU/kfreeBSD 64bit userspace (Thomas Preud'homme)
- support Debian GNU/kfreeBSD 64bit userspace (Thomas Preud'homme)
- fix GNU/Hurd interpreter path (Thomas Preud'homme)
- fix configure script for FreeBSD host (Thomas Preud'homme)
- make tcc -run work reliably on ARM by flushing caches (Thomas Preud'homme)
- many x86-64 ABI fixes incl. XMM register passing (James Lyon)
- improve compatibility with mingw's long double (James Lyon)
- avoid .stabstr section name to be truncated on win32 (Roy)
- add support for load/store of _Bool value (Thomas Preud'homme)
- detect instruction with incorrect operands on x86-64 (Thomas Preud'homme)
- improved relocations on ARM (Thomas Preud'homme)
- add va_* macro implementation for ARM (Thomas Preud'homme)
- define __ARM_EABI__, __ARMEL__ and __ARM_PCS_VFP (Thomas Preud'homme)
- provide a runtime library for ARM (Thomas Preud'homme)
- vastly improved support for ARM hard float calling convention
(Thomas Preud'homme, Daniel Glöckner)
- tcc can uses libtcc1 on ARM (Thomas Preud'homme)
- use __fixdfdi for all float to integer conversion (grischka)
- simplify startup code for unix platforms (grischka)
- improve ELF generated on ARM (Thomas Preud'homme)
- add support for thumb to ARM relocation (Thomas Preud'homme)
- fix globbing to match MSVC on Windows (Thomas Preud'homme)
- deprecate FPA and OABI support for ARM (Thomas Preud'homme)
- warn about softfloat not being supported on ARM (Thomas Preud'homme)
Bug fixes:
- many code clean up (Urs Janssen, grischka)
- fixes of other's patches (grischka, Ramsay Jones, Michael Matz)
- fix documentation about __TINYC__ (Urs Janssen)
- improve build of documentation (Urs Janssen)
- improve build instructions (Jov)
- switch from texi2html to makeinfo --html to build tcc-doc.html (James Lyon)
- improve out of tree build (James Lyon)
- improved passing and returning of struct (James Lyon)
- fix CMake build on i386 and x86-64 (James Lyon)
- fix i386 calling convention issue (James Lyon)
- fix error in Windows build of tests (James Lyon)
- fix x86-64 long double passing (James Lyon)
- fix crash with undefined struct (grischka)
- normalize slashes on win32 to always use backslashes (grischka)
- use runtime function for float to int conversion on i386 (grischka)
- improved documentation for include and lib lookup on win32 (grischka)
- detect redefinition of function (Thomas Preud'homme)
- detect the use of array of functions (Thomas Preud'homme)
- detect use of enumerator with wrong enumeration (Thomas Preud'homme)
- detect redefinition of enumerator or enumeration (Thomas Preud'homme)
- set the user-defined library search paths first (Vittorio Giovara)
- detect usage of incomplete types inside struct/union (Amine Najahi)
- various macro bug fixes (Joseph Poirier)
- avoid wrong trigger of assert on x86-64 platform (Thomas Preud'homme)
- fix NaN comparison (Thomas Preud'homme)
- use libtcc for static linking with runtime library (Thomas Preud'homme)
- fix negation of 0.0 and -0.0 values (Thomas Preud'homme)
- fix use of long long as if condition (Thomas Preud'homme)
- disable bound check if libgcc is used (Thomas Preud'homme)
- error out when casting to void (grischka)
- remove circular dependency in Makefile (grischka)
- stop preventing gcc to do strict aliasing (grischka)
- fix Windows build of tcc (grischka)
- build runtime library for arm cross compiler (Thomas Preud'homme)
- fix installation of arm cross-compiler (Thomas Preud'homme)
- add basic test for cross-compiler (Thomas Preud'homme)
- fix failure when generating PE on x86-64 (Archidemon)
- fix floating point unary minus and plus (Michael Matz)
- add more tests for signed zero float (Michael Matz)
- fix precision of double on x86-64 (Vincent Lefevre)
- fix bound checking of argv with -run switch (Kirill Smelkov)
- work around a wine cmd bug when building tcc on Windows (Austin English)
- reenable some bound check tests (grischka)
- boundtest.c lookup honors VPATH (grischka)
- diff compared to CC in test[123]b? are now errors (grischka)
- fix test3 on Windows (grischka)
- prevent gcc from building (non functional) libtcc.a (grischka)
- fix warning related to PE file generation on x86-64 (grischka)
- stop mixing ordinary and implicit rule in Makefile (Iavael)
- fix integer to double conversion on ARM (Thomas Preud'homme)
- fix parameter passing of structure < 4 bytes on ARM (Thomas Preud'homme)
- disable builtin_frame_address test on ARM due to gcc bug (Thomas Preud'homme)
- fix initialization of struct on ARM (Thomas Preud'homme)
- fix parameter passing of (unsigned) long long bitfield (Thomas Preud'homme)
- improve float to integer tests (Thomas Preud'homme)
- fix relocation of Thumb branch to ARM function (Thomas Preud'homme)
- fix char wrong compatibility with [un]signed char (Thomas Preud'homme)
- choose the code to compile based on target in libtcc1 (Thomas Preud'homme)
- fix various clang warnings (Thomas Preud'homme)
- don't hardcode tcc in Makefile for tests (Thomas Preud'homme)
- fix relocation of __bound_init bound checking code (Thomas Preud'homme)
- accept only one basic type for a given variable (Thomas Preud'homme)
- fix error when using va_* with tcc using libgcc (Thomas Preud'homme)
- support GOT32 and PLT32 reloc on the same symbol (Thomas Preud'homme)
- fix memory leak due to symbol attributes (mingodad)
- partially fix bound checking of argv and arge (Thomas Preud'homme)
- fix possible dereference when getting name of symbol (grischka)
- fix va_list type definition on x86-64 (Daniel Glöckner)
- reduce number of scan-build false positive (mingodad)
version 0.9.26:

View File

@ -66,7 +66,7 @@ NATIVE_DEFINES_$(CONFIG_i386) += -DTCC_TARGET_I386
NATIVE_DEFINES_$(CONFIG_x86-64) += -DTCC_TARGET_X86_64
NATIVE_DEFINES_$(CONFIG_WIN32) += -DTCC_TARGET_PE
NATIVE_DEFINES_$(CONFIG_uClibc) += -DTCC_UCLIBC
NATIVE_DEFINES_$(CONFIG_arm) += -DTCC_TARGET_ARM -DWITHOUT_LIBTCC
NATIVE_DEFINES_$(CONFIG_arm) += -DTCC_TARGET_ARM
NATIVE_DEFINES_$(CONFIG_arm_eabihf) += -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT
NATIVE_DEFINES_$(CONFIG_arm_eabi) += -DTCC_ARM_EABI
NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP
@ -75,18 +75,30 @@ NATIVE_DEFINES += $(NATIVE_DEFINES_yes)
ifeq ($(TOP),.)
PROGS=tcc$(EXESUF)
I386_CROSS = i386-tcc$(EXESUF)
WIN32_CROSS = i386-win32-tcc$(EXESUF)
WIN64_CROSS = x86_64-win32-tcc$(EXESUF)
WINCE_CROSS = arm-win32-tcc$(EXESUF)
X64_CROSS = x86_64-tcc$(EXESUF)
ARM_FPA_CROSS = arm-fpa-tcc$(EXESUF)
ARM_FPA_LD_CROSS = arm-fpa-ld-tcc$(EXESUF)
ARM_VFP_CROSS = arm-vfp-tcc$(EXESUF)
ARM_EABI_CROSS = arm-eabi-tcc$(EXESUF)
I386_CROSS = i386-linux-gnu-tcc$(EXESUF)
WIN32_CROSS = i386-w64-mingw32-tcc$(EXESUF)
WIN64_CROSS = x86_64-w64-mingw32-tcc$(EXESUF)
WINCE_CROSS = arm-wince-mingw32ce-tcc$(EXESUF)
X64_CROSS = x86_64-linux-gnu-tcc$(EXESUF)
ARM_FPA_CROSS = arm-linux-fpa-tcc$(EXESUF)
ARM_FPA_LD_CROSS = arm-linux-fpa-ld-tcc$(EXESUF)
ARM_VFP_CROSS = arm-linux-gnu-tcc$(EXESUF)
ARM_EABI_CROSS = arm-linux-gnueabi-tcc$(EXESUF)
ARM_EABIHF_CROSS = arm-linux-gnueabihf-tcc$(EXESUF)
ARM_CROSS = $(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CROSS)
C67_CROSS = c67-tcc$(EXESUF)
# Legacy symlinks for cross compilers
$(I386_CROSS)_LINK = i386-tcc$(EXESUF)
$(WIN32_CROSS)_LINK = i386-win32-tcc$(EXESUF)
$(WIN64_CROSS)_LINK = x86_64-win32-tcc$(EXESUF)
$(WINCE_CROSS)_LINK = arm-win32-tcc$(EXESUF)
$(X64_CROSS)_LINK = x86_64-tcc$(EXESUF)
$(ARM_FPA_CROSS)_LINK = arm-fpa-tcc$(EXESUF)
$(ARM_FPA_LD_CROSS)_LINK = arm-fpa-ld-tcc$(EXESUF)
$(ARM_VFP_CROSS)_LINK = arm-vfp-tcc$(EXESUF)
$(ARM_EABI_CROSS)_LINK = arm-eabi-tcc$(EXESUF)
CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
CORE_FILES += tcc.h config.h libtcc.h tcctok.h
I386_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h
@ -122,16 +134,15 @@ LIBTCC1=libtcc1.a
else ifeq ($(ARCH),arm)
NATIVE_FILES=$(ARM_FILES)
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(C67_CROSS)
LIBTCC1=libtcc1.a
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a lib/i386/libtcc1.a
endif
PROGS_CROSS_LINK=$(foreach PROG_CROSS,$(PROGS_CROSS),$($(PROG_CROSS)_LINK))
ifeq ($(TARGETOS),Darwin)
PROGS+=tiny_libmaker$(EXESUF)
endif
ifdef CONFIG_USE_LIBGCC
LIBTCC1=
endif
TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCC_EXTRA)
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
@ -149,6 +160,7 @@ tcc$(EXESUF): tcc.o $(LIBTCC)
# Cross Tiny C Compilers
%-tcc$(EXESUF): tcc.c
$(CC) -o $@ $< -DONE_SOURCE $(DEFINES) $(CPPFLAGS) $(CFLAGS) $(LIBS) $(LDFLAGS)
$(if $($@_LINK),ln -sf $@ $($@_LINK))
# profiling version
tcc_p$(EXESUF): $(NATIVE_FILES)
@ -168,7 +180,7 @@ $(C67_CROSS): DEFINES = -DTCC_TARGET_C67
$(ARM_FPA_CROSS): DEFINES = -DTCC_TARGET_ARM
$(ARM_FPA_LD_CROSS)$(EXESUF): DEFINES = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12
$(ARM_VFP_CROSS): DEFINES = -DTCC_TARGET_ARM -DTCC_ARM_VFP
$(ARM_EABI_CROSS): DEFINES = -DTCC_TARGET_ARM -DTCC_ARM_EABI
$(ARM_EABI_CROSS): DEFINES = -DTCC_TARGET_ARM -DTCC_ARM_EABI -DTCC_ARM_VFP
$(I386_CROSS): $(I386_FILES)
$(X64_CROSS): $(X86_64_FILES)
@ -229,18 +241,21 @@ else
INSTALLBIN=$(INSTALL)
endif
install-strip: install
strip $(foreach PROG,$(PROGS),"$(bindir)"/$(PROG))
ifndef CONFIG_WIN32
install: $(PROGS) $(TCCLIBS) $(TCCDOCS)
mkdir -p "$(bindir)"
ifeq ($(CC),tcc)
$(INSTALL) -m755 $(PROGS) "$(bindir)"
$(INSTALL) -m755 $(PROGS) $(PROGS_CROSS_LINK) "$(bindir)"
else
$(INSTALLBIN) -m755 $(PROGS) "$(bindir)"
endif
mkdir -p "$(mandir)/man1"
-$(INSTALL) tcc.1 "$(mandir)/man1"
-$(INSTALL) -m644 tcc.1 "$(mandir)/man1"
mkdir -p "$(infodir)"
-$(INSTALL) tcc-doc.info "$(infodir)"
-$(INSTALL) -m644 tcc-doc.info "$(infodir)"
mkdir -p "$(tccdir)"
mkdir -p "$(tccdir)/include"
ifneq ($(LIBTCC1),)
@ -248,7 +263,7 @@ ifneq ($(LIBTCC1),)
endif
$(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) $(top_srcdir)/tcclib.h "$(tccdir)/include"
mkdir -p "$(libdir)"
$(INSTALL) -m755 $(LIBTCC) "$(libdir)"
$(INSTALL) -m644 $(LIBTCC) "$(libdir)"
ifdef DISABLE_STATIC
ln -sf "$(ln_libdir)/libtcc.so.1.0" "$(libdir)/libtcc.so.1"
ln -sf "$(ln_libdir)/libtcc.so.1.0" "$(libdir)/libtcc.so"
@ -260,7 +275,7 @@ endif
ifdef CONFIG_CROSS
mkdir -p "$(tccdir)/win32/lib/32"
mkdir -p "$(tccdir)/win32/lib/64"
ifeq ($(ARCH),x86-64)
ifneq ($(ARCH),i386)
mkdir -p "$(tccdir)/i386"
$(INSTALL) -m644 lib/i386/libtcc1.a "$(tccdir)/i386"
cp -r "$(tccdir)/include" "$(tccdir)/i386"
@ -269,7 +284,7 @@ endif
$(INSTALL) -m644 lib/i386-win32/libtcc1.a "$(tccdir)/win32/lib/32"
$(INSTALL) -m644 lib/x86_64-win32/libtcc1.a "$(tccdir)/win32/lib/64"
cp -r $(top_srcdir)/win32/include/. "$(tccdir)/win32/include"
cp -r $(top_srcdir)/include/. "$(tccdir)/win32/include"
cp -r "$(tccdir)/include" "$(tccdir)/win32"
endif
uninstall:
@ -282,7 +297,7 @@ uninstall:
rm -fv "$(libdir)/libtcc.so*"
rm -rf "$(tccdir)/win32"
-rmdir $(tccdir)/include
ifeq ($(ARCH),x86-64)
ifneq ($(ARCH),i386)
rm -rf "$(tccdir)/i386"
endif
else
@ -328,7 +343,7 @@ tcc-doc.info: tcc-doc.texi
export LIBTCC1
%est:
$(MAKE) -C tests $@
$(MAKE) -C tests $@ 'PROGS_CROSS=$(PROGS_CROSS)'
clean:
rm -vf $(PROGS) tcc_p$(EXESUF) tcc.pod *~ *.o *.a *.so* *.out *.exe libtcc_test$(EXESUF)
@ -358,9 +373,6 @@ tar: tcc-doc.html
rm -rf $(TCC-VERSION)
git reset
Makefile: $(top_srcdir)/Makefile
cp $< $@
.PHONY: all clean tar distclean install uninstall FORCE
endif # ifeq ($(TOP),.)

View File

@ -27,9 +27,10 @@
Author (name) I agree (YES/NO) Files/Features (optional)
------------------------------------------------------------------------------
Daniel Glöckner ? arm-gen.c
Daniel Glöckner NO arm-gen.c
Daniel Glöckner YES not arm-gen.c
Fabrice Bellard YES original author
Frédéric Feret ? x86 64/16 bit asm
Frédéric Féret YES x86 64/16 bit asm
grischka YES tccpe.c
Shinichiro Hamaji YES x86_64-gen.c
Thomas Preud'homme YES arm-gen.c

925
arm-gen.c

File diff suppressed because it is too large Load Diff

View File

@ -245,8 +245,8 @@ void gsym(int t)
}
// these are regs that tcc doesn't really know about,
// but asign them unique values so the mapping routines
// can distinquish them
// but assign them unique values so the mapping routines
// can distinguish them
#define C67_A0 105
#define C67_SP 106
@ -1879,10 +1879,11 @@ static void gcall_or_jmp(int is_jmp)
}
}
/* Return 1 if this function returns via an sret pointer, 0 otherwise */
ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) {
/* Return the number of registers needed to return the struct, or 0 if
returning via struct pointer. */
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) {
*ret_align = 1; // Never have to re-align return values for x86-64
return 1;
return 0;
}
/* generate function call with address in (vtop->t, vtop->c) and free function
@ -1900,8 +1901,6 @@ void gfunc_call(int nb_args)
for (i = 0; i < nb_args; i++) {
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
ALWAYS_ASSERT(FALSE);
} else if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
ALWAYS_ASSERT(FALSE);
} else {
/* simple type (currently always same size) */
/* XXX: implicit cast ? */
@ -1970,6 +1969,7 @@ void gfunc_prolog(CType * func_type)
/* if the function returns a structure, then add an
implicit pointer parameter */
func_vt = sym->type;
func_var = (sym->c == FUNC_ELLIPSIS);
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
func_vc = addr;
addr += 4;
@ -2102,7 +2102,7 @@ int gtst(int inv, int t)
C67_NOP(5);
t = ind1; //return where we need to patch
} else if (v == VT_JMP || v == VT_JMPI) {
} else { /* VT_JMP || VT_JMPI */
/* && or || optimization */
if ((v & 1) == inv) {
/* insert vtop->c jump list in t */
@ -2128,37 +2128,6 @@ int gtst(int inv, int t)
t = gjmp(t);
gsym(vtop->c.i);
}
} else {
if (is_float(vtop->type.t)) {
vpushi(0);
gen_op(TOK_NE);
}
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
/* constant jmp optimization */
if ((vtop->c.i != 0) != inv)
t = gjmp(t);
} else {
// I think we need to get the value on the stack
// into a register, test it, and generate a branch
// return the address of the branch, so it can be
// later patched
v = gv(RC_INT); // get value into a reg
ind1 = ind;
C67_MVKL(C67_A0, t); //r=reg to load, constant
C67_MVKH(C67_A0, t); //r=reg to load, constant
if (v != TREG_EAX && // check if not already in a conditional test reg
v != TREG_EDX && v != TREG_ST0 && v != C67_B2) {
C67_MV(v, C67_B2);
v = C67_B2;
}
C67_IREG_B_REG(inv, v, C67_A0); // [!R] B.S2x A0
C67_NOP(5);
t = ind1; //return where we need to patch
ind1 = ind;
}
}
vtop--;
return t;

114
configure vendored
View File

@ -56,6 +56,7 @@ case $targetos in
DragonFly) noldl=yes;;
OpenBSD) noldl=yes;;
FreeBSD) noldl=yes;;
NetBSD) noldl=yes;;
*) ;;
esac
@ -70,46 +71,52 @@ if test -z "$source_path" -o "$source_path" = "." ; then
source_path_used="no"
fi
case "$cpu" in
i386|i486|i586|i686|i86pc|BePC|i686-AT386)
cpu="x86"
;;
x86_64|amd64)
cpu="x86-64"
;;
arm*)
case "$cpu" in
arm|armv4l)
cpuver=4
;;
armv5tel|armv5tejl)
cpuver=5
;;
armv6j|armv6l)
cpuver=6
;;
armv7a|armv7l)
cpuver=7
;;
esac
cpu="armv4l"
;;
alpha)
cpu="alpha"
;;
"Power Macintosh"|ppc|ppc64)
cpu="powerpc"
;;
mips)
cpu="mips"
;;
s390)
cpu="s390"
;;
*)
cpu="unknown"
;;
esac
classify_cpu ()
{
cpu="$1"
case "$cpu" in
x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386)
cpu="x86"
;;
x86_64|amd64)
cpu="x86-64"
;;
arm*)
case "$cpu" in
arm|armv4l)
cpuver=4
;;
armv5tel|armv5tejl)
cpuver=5
;;
armv6j|armv6l)
cpuver=6
;;
armv7a|armv7l)
cpuver=7
;;
esac
cpu="armv4l"
;;
alpha)
cpu="alpha"
;;
"Power Macintosh"|ppc|ppc64)
cpu="powerpc"
;;
mips)
cpu="mips"
;;
s390)
cpu="s390"
;;
*)
echo "Unsupported CPU: $cpu"
exit 1
;;
esac
}
for opt do
eval opt=\"$opt\"
@ -140,14 +147,6 @@ for opt do
;;
--cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2`
;;
--cc=*) cc=`echo $opt | cut -d '=' -f 2`
;;
--extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
;;
--extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
;;
--extra-libs=*) extralibs=${opt#--extra-libs=}
;;
--sysincludepaths=*) tcc_sysincludepaths=`echo $opt | cut -d '=' -f 2`
;;
--libpaths=*) tcc_libpaths=`echo $opt | cut -d '=' -f 2`
@ -156,7 +155,15 @@ for opt do
;;
--elfinterp=*) tcc_elfinterp=`echo $opt | cut -d '=' -f 2`
;;
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
--cc=*) cc=`echo $opt | cut -d '=' -f 2`
;;
--extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
;;
--extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
;;
--extra-libs=*) extralibs=${opt#--extra-libs=}
;;
--cpu=*) build_cpu=`echo $opt | cut -d '=' -f 2`
;;
--enable-gprof) gprof="yes"
;;
@ -185,6 +192,8 @@ for opt do
esac
done
classify_cpu "$cpu"
# Checking for CFLAGS
if test -z "$CFLAGS"; then
CFLAGS="-Wall -g -O2"
@ -270,10 +279,11 @@ Advanced options (experts only):
--cc=CC use C compiler CC [$cc]
--extra-cflags= specify compiler flags [$CFLAGS]
--extra-ldflags= specify linker options []
--cpu=CPU CPU [$cpu]
--strip-binaries strip symbol tables from resulting binaries
--disable-static make libtcc.so instead of libtcc.a
--disable-rpath disable use of -rpath with the above
--with-libgcc use /lib/libgcc_s.so.1 instead of libtcc.a
--with-libgcc use libgcc_s.so.1 instead of libtcc1.a in dynamic link
--enable-mingw32 build windows version on linux with mingw32
--enable-cygwin build windows version on windows with cygwin
--enable-cross build cross compilers
@ -304,7 +314,7 @@ if test -z "$cross_prefix" ; then
if test "$mingw32" = "no" ; then
triplet="$($CONFTEST triplet)"
if test -f "/usr/lib/$triplet/crti.o" ; then
tcc_lddir="lib/$triplet"
tcc_lddir="lib"
multiarch_triplet="$triplet"
elif test -f "/usr/lib64/crti.o" ; then
tcc_lddir="lib64"
@ -355,8 +365,8 @@ Doc directory $docdir
Target root prefix $sysroot
Source path $source_path
C compiler $cc
Build CPU $cpu
Target OS $targetos
CPU $cpu
Big Endian $bigendian
gprof enabled $gprof
cross compilers $build_cross

View File

@ -37,6 +37,10 @@
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI
#endif
#if defined(_WIN32)
int _CRT_glob = 0;
#endif
int main(int argc, char *argv[])
{
switch(argc == 2 ? argv[1][0] : 0) {

3967
elf.h

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@
#define TOK_ASM_first TOK_ASM_clc
#define TOK_ASM_last TOK_ASM_emms
#define TOK_ASM_alllast TOK_ASM_pxor
#define OPC_JMP 0x01 /* jmp operand */
#define OPC_B 0x02 /* only used with OPC_WL */
@ -715,6 +716,9 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
g(b >> 8);
g(b);
return;
} else if (opcode <= TOK_ASM_alllast) {
tcc_error("bad operand with opcode '%s'",
get_tok_str(opcode, NULL));
} else {
tcc_error("unknown opcode '%s'",
get_tok_str(opcode, NULL));
@ -1378,7 +1382,7 @@ ST_FUNC void subst_asm_operand(CString *add_str,
}
}
/* generate prolog and epilog code for asm statment */
/* generate prolog and epilog code for asm statement */
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
int nb_outputs, int is_output,
uint8_t *clobber_regs,

View File

@ -463,7 +463,7 @@ ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) /* must be last !OP0 */
#undef ALT
#undef DEF_ASM_OP0

View File

@ -338,6 +338,15 @@ static void gadd_sp(int val)
}
}
static void gen_static_call(int v)
{
Sym *sym;
sym = external_global_sym(v, &func_old_type, 0);
oad(0xe8, -4);
greloc(cur_text_section, sym, ind-4, R_386_PC32);
}
/* 'is_jmp' is '1' if it is a jump */
static void gcall_or_jmp(int is_jmp)
{
@ -365,8 +374,9 @@ static void gcall_or_jmp(int is_jmp)
static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX };
static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX };
/* Return 1 if this function returns via an sret pointer, 0 otherwise */
ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align)
/* Return the number of registers needed to return the struct, or 0 if
returning via struct pointer. */
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align)
{
#ifdef TCC_TARGET_PE
int size, align;
@ -374,19 +384,19 @@ ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align)
*ret_align = 1; // Never have to re-align return values for x86
size = type_size(vt, &align);
if (size > 8) {
return 1;
return 0;
} else if (size > 4) {
ret->ref = NULL;
ret->t = VT_LLONG;
return 0;
return 1;
} else {
ret->ref = NULL;
ret->t = VT_INT;
return 0;
return 1;
}
#else
*ret_align = 1; // Never have to re-align return values for x86
return 1;
return 0;
#endif
}
@ -447,7 +457,7 @@ ST_FUNC void gfunc_call(int nb_args)
}
save_regs(0); /* save used temporary registers */
func_sym = vtop->type.ref;
func_call = FUNC_CALL(func_sym->r);
func_call = func_sym->a.func_call;
/* fast call case */
if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) ||
func_call == FUNC_FASTCALLW) {
@ -495,7 +505,7 @@ ST_FUNC void gfunc_prolog(CType *func_type)
CType *type;
sym = func_type->ref;
func_call = FUNC_CALL(sym->r);
func_call = sym->a.func_call;
addr = 8;
loc = 0;
func_vc = 0;
@ -517,6 +527,7 @@ ST_FUNC void gfunc_prolog(CType *func_type)
/* if the function returns a structure, then add an
implicit pointer parameter */
func_vt = sym->type;
func_var = (sym->c == FUNC_ELLIPSIS);
#ifdef TCC_TARGET_PE
size = type_size(&func_vt,&align);
if (((func_vt.t & VT_BTYPE) == VT_STRUCT) && (size > 8)) {
@ -582,7 +593,7 @@ ST_FUNC void gfunc_epilog(void)
&& func_bound_offset != lbounds_section->data_offset) {
int saved_ind;
int *bounds_ptr;
Sym *sym, *sym_data;
Sym *sym_data;
/* add end of table info */
bounds_ptr = section_ptr_add(lbounds_section, sizeof(int));
*bounds_ptr = 0;
@ -594,20 +605,16 @@ ST_FUNC void gfunc_epilog(void)
greloc(cur_text_section, sym_data,
ind + 1, R_386_32);
oad(0xb8, 0); /* mov %eax, xxx */
sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0);
greloc(cur_text_section, sym,
ind + 1, R_386_PC32);
oad(0xe8, -4);
gen_static_call(TOK___bound_local_new);
ind = saved_ind;
/* generate bound check local freeing */
o(0x5250); /* save returned value, if any */
greloc(cur_text_section, sym_data,
ind + 1, R_386_32);
oad(0xb8, 0); /* mov %eax, xxx */
sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0);
greloc(cur_text_section, sym,
ind + 1, R_386_PC32);
oad(0xe8, -4);
gen_static_call(TOK___bound_local_delete);
o(0x585a); /* restore returned value, if any */
}
#endif
@ -626,10 +633,8 @@ ST_FUNC void gfunc_epilog(void)
ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
#ifdef TCC_TARGET_PE
if (v >= 4096) {
Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
oad(0xb8, v); /* mov stacksize, %eax */
oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
greloc(cur_text_section, sym, ind-4, R_386_PC32);
gen_static_call(TOK___chkstk); /* call __chkstk, (does the stackframe too) */
} else
#endif
{
@ -672,7 +677,7 @@ ST_FUNC int gtst(int inv, int t)
/* fast case : can jump directly since flags are set */
g(0x0f);
t = psym((vtop->c.i - 16) ^ inv, t);
} else if (v == VT_JMP || v == VT_JMPI) {
} else { /* VT_JMP || VT_JMPI */
/* && or || optimization */
if ((v & 1) == inv) {
/* insert vtop->c jump list in t */
@ -685,23 +690,6 @@ ST_FUNC int gtst(int inv, int t)
t = gjmp(t);
gsym(vtop->c.i);
}
} else {
if (is_float(vtop->type.t) ||
(vtop->type.t & VT_BTYPE) == VT_LLONG) {
vpushi(0);
gen_op(TOK_NE);
}
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
/* constant jmp optimization */
if ((vtop->c.i != 0) != inv)
t = gjmp(t);
} else {
v = gv(RC_INT);
o(0x85);
o(0xc0 + v * 9);
g(0x0f);
t = psym(0x85 ^ inv, t);
}
}
vtop--;
return t;
@ -885,7 +873,10 @@ ST_FUNC void gen_opf(int op)
swapped = 0;
if (swapped)
o(0xc9d9); /* fxch %st(1) */
o(0xe9da); /* fucompp */
if (op == TOK_EQ || op == TOK_NE)
o(0xe9da); /* fucompp */
else
o(0xd9de); /* fcompp */
o(0xe0df); /* fnstsw %ax */
if (op == TOK_EQ) {
o(0x45e480); /* and $0x45, %ah */
@ -989,55 +980,20 @@ ST_FUNC void gen_cvt_itof(int t)
}
/* convert fp to int 't' type */
/* XXX: handle long long case */
ST_FUNC void gen_cvt_ftoi(int t)
{
int r, r2, size;
Sym *sym;
CType ushort_type;
ushort_type.t = VT_SHORT | VT_UNSIGNED;
ushort_type.ref = 0;
gv(RC_FLOAT);
if (t != VT_INT)
size = 8;
else
size = 4;
o(0x2dd9); /* ldcw xxx */
sym = external_global_sym(TOK___tcc_int_fpu_control,
&ushort_type, VT_LVAL);
greloc(cur_text_section, sym,
ind, R_386_32);
gen_le32(0);
oad(0xec81, size); /* sub $xxx, %esp */
if (size == 4)
o(0x1cdb); /* fistpl */
int bt = vtop->type.t & VT_BTYPE;
if (bt == VT_FLOAT)
vpush_global_sym(&func_old_type, TOK___fixsfdi);
else if (bt == VT_LDOUBLE)
vpush_global_sym(&func_old_type, TOK___fixxfdi);
else
o(0x3cdf); /* fistpll */
o(0x24);
o(0x2dd9); /* ldcw xxx */
sym = external_global_sym(TOK___tcc_fpu_control,
&ushort_type, VT_LVAL);
greloc(cur_text_section, sym,
ind, R_386_32);
gen_le32(0);
r = get_reg(RC_INT);
o(0x58 + r); /* pop r */
if (size == 8) {
if (t == VT_LLONG) {
vtop->r = r; /* mark reg as used */
r2 = get_reg(RC_INT);
o(0x58 + r2); /* pop r2 */
vtop->r2 = r2;
} else {
o(0x04c483); /* add $4, %esp */
}
}
vtop->r = r;
vpush_global_sym(&func_old_type, TOK___fixdfdi);
vswap();
gfunc_call(1);
vpushi(0);
vtop->r = REG_IRET;
vtop->r2 = REG_LRET;
}
/* convert from one floating point type to another */
@ -1060,18 +1016,13 @@ ST_FUNC void ggoto(void)
/* generate a bounded pointer addition */
ST_FUNC void gen_bounded_ptr_add(void)
{
Sym *sym;
/* prepare fast i386 function call (args in eax and edx) */
gv2(RC_EAX, RC_EDX);
/* save all temporary registers */
vtop -= 2;
save_regs(0);
/* do a fast function call */
sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0);
greloc(cur_text_section, sym,
ind + 1, R_386_PC32);
oad(0xe8, -4);
gen_static_call(TOK___bound_ptr_add);
/* returned pointer is in eax */
vtop++;
vtop->r = TREG_EAX | VT_BOUNDED;

View File

@ -191,7 +191,7 @@
DEF_FP(mul)
DEF_ASM(fcom)
DEF_ASM(fcom_1) /* non existant op, just to have a regular table */
DEF_ASM(fcom_1) /* non existent op, just to have a regular table */
DEF_FP1(com)
DEF_FP(comp)

View File

@ -441,6 +441,7 @@ void gfunc_prolog(int t)
/* if the function returns a structure, then add an
implicit pointer parameter */
func_vt = sym->t;
func_var = (sym->c == FUNC_ELLIPSIS);
if ((func_vt & VT_BTYPE) == VT_STRUCT) {
func_vc = addr;
addr++;
@ -515,7 +516,7 @@ int gtst(int inv, int t)
break;
}
t = out_opj(c, t);
} else if (v == VT_JMP || v == VT_JMPI) {
} else { /* VT_JMP || VT_JMPI */
/* && or || optimization */
if ((v & 1) == inv) {
/* insert vtop->c jump list in t */
@ -528,19 +529,6 @@ int gtst(int inv, int t)
t = gjmp(t);
gsym(vtop->c.i);
}
} else {
if (is_float(vtop->t)) {
vpushi(0);
gen_op(TOK_NE);
}
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
/* constant jmp optimization */
if ((vtop->c.i != 0) != inv)
t = gjmp(t);
} else {
v = gv(RC_INT);
t = out_opj(IL_OP_BRTRUE - inv, t);
}
}
vtop--;
return t;

View File

@ -27,7 +27,7 @@
#define DBL_MAX_10_EXP 308
/* horrible intel long double */
#ifdef __i386__
#if defined __i386__ || defined __x86_64__
#define LDBL_MANT_DIG 64
#define LDBL_DIG 18

View File

@ -4,18 +4,28 @@
#ifdef __x86_64__
#ifndef _WIN64
typedef void *va_list;
//This should be in sync with the declaration on our lib/libtcc1.c
/* GCC compatible definition of va_list. */
typedef struct {
unsigned int gp_offset;
unsigned int fp_offset;
union {
unsigned int overflow_offset;
char *overflow_arg_area;
};
char *reg_save_area;
} __va_list_struct;
va_list __va_start(void *fp);
void *__va_arg(va_list ap, int arg_type, int size, int align);
va_list __va_copy(va_list src);
void __va_end(va_list ap);
typedef __va_list_struct va_list[1];
#define va_start(ap, last) ((ap) = __va_start(__builtin_frame_address(0)))
void __va_start(__va_list_struct *ap, void *fp);
void *__va_arg(__va_list_struct *ap, int arg_type, int size, int align);
#define va_start(ap, last) __va_start(ap, __builtin_frame_address(0))
#define va_arg(ap, type) \
(*(type *)(__va_arg(ap, __builtin_va_arg_types(type), sizeof(type), __alignof__(type))))
#define va_copy(dest, src) ((dest) = __va_copy(src))
#define va_end(ap) __va_end(ap)
#define va_copy(dest, src) (*(dest) = *(src))
#define va_end(ap)
#else /* _WIN64 */
typedef char *va_list;
@ -25,6 +35,17 @@ typedef char *va_list;
#define va_end(ap)
#endif
#elif __arm__
typedef char *va_list;
#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
& ~(_tcc_alignof(type) - 1))
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
#define va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
&~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
#define va_copy(dest, src) (dest) = (src)
#define va_end(ap)
#else /* __i386__ */
typedef char *va_list;
/* only correct for i386 */

View File

@ -6,5 +6,6 @@
#define bool _Bool
#define true 1
#define false 0
#define __bool_true_false_are_defined 1
#endif /* _STDBOOL_H */

View File

@ -26,3 +26,18 @@ typedef unsigned long long int uint64_t;
void *alloca(size_t size);
#endif
/* Older glibc require a wint_t from <stddef.h> (when requested
by __need_wint_t, as otherwise stddef.h isn't allowed to
define this type). Note that this must be outside the normal
_STDDEF_H guard, so that it works even when we've included the file
already (without requiring wint_t). Some other libs define _WINT_T
if they've already provided that type, so we can use that as guard.
TCC defines __WINT_TYPE__ for us. */
#if defined (__need_wint_t)
#ifndef _WINT_T
#define _WINT_T
typedef __WINT_TYPE__ wint_t;
#endif
#undef __need_wint_t
#endif

View File

@ -6,7 +6,7 @@ TOP = ..
include $(TOP)/Makefile
VPATH = $(top_srcdir)/lib $(top_srcdir)/win32/lib
ifndef TARGET
ifndef TARGET # native library
ifdef CONFIG_WIN64
TARGET = x86_64-win32
else
@ -24,6 +24,11 @@ ifndef TARGET
ifneq ($(TARGETOS),Darwin)
XCC = $(CC)
endif
else
ifeq ($(ARCH),arm)
TARGET = arm
XCC = $(CC)
endif
endif
endif
endif
@ -41,20 +46,27 @@ cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)
I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)
X86_64_O = libtcc1.o alloca86_64.o
ARM_O = libtcc1.o armeabi.o alloca-arm.o
WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
WIN64_O = $(X86_64_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
# build TCC runtime library to contain PIC code, so it can be linked
# into shared libraries
PICFLAGS = -fPIC
ifeq "$(TARGET)" "i386-win32"
OBJ = $(addprefix $(DIR)/,$(WIN32_O))
TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE
XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include
XAR = $(DIR)/tiny_libmaker$(EXESUF)
PICFLAGS =
else
ifeq "$(TARGET)" "x86_64-win32"
OBJ = $(addprefix $(DIR)/,$(WIN64_O))
TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE
XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include
XAR = $(DIR)/tiny_libmaker$(EXESUF)
PICFLAGS =
else
ifeq "$(TARGET)" "i386"
OBJ = $(addprefix $(DIR)/,$(I386_O))
@ -65,14 +77,20 @@ ifeq "$(TARGET)" "x86_64"
OBJ = $(addprefix $(DIR)/,$(X86_64_O))
TGT = -DTCC_TARGET_X86_64
XCC ?= $(TCC) -B$(TOP)
else
ifeq "$(TARGET)" "arm"
OBJ = $(addprefix $(DIR)/,$(ARM_O))
TGT = -DTCC_TARGET_ARM
XCC ?= $(TCC) -B$(TOP)
else
$(error libtcc1.a not supported on target '$(TARGET)')
endif
endif
endif
endif
endif
XFLAGS = $(CPPFLAGS) $(CFLAGS) $(TGT)
XFLAGS = $(CPPFLAGS) $(CFLAGS) $(PICFLAGS) $(TGT)
ifeq ($(TARGETOS),Darwin)
XAR = $(DIR)/tiny_libmaker$(EXESUF)
@ -100,6 +118,3 @@ $(DIR)/exists :
clean :
rm -rfv i386-win32 x86_64-win32 i386 x86_64
Makefile: $(top_srcdir)/lib/Makefile
cp $< $@

11
lib/alloca-arm.S 100644
View File

@ -0,0 +1,11 @@
.text
.align 2
.global alloca
.type alloca, %function
alloca:
rsb sp, r0, sp
bic sp, sp, #7
mov r0, sp
mov pc, lr
.size alloca, .-alloca
.section .note.GNU-stack,"",%progbits

468
lib/armeabi.c 100644
View File

@ -0,0 +1,468 @@
#include <limits.h>
/* We rely on the little endianness and EABI calling convention for this to
work */
typedef struct double_unsigned_struct {
unsigned low;
unsigned high;
} double_unsigned_struct;
typedef struct unsigned_int_struct {
unsigned low;
int high;
} unsigned_int_struct;
#define REGS_RETURN(name, type) \
void name ## _return(type ret) {}
/* Float helper functions */
#define FLOAT_EXP_BITS 8
#define FLOAT_FRAC_BITS 23
#define DOUBLE_EXP_BITS 11
#define DOUBLE_FRAC_BITS 52
#define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1)
REGS_RETURN(unsigned_int_struct, unsigned_int_struct)
REGS_RETURN(double_unsigned_struct, double_unsigned_struct)
/* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */
/* float to [unsigned] long long conversion */
#define DEFINE__AEABI_F2XLZ(name, with_sign) \
void __aeabi_ ## name(unsigned val) \
{ \
int exp, high_shift, sign; \
double_unsigned_struct ret; \
\
/* compute sign */ \
sign = val >> 31; \
\
/* compute real exponent */ \
exp = val >> FLOAT_FRAC_BITS; \
exp &= (1 << FLOAT_EXP_BITS) - 1; \
exp -= ONE_EXP(FLOAT); \
\
/* undefined behavior if truncated value cannot be represented */ \
if (with_sign) { \
if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
return; \
} else { \
if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
return; \
} \
\
val &= (1 << FLOAT_FRAC_BITS) - 1; \
if (exp >= 32) { \
ret.high = 1 << (exp - 32); \
if (exp - 32 >= FLOAT_FRAC_BITS) { \
ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \
ret.low = 0; \
} else { \
high_shift = FLOAT_FRAC_BITS - (exp - 32); \
ret.high |= val >> high_shift; \
ret.low = val << (32 - high_shift); \
} \
} else { \
ret.high = 0; \
ret.low = 1 << exp; \
if (exp > FLOAT_FRAC_BITS) \
ret.low |= val << (exp - FLOAT_FRAC_BITS); \
else \
ret.low |= val >> (FLOAT_FRAC_BITS - exp); \
} \
\
/* encode negative integer using 2's complement */ \
if (with_sign && sign) { \
ret.low = ~ret.low; \
ret.high = ~ret.high; \
if (ret.low == UINT_MAX) { \
ret.low = 0; \
ret.high++; \
} else \
ret.low++; \
} \
\
double_unsigned_struct_return(ret); \
}
/* float to unsigned long long conversion */
DEFINE__AEABI_F2XLZ(f2ulz, 0)
/* float to long long conversion */
DEFINE__AEABI_F2XLZ(f2lz, 1)
/* double to [unsigned] long long conversion */
#define DEFINE__AEABI_D2XLZ(name, with_sign) \
void __aeabi_ ## name(double_unsigned_struct val) \
{ \
int exp, high_shift, sign; \
double_unsigned_struct ret; \
\
/* compute sign */ \
sign = val.high >> 31; \
\
/* compute real exponent */ \
exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \
exp &= (1 << DOUBLE_EXP_BITS) - 1; \
exp -= ONE_EXP(DOUBLE); \
\
/* undefined behavior if truncated value cannot be represented */ \
if (with_sign) { \
if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
return; \
} else { \
if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
return; \
} \
\
val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
if (exp >= 32) { \
ret.high = 1 << (exp - 32); \
if (exp >= DOUBLE_FRAC_BITS) { \
high_shift = exp - DOUBLE_FRAC_BITS; \
ret.high |= val.high << high_shift; \
ret.high |= val.low >> (32 - high_shift); \
ret.low = val.low << high_shift; \
} else { \
high_shift = DOUBLE_FRAC_BITS - exp; \
ret.high |= val.high >> high_shift; \
ret.low = val.high << (32 - high_shift); \
ret.low |= val.low >> high_shift; \
} \
} else { \
ret.high = 0; \
ret.low = 1 << exp; \
if (exp > DOUBLE_FRAC_BITS - 32) { \
high_shift = exp - DOUBLE_FRAC_BITS - 32; \
ret.low |= val.high << high_shift; \
ret.low |= val.low >> (32 - high_shift); \
} else \
ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \
} \
\
/* encode negative integer using 2's complement */ \
if (with_sign && sign) { \
ret.low = ~ret.low; \
ret.high = ~ret.high; \
if (ret.low == UINT_MAX) { \
ret.low = 0; \
ret.high++; \
} else \
ret.low++; \
} \
\
double_unsigned_struct_return(ret); \
}
/* double to unsigned long long conversion */
DEFINE__AEABI_D2XLZ(d2ulz, 0)
/* double to long long conversion */
DEFINE__AEABI_D2XLZ(d2lz, 1)
/* long long to float conversion */
#define DEFINE__AEABI_XL2F(name, with_sign) \
unsigned __aeabi_ ## name(unsigned long long v) \
{ \
int s /* shift */, flb /* first lost bit */, sign = 0; \
unsigned p = 0 /* power */, ret; \
double_unsigned_struct val; \
\
/* fraction in negative float is encoded in 1's complement */ \
if (with_sign && (v & (1ULL << 63))) { \
sign = 1; \
v = ~v + 1; \
} \
val.low = v; \
val.high = v >> 32; \
/* fill fraction bits */ \
for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
if (p) { \
ret = val.high & (p - 1); \
if (s < FLOAT_FRAC_BITS) { \
ret <<= FLOAT_FRAC_BITS - s; \
ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \
flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \
} else { \
flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
ret >>= s - FLOAT_FRAC_BITS; \
} \
s += 32; \
} else { \
for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
if (p) { \
ret = val.low & (p - 1); \
if (s <= FLOAT_FRAC_BITS) { \
ret <<= FLOAT_FRAC_BITS - s; \
flb = 0; \
} else { \
flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
ret >>= s - FLOAT_FRAC_BITS; \
} \
} else \
return 0; \
} \
if (flb) \
ret++; \
\
/* fill exponent bits */ \
ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
\
/* fill sign bit */ \
ret |= sign << 31; \
\
return ret; \
}
/* unsigned long long to float conversion */
DEFINE__AEABI_XL2F(ul2f, 0)
/* long long to float conversion */
DEFINE__AEABI_XL2F(l2f, 1)
/* long long to double conversion */
#define __AEABI_XL2D(name, with_sign) \
void __aeabi_ ## name(unsigned long long v) \
{ \
int s /* shift */, high_shift, sign = 0; \
unsigned tmp, p = 0; \
double_unsigned_struct val, ret; \
\
/* fraction in negative float is encoded in 1's complement */ \
if (with_sign && (v & (1ULL << 63))) { \
sign = 1; \
v = ~v + 1; \
} \
val.low = v; \
val.high = v >> 32; \
\
/* fill fraction bits */ \
for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
if (p) { \
tmp = val.high & (p - 1); \
if (s < DOUBLE_FRAC_BITS - 32) { \
high_shift = DOUBLE_FRAC_BITS - 32 - s; \
ret.high = tmp << high_shift; \
ret.high |= val.low >> (32 - high_shift); \
ret.low = val.low << high_shift; \
} else { \
high_shift = s - (DOUBLE_FRAC_BITS - 32); \
ret.high = tmp >> high_shift; \
ret.low = tmp << (32 - high_shift); \
ret.low |= val.low >> high_shift; \
if ((val.low >> (high_shift - 1)) & 1) { \
if (ret.low == UINT_MAX) { \
ret.high++; \
ret.low = 0; \
} else \
ret.low++; \
} \
} \
s += 32; \
} else { \
for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
if (p) { \
tmp = val.low & (p - 1); \
if (s <= DOUBLE_FRAC_BITS - 32) { \
high_shift = DOUBLE_FRAC_BITS - 32 - s; \
ret.high = tmp << high_shift; \
ret.low = 0; \
} else { \
high_shift = s - (DOUBLE_FRAC_BITS - 32); \
ret.high = tmp >> high_shift; \
ret.low = tmp << (32 - high_shift); \
} \
} else { \
ret.high = ret.low = 0; \
double_unsigned_struct_return(ret); \
} \
} \
\
/* fill exponent bits */ \
ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \
\
/* fill sign bit */ \
ret.high |= sign << 31; \
\
double_unsigned_struct_return(ret); \
}
/* unsigned long long to double conversion */
__AEABI_XL2D(ul2d, 0)
/* long long to double conversion */
__AEABI_XL2D(l2d, 1)
/* Long long helper functions */
/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
#define define_aeabi_xdivmod_signed_type(basetype, type) \
typedef struct type { \
basetype quot; \
unsigned basetype rem; \
} type
#define define_aeabi_xdivmod_unsigned_type(basetype, type) \
typedef struct type { \
basetype quot; \
basetype rem; \
} type
#define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
static inline rettype aeabi_ ## name (type num, type den) \
{ \
rettype ret; \
type quot = 0; \
\
/* Increase quotient while it is less than numerator */ \
while (num >= den) { \
type q = 1; \
\
/* Find closest power of two */ \
while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
q <<= 1; \
\
/* Compute difference between current quotient and numerator */ \
num -= q * den; \
quot += q; \
} \
ret.quot = quot; \
ret.rem = num; \
return ret; \
}
#define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \
void __aeabi_ ## name(type numerator, type denominator) \
{ \
unsigned type num, den; \
urettype uxdiv_ret; \
rettype ret; \
\
if (numerator >= 0) \
num = numerator; \
else \
num = 0 - numerator; \
if (denominator >= 0) \
den = denominator; \
else \
den = 0 - denominator; \
uxdiv_ret = aeabi_ ## uiname(num, den); \
/* signs differ */ \
if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
ret.quot = 0 - uxdiv_ret.quot; \
else \
ret.quot = uxdiv_ret.quot; \
if (numerator < 0) \
ret.rem = 0 - uxdiv_ret.rem; \
else \
ret.rem = uxdiv_ret.rem; \
\
rettype ## _return(ret); \
}
define_aeabi_xdivmod_signed_type(long long, lldiv_t);
define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t);
define_aeabi_xdivmod_signed_type(int, idiv_t);
define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t);
REGS_RETURN(lldiv_t, lldiv_t)
REGS_RETURN(ulldiv_t, ulldiv_t)
REGS_RETURN(idiv_t, idiv_t)
REGS_RETURN(uidiv_t, uidiv_t)
AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULONG)
__AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG)
void __aeabi_uldivmod(unsigned long long num, unsigned long long den)
{
ulldiv_t_return(aeabi_uldivmod(num, den));
}
void __aeabi_llsl(double_unsigned_struct val, int shift)
{
double_unsigned_struct ret;
if (shift >= 32) {
val.high = val.low;
val.low = 0;
shift -= 32;
}
if (shift > 0) {
ret.low = val.low << shift;
ret.high = (val.high << shift) | (val.low >> (32 - shift));
double_unsigned_struct_return(ret);
return;
}
double_unsigned_struct_return(val);
}
#define aeabi_lsr(val, shift, fill, type) \
type ## _struct ret; \
\
if (shift >= 32) { \
val.low = val.high; \
val.high = fill; \
shift -= 32; \
} \
if (shift > 0) { \
ret.high = val.high >> shift; \
ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
type ## _struct_return(ret); \
return; \
} \
type ## _struct_return(val);
void __aeabi_llsr(double_unsigned_struct val, int shift)
{
aeabi_lsr(val, shift, 0, double_unsigned);
}
void __aeabi_lasr(unsigned_int_struct val, int shift)
{
aeabi_lsr(val, shift, val.high >> 31, unsigned_int);
}
/* Integer division functions */
AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
int __aeabi_idiv(int numerator, int denominator)
{
unsigned num, den;
uidiv_t ret;
if (numerator >= 0)
num = numerator;
else
num = 0 - numerator;
if (denominator >= 0)
den = denominator;
else
den = 0 - denominator;
ret = aeabi_uidivmod(num, den);
if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */
ret.quot *= -1;
return ret.quot;
}
unsigned __aeabi_uidiv(unsigned num, unsigned den)
{
return aeabi_uidivmod(num, den).quot;
}
__AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT)
void __aeabi_uidivmod(unsigned num, unsigned den)
{
uidiv_t_return(aeabi_uidivmod(num, den));
}

View File

@ -22,7 +22,7 @@
#include <stdarg.h>
#include <string.h>
#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) \
&& !defined(__DragonFly__) && !defined(__OpenBSD__)
&& !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
#include <malloc.h>
#endif
#if !defined(_WIN32)
@ -41,7 +41,7 @@
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
|| defined(__DragonFly__) || defined(__dietlibc__) \
|| defined(__UCLIBC__) || defined(__OpenBSD__) \
|| defined(__UCLIBC__) || defined(__OpenBSD__) || defined(__NetBSD__) \
|| defined(_WIN32) || defined(TCC_UCLIBC)
#warning Bound checking does not support malloc (etc.) in this environment.
#undef CONFIG_TCC_MALLOC_HOOKS
@ -418,6 +418,13 @@ void __bound_init(void)
}
}
void __bound_main_arg(void **p)
{
void *start = p;
while (*p++);
__bound_new_region(start, (void *) p - start);
}
void __bound_exit(void)
{
restore_malloc_hooks();
@ -628,7 +635,7 @@ int __bound_delete_region(void *p)
}
/* return the size of the region starting at p, or EMPTY_SIZE if non
existant region. */
existent region. */
static unsigned long get_region_size(void *p)
{
unsigned long addr = (unsigned long)p;

View File

@ -28,6 +28,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <stdint.h>
#define W_TYPE_SIZE 32
#define BITS_PER_UNIT 8
@ -107,10 +109,10 @@ union float_long {
};
/* XXX: we don't support several builtin supports for now */
#ifndef __x86_64__
#if !defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_ARM)
/* XXX: use gcc/tcc intrinsic ? */
#if defined(__i386__)
#if defined(TCC_TARGET_I386)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \
: "=r" ((USItype) (sh)), \
@ -478,13 +480,6 @@ long long __ashldi3(long long a, int b)
#endif
}
#if defined(__i386__)
/* FPU control word for rounding to nearest mode */
unsigned short __tcc_fpu_control = 0x137f;
/* FPU control word for round to zero mode for int conversion */
unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00;
#endif
#endif /* !__x86_64__ */
/* XXX: fix tcc's code generator to do this instead */
@ -605,15 +600,38 @@ unsigned long long __fixunsxfdi (long double a1)
return 0;
}
#if defined(__x86_64__) && !defined(_WIN64)
long long __fixsfdi (float a1)
{
long long ret; int s;
ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1);
return s ? ret : -ret;
}
long long __fixdfdi (double a1)
{
long long ret; int s;
ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1);
return s ? ret : -ret;
}
long long __fixxfdi (long double a1)
{
long long ret; int s;
ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1);
return s ? ret : -ret;
}
#if defined(TCC_TARGET_X86_64) && !defined(_WIN64)
#ifndef __TINYC__
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#else
/* Avoid including stdlib.h because it is not easily available when
cross compiling */
extern void *malloc(unsigned long long);
void *memset(void *s, int c, size_t n);
extern void free(void*);
extern void abort(void);
#endif
@ -622,8 +640,9 @@ enum __va_arg_type {
__va_gen_reg, __va_float_reg, __va_stack
};
//This should be in sync with the declaration on our include/stdarg.h
/* GCC compatible definition of va_list. */
struct __va_list_struct {
typedef struct {
unsigned int gp_offset;
unsigned int fp_offset;
union {
@ -631,19 +650,22 @@ struct __va_list_struct {
char *overflow_arg_area;
};
char *reg_save_area;
};
} __va_list_struct;
void *__va_start(void *fp)
#undef __va_start
#undef __va_arg
#undef __va_copy
#undef __va_end
void __va_start(__va_list_struct *ap, void *fp)
{
struct __va_list_struct *ap =
(struct __va_list_struct *)malloc(sizeof(struct __va_list_struct));
*ap = *(struct __va_list_struct *)((char *)fp - 16);
memset(ap, 0, sizeof(__va_list_struct));
*ap = *(__va_list_struct *)((char *)fp - 16);
ap->overflow_arg_area = (char *)fp + ap->overflow_offset;
ap->reg_save_area = (char *)fp - 176 - 16;
return ap;
}
void *__va_arg(struct __va_list_struct *ap,
void *__va_arg(__va_list_struct *ap,
enum __va_arg_type arg_type,
int size, int align)
{
@ -669,7 +691,7 @@ void *__va_arg(struct __va_list_struct *ap,
case __va_stack:
use_overflow_area:
ap->overflow_arg_area += size;
ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -(long long)align);
ap->overflow_arg_area = (char*)((intptr_t)(ap->overflow_arg_area + align - 1) & -(intptr_t)align);
return ap->overflow_arg_area - size;
default:
@ -680,28 +702,38 @@ void *__va_arg(struct __va_list_struct *ap,
}
}
void *__va_copy(struct __va_list_struct *src)
{
struct __va_list_struct *dest =
(struct __va_list_struct *)malloc(sizeof(struct __va_list_struct));
*dest = *src;
return dest;
}
void __va_end(struct __va_list_struct *ap)
{
free(ap);
}
#endif /* __x86_64__ */
/* Flushing for tccrun */
#if defined(__x86_64__) || defined(__i386__)
#if defined(TCC_TARGET_X86_64) || defined(TCC_TARGET_I386)
void __clear_cache(char *beginning, char *end)
{
}
#elif defined(TCC_TARGET_ARM)
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
void __clear_cache(char *beginning, char *end)
{
/* __ARM_NR_cacheflush is kernel private and should not be used in user space.
* However, there is no ARM asm parser in tcc so we use it for now */
#if 1
syscall(__ARM_NR_cacheflush, beginning, end, 0);
#else
__asm__ ("push {r7}\n\t"
"mov r7, #0xf0002\n\t"
"mov r2, #0\n\t"
"swi 0\n\t"
"pop {r7}\n\t"
"ret");
#endif
}
#else
#warning __clear_cache not defined for this architecture, avoid using tcc -run
#endif

176
libtcc.c
View File

@ -1,6 +1,6 @@
/*
* TCC - Tiny C Compiler
*
*
* Copyright (c) 2001-2004 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
@ -78,21 +78,13 @@ ST_FUNC void asm_global_instr(void)
#endif
/********************************************************/
#ifdef _WIN32
// GCC appears to use '/' for relative paths and '\\' for absolute paths on Windows
static char *normalize_slashes(char *path)
{
char *p;
if (path[1] == ':') {
for (p = path+2; *p; ++p)
if (*p == '/')
*p = '\\';
} else {
for (p = path; *p; ++p)
if (*p == '\\')
*p = '/';
}
for (p = path; *p; ++p)
if (*p == '\\')
*p = '/';
return path;
}
@ -129,7 +121,7 @@ void dlclose(void *p)
#endif
#ifdef LIBTCC_AS_DLL
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved)
{
if (DLL_PROCESS_ATTACH == dwReason)
tcc_module = hDll;
@ -164,7 +156,7 @@ PUB_FUNC char *pstrcat(char *buf, int buf_size, const char *s)
{
int len;
len = strlen(buf);
if (len < buf_size)
if (len < buf_size)
pstrcpy(buf + len, buf_size - len, s);
return buf;
}
@ -222,7 +214,7 @@ PUB_FUNC void *tcc_malloc(unsigned long size)
void *ptr;
ptr = malloc(size);
if (!ptr && size)
tcc_error("memory full");
tcc_error("memory full (malloc)");
#ifdef MEM_DEBUG
mem_cur_size += malloc_usable_size(ptr);
if (mem_cur_size > mem_max_size)
@ -247,7 +239,7 @@ PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size)
#endif
ptr1 = realloc(ptr, size);
if (!ptr1 && size)
tcc_error("memory full");
tcc_error("memory full (realloc)");
#ifdef MEM_DEBUG
/* NOTE: count not correct if alloc error, but not critical */
mem_cur_size += malloc_usable_size(ptr1);
@ -283,7 +275,7 @@ ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data)
{
int nb, nb_alloc;
void **pp;
nb = *nb_ptr;
pp = *ptab;
/* every power of two we double array size */
@ -379,7 +371,7 @@ ST_FUNC void section_realloc(Section *sec, unsigned long new_size)
{
unsigned long size;
unsigned char *data;
size = sec->data_allocated;
if (size == 0)
size = 1;
@ -422,7 +414,7 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name)
int i;
for(i = 1; i < s1->nb_sections; i++) {
sec = s1->sections[i];
if (!strcmp(name, sec->name))
if (!strcmp(name, sec->name))
return sec;
}
/* sections are created as PROGBITS */
@ -431,7 +423,7 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name)
/* update sym->c so that it points to an external symbol in section
'section' with value 'value' */
ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
addr_t value, unsigned long size,
int can_add_underscore)
{
@ -442,7 +434,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
if (section == NULL)
sh_num = SHN_UNDEF;
else if (section == SECTION_ABS)
else if (section == SECTION_ABS)
sh_num = SHN_ABS;
else
sh_num = section->sh_num;
@ -476,13 +468,13 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
switch(sym->v) {
#ifdef TCC_TARGET_PE
/* XXX: we rely only on malloc hooks */
case TOK_malloc:
case TOK_free:
case TOK_realloc:
case TOK_memalign:
case TOK_calloc:
case TOK_malloc:
case TOK_free:
case TOK_realloc:
case TOK_memalign:
case TOK_calloc:
#endif
case TOK_memcpy:
case TOK_memcpy:
case TOK_memmove:
case TOK_memset:
case TOK_strlen:
@ -499,23 +491,26 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
#ifdef TCC_TARGET_PE
if (sym->type.t & VT_EXPORT)
other |= 1;
other |= ST_PE_EXPORT;
if (sym_type == STT_FUNC && sym->type.ref) {
int attr = sym->type.ref->r;
if (FUNC_EXPORT(attr))
other |= 1;
if (FUNC_CALL(attr) == FUNC_STDCALL && can_add_underscore) {
sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr) * PTR_SIZE);
Sym *ref = sym->type.ref;
if (ref->a.func_export)
other |= ST_PE_EXPORT;
if (ref->a.func_call == FUNC_STDCALL && can_add_underscore) {
sprintf(buf1, "_%s@%d", name, ref->a.func_args * PTR_SIZE);
name = buf1;
other |= 2;
other |= ST_PE_STDCALL;
can_add_underscore = 0;
}
} else {
if (find_elf_sym(tcc_state->dynsymtab_section, name))
other |= 4;
other |= ST_PE_IMPORT;
if (sym->type.t & VT_IMPORT)
other |= 4;
other |= ST_PE_IMPORT;
}
#else
if (! (sym->type.t & VT_STATIC))
other = (sym->type.t & VT_VIS_MASK) >> VT_VIS_SHIFT;
#endif
if (tcc_state->leading_underscore && can_add_underscore) {
buf1[0] = '_';
@ -535,7 +530,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
}
}
ST_FUNC void put_extern_sym(Sym *sym, Section *section,
ST_FUNC void put_extern_sym(Sym *sym, Section *section,
addr_t value, unsigned long size)
{
put_extern_sym2(sym, section, value, size, 1);
@ -575,7 +570,7 @@ static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
{
char buf[2048];
BufferedFile **pf, *f;
buf[0] = '\0';
/* use upper file if inline ":asm:" or token ":paste:" */
for (f = file; f && f->filename[0] == ':'; f = f->prev)
@ -726,28 +721,28 @@ static int tcc_compile(TCCState *s1)
cur_text_section = NULL;
funcname = "";
anon_sym = SYM_FIRST_ANOM;
anon_sym = SYM_FIRST_ANOM;
/* file info: full path + filename */
section_sym = 0; /* avoid warning */
if (s1->do_debug) {
section_sym = put_elf_sym(symtab_section, 0, 0,
ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
section_sym = put_elf_sym(symtab_section, 0, 0,
ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
text_section->sh_num, NULL);
getcwd(buf, sizeof(buf));
#ifdef _WIN32
normalize_slashes(buf);
#endif
pstrcat(buf, sizeof(buf), "/");
put_stabs_r(buf, N_SO, 0, 0,
put_stabs_r(buf, N_SO, 0, 0,
text_section->data_offset, text_section, section_sym);
put_stabs_r(file->filename, N_SO, 0, 0,
put_stabs_r(file->filename, N_SO, 0, 0,
text_section->data_offset, text_section, section_sym);
}
/* an elf symbol of type STT_FILE must be put so that STB_LOCAL
symbols can be safely used */
put_elf_sym(symtab_section, 0, 0,
ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
put_elf_sym(symtab_section, 0, 0,
ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
SHN_ABS, file->filename);
/* define some often used types */
@ -765,7 +760,7 @@ static int tcc_compile(TCCState *s1)
func_old_type.t = VT_FUNC;
func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
#ifdef TCC_TARGET_ARM
arm_init_types();
arm_init(s1);
#endif
#if 0
@ -802,7 +797,7 @@ static int tcc_compile(TCCState *s1)
/* end of translation unit info */
if (s1->do_debug) {
put_stabs_r(NULL, N_SO, 0, 0,
put_stabs_r(NULL, N_SO, 0, 0,
text_section->data_offset, text_section, section_sym);
}
}
@ -811,7 +806,7 @@ static int tcc_compile(TCCState *s1)
/* reset define stack, but leave -Dsymbols (may be incorrect if
they are undefined) */
free_defines(define_start);
free_defines(define_start);
gen_inline_functions();
@ -950,6 +945,16 @@ LIBTCCAPI TCCState *tcc_new(void)
tcc_define_symbol(s, "__arm", NULL);
tcc_define_symbol(s, "arm", NULL);
tcc_define_symbol(s, "__APCS_32__", NULL);
tcc_define_symbol(s, "__ARMEL__", NULL);
#if defined(TCC_ARM_EABI)
tcc_define_symbol(s, "__ARM_EABI__", NULL);
#endif
#if defined(TCC_ARM_HARDFLOAT)
s->float_abi = ARM_HARD_FLOAT;
tcc_define_symbol(s, "__ARM_PCS_VFP", NULL);
#else
s->float_abi = ARM_SOFTFP_FLOAT;
#endif
#endif
#ifdef TCC_TARGET_PE
@ -986,16 +991,23 @@ LIBTCCAPI TCCState *tcc_new(void)
#ifdef TCC_TARGET_PE
tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
tcc_define_symbol(s, "__WINT_TYPE__", "unsigned short");
#else
tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
/* wint_t is unsigned int by default, but (signed) int on BSDs
and unsigned short on windows. Other OSes might have still
other conventions, sigh. */
#if defined(__FreeBSD__) || defined (__FreeBSD_kernel__)
tcc_define_symbol(s, "__WINT_TYPE__", "int");
#else
tcc_define_symbol(s, "__WINT_TYPE__", "unsigned int");
#endif
#endif
#ifndef TCC_TARGET_PE
/* glibc defines */
tcc_define_symbol(s, "__REDIRECT(name, proto, alias)", "name proto __asm__ (#alias)");
tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", "name proto __asm__ (#alias) __THROW");
/* default library paths */
tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
/* paths for crt objects */
tcc_split_path(s, (void ***)&s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
#endif
@ -1011,13 +1023,13 @@ LIBTCCAPI TCCState *tcc_new(void)
/* symbols are always generated for linking stage */
symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
".strtab",
".hashtab", SHF_PRIVATE);
".hashtab", SHF_PRIVATE);
strtab_section = symtab_section->link;
s->symtab = symtab_section;
/* private symbol table for dynamic symbols */
s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
".dynstrtab",
".dynstrtab",
".dynhashtab", SHF_PRIVATE);
s->alacarte_link = 1;
s->nocommon = 1;
@ -1032,6 +1044,9 @@ LIBTCCAPI TCCState *tcc_new(void)
#endif
#ifdef TCC_TARGET_I386
s->seg_size = 32;
#endif
#ifdef TCC_IS_NATIVE
s->runtime_main = "main";
#endif
return s;
}
@ -1050,7 +1065,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
for(i = 0; i < s1->nb_priv_sections; i++)
free_section(s1->priv_sections[i]);
dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
/* free any loaded DLLs */
#ifdef TCC_IS_NATIVE
for ( i = 0; i < s1->nb_loaded_dlls; i++) {
@ -1059,7 +1074,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
dlclose(ref->handle);
}
#endif
/* free loaded dlls array */
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
@ -1085,12 +1100,14 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
#ifdef TCC_IS_NATIVE
# ifdef HAVE_SELINUX
munmap (s1->write_mem, s1->mem_size);
munmap (s1->runtime_mem, s1->mem_size);
munmap (s1->runtime_mem, s1->mem_size);
# else
tcc_free(s1->runtime_mem);
# endif
#endif
if(s1->sym_attrs) tcc_free(s1->sym_attrs);
tcc_free(s1);
}
@ -1192,7 +1209,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
#endif
ret = 0;
} else {
ret = tcc_load_dll(s1, fd, filename,
ret = tcc_load_dll(s1, fd, filename,
(flags & AFF_REFERENCED_DLL) != 0);
}
goto the_end;
@ -1299,8 +1316,6 @@ LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val)
So it is handled here as if it were in a DLL. */
pe_putimport(s, 0, name, (uintptr_t)val);
#else
/* XXX: Same problem on linux but currently "solved" elsewhere
via the rather dirty 'runtime_plt_and_got' hack. */
add_elf_sym(symtab_section, (uintptr_t)val, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
SHN_ABS, name);
@ -1324,9 +1339,9 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
/* define symbol */
tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
/* create bounds sections */
bounds_section = new_section(s, ".bounds",
bounds_section = new_section(s, ".bounds",
SHT_PROGBITS, SHF_ALLOC);
lbounds_section = new_section(s, ".lbounds",
lbounds_section = new_section(s, ".lbounds",
SHT_PROGBITS, SHF_ALLOC);
}
#endif
@ -1347,8 +1362,8 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
put_stabs("", 0, 0, 0, 0);
}
#ifdef TCC_TARGET_PE
tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
#ifdef TCC_TARGET_PE
# ifdef _WIN32
tcc_add_systemdir(s);
# endif
@ -1557,6 +1572,10 @@ static int tcc_set_linker(TCCState *s, const char *option)
} else
goto err;
} else if (link_option(option, "as-needed", &p)) {
ignoring = 1;
} else if (link_option(option, "O", &p)) {
ignoring = 1;
} else if (link_option(option, "rpath=", &p)) {
s->rpath = copy_linker_arg(p);
} else if (link_option(option, "section-alignment=", &p)) {
@ -1628,6 +1647,7 @@ enum {
TCC_OPTION_b,
TCC_OPTION_g,
TCC_OPTION_c,
TCC_OPTION_float_abi,
TCC_OPTION_static,
TCC_OPTION_shared,
TCC_OPTION_soname,
@ -1647,7 +1667,6 @@ enum {
TCC_OPTION_pedantic,
TCC_OPTION_pthread,
TCC_OPTION_run,
TCC_OPTION_norunsrc,
TCC_OPTION_v,
TCC_OPTION_w,
TCC_OPTION_pipe,
@ -1680,6 +1699,9 @@ static const TCCOption tcc_options[] = {
#endif
{ "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "c", TCC_OPTION_c, 0 },
#ifdef TCC_TARGET_ARM
{ "mfloat-abi", TCC_OPTION_float_abi, TCC_OPTION_HAS_ARG },
#endif
{ "static", TCC_OPTION_static, 0 },
{ "shared", TCC_OPTION_shared, 0 },
{ "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
@ -1687,7 +1709,6 @@ static const TCCOption tcc_options[] = {
{ "pedantic", TCC_OPTION_pedantic, 0},
{ "pthread", TCC_OPTION_pthread, 0},
{ "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "norunsrc", TCC_OPTION_norunsrc, 0 },
{ "rdynamic", TCC_OPTION_rdynamic, 0 },
{ "r", TCC_OPTION_r, 0 },
{ "s", TCC_OPTION_s, 0 },
@ -1699,7 +1720,7 @@ static const TCCOption tcc_options[] = {
{ "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
{ "nostdinc", TCC_OPTION_nostdinc, 0 },
{ "nostdlib", TCC_OPTION_nostdlib, 0 },
{ "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
{ "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
{ "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "w", TCC_OPTION_w, 0 },
{ "pipe", TCC_OPTION_pipe, 0},
@ -1726,7 +1747,6 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
const TCCOption *popt;
const char *optarg, *r;
int run = 0;
int norunsrc = 0;
int pthread = 0;
int optind = 0;
@ -1739,8 +1759,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
r = argv[optind++];
if (r[0] != '-' || r[1] == '\0') {
/* add a new file */
if (!run || !norunsrc)
dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));
dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));
if (run) {
optind--;
/* argv[0] will be this file */
@ -1817,6 +1836,18 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
case TCC_OPTION_c:
s->output_type = TCC_OUTPUT_OBJ;
break;
#ifdef TCC_TARGET_ARM
case TCC_OPTION_float_abi:
/* tcc doesn't support soft float yet */
if (!strcmp(optarg, "softfp")) {
s->float_abi = ARM_SOFTFP_FLOAT;
tcc_undefine_symbol(s, "__ARM_PCS_VFP");
} else if (!strcmp(optarg, "hard"))
s->float_abi = ARM_HARD_FLOAT;
else
tcc_error("unsupported float abi '%s'", optarg);
break;
#endif
case TCC_OPTION_static:
s->static_link = 1;
break;
@ -1854,9 +1885,6 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
tcc_set_options(s, optarg);
run = 1;
break;
case TCC_OPTION_norunsrc:
norunsrc = 1;
break;
case TCC_OPTION_v:
do ++s->verbose; while (*optarg++ == 'v');
break;
@ -1865,7 +1893,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
goto unsupported_option;
break;
case TCC_OPTION_W:
if (tcc_set_warning(s, optarg, 1) < 0 &&
if (tcc_set_warning(s, optarg, 1) < 0 &&
s->warn_unsupported)
goto unsupported_option;
break;
@ -1952,7 +1980,7 @@ PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
tt = 0.001;
if (total_bytes < 1)
total_bytes = 1;
printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
tok_ident - TOK_IDENT, total_lines, total_bytes,
tt, (int)(total_lines / tt),
total_bytes / tt / 1000000.0);
@ -1961,7 +1989,7 @@ PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
PUB_FUNC void tcc_set_environment(TCCState *s)
{
char * path;
path = getenv("C_INCLUDE_PATH");
if(path != NULL) {
tcc_add_include_path(s, path);

View File

@ -176,6 +176,9 @@ In a script, it gives the following header:
#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11
@end example
@item -mfloat-abi (ARM only)
Select the float ABI. Possible values: @code{softfp} and @code{hard}
@item -dumpversion
Print only the compiler version and nothing else.
@ -217,7 +220,7 @@ Undefine preprocessor symbol @samp{sym}.
Compilation flags:
Note: each of the following warning options has a negative form beginning with
Note: each of the following options has a negative form beginning with
@option{-fno-}.
@table @option
@ -338,7 +341,7 @@ Generate additional support code to check
memory allocations and array/pointer bounds. @option{-g} is implied. Note
that the generated code is slower and bigger in this case.
Note: @option{-b} is only available on i386 for the moment.
Note: @option{-b} is only available on i386 when using libtcc for the moment.
@item -bt N
Display N callers in stack traces. This is useful with @option{-g} or
@ -967,7 +970,7 @@ be the best solution.
#define VT_BITFIELD 0x0040 /* bitfield modifier */
#define VT_CONSTANT 0x0800 /* const modifier */
#define VT_VOLATILE 0x1000 /* volatile modifier */
#define VT_SIGNED 0x2000 /* signed type */
#define VT_DEFSIGN 0x2000 /* signed type */
#define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */
@end example
@ -1077,7 +1080,7 @@ are used when bound checking is activated
@item stab_section
@itemx stabstr_section
are used when debugging is actived to store debug information
are used when debugging is active to store debug information
@item symtab_section
@itemx strtab_section

5
tcc.c
View File

@ -69,7 +69,6 @@ static void help(void)
" -Bdir use 'dir' as tcc internal library and include path\n"
" -MD generate target dependencies for make\n"
" -MF depfile put generated dependencies here\n"
" -norunsrc Do not compile the file which is the first argument after -run.\n"
);
}
@ -79,7 +78,7 @@ static void help(void)
#include <process.h>
static int execvp_win32(const char *prog, char **argv)
{
int ret = spawnvp(P_NOWAIT, prog, (char const*const*)argv);
int ret = spawnvp(P_NOWAIT, prog, (const char *const*)argv);
if (-1 == ret)
return ret;
cwait(&ret, ret, WAIT_CHILD);
@ -224,7 +223,7 @@ static void display_info(TCCState *s, int what)
print_paths("crt", s->crt_paths, s->nb_crt_paths);
print_paths("libraries", s->library_paths, s->nb_library_paths);
print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths);
printf("elfinterp:\n %s\n", CONFIG_TCC_ELFINTERP);
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
break;
}
}

252
tcc.h
View File

@ -55,18 +55,27 @@
# ifndef CONFIG_TCC_STATIC
# include <dlfcn.h>
# endif
#else
/* XXX: need to define this to use them in non ISOC99 context */
extern float strtof (const char *__nptr, char **__endptr);
extern long double strtold (const char *__nptr, char **__endptr);
#else /* on _WIN32: */
# include <windows.h>
# include <sys/timeb.h>
# include <io.h> /* open, close etc. */
# include <direct.h> /* getcwd */
# ifdef __GNUC__
# include <stdint.h>
# else
typedef UINT_PTR uintptr_t;
# endif
# define inline __inline
# define inp next_inp
# define snprintf _snprintf
# define vsnprintf _vsnprintf
# ifndef __GNUC__
# define strtold (long double)strtod
# define strtof (float)strtod
# define strtoll _strtoi64
# define strtoull _strtoui64
# endif
# ifdef LIBTCC_AS_DLL
# define LIBTCCAPI __declspec(dllexport)
# define PUB_FUNC LIBTCCAPI
@ -79,6 +88,30 @@
# define O_BINARY 0
#endif
#ifdef __GNUC__
# define NORETURN __attribute__ ((noreturn))
#elif defined _MSC_VER
# define NORETURN __declspec(noreturn)
#else
# define NORETURN
#endif
#ifdef _WIN32
# 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
#else
# define IS_DIRSEP(c) (c == '/')
# define IS_ABSPATH(p) IS_DIRSEP(p[0])
# define PATHCMP strcmp
#endif
#ifdef TCC_TARGET_PE
#define PATHSEP ';'
#else
#define PATHSEP ':'
#endif
#include "elf.h"
#ifdef TCC_TARGET_X86_64
# define ELFCLASSW ELFCLASS64
@ -128,7 +161,8 @@
#endif
#if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
!defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)
!defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64) && \
!defined(CONFIG_USE_LIBGCC)
#define CONFIG_TCC_BCHECK /* enable bound checking code */
#endif
@ -169,9 +203,17 @@
# define CONFIG_LDDIR "lib"
#endif
#ifdef CONFIG_MULTIARCHDIR
# define USE_MUADIR(s) s "/" CONFIG_MULTIARCHDIR
# define ALSO_MUADIR(s) s "/" CONFIG_MULTIARCHDIR ":" s
#else
# define USE_MUADIR(s) s
# define ALSO_MUADIR(s) s
#endif
/* path to find crt1.o, crti.o and crtn.o */
#ifndef CONFIG_TCC_CRTPREFIX
# define CONFIG_TCC_CRTPREFIX CONFIG_SYSROOT "/usr/" CONFIG_LDDIR
# define CONFIG_TCC_CRTPREFIX USE_MUADIR(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR)
#endif
/* Below: {B} is substituted by CONFIG_TCCDIR (rsp. -B option) */
@ -180,17 +222,10 @@
#ifndef CONFIG_TCC_SYSINCLUDEPATHS
# ifdef TCC_TARGET_PE
# define CONFIG_TCC_SYSINCLUDEPATHS "{B}/include;{B}/include/winapi"
# elif defined CONFIG_MULTIARCHDIR
# define CONFIG_TCC_SYSINCLUDEPATHS \
CONFIG_SYSROOT "/usr/local/include" \
":" CONFIG_SYSROOT "/usr/local/include/" CONFIG_MULTIARCHDIR \
":" CONFIG_SYSROOT "/usr/include" \
":" CONFIG_SYSROOT "/usr/include/" CONFIG_MULTIARCHDIR \
":" "{B}/include"
# else
# define CONFIG_TCC_SYSINCLUDEPATHS \
CONFIG_SYSROOT "/usr/local/include" \
":" CONFIG_SYSROOT "/usr/include" \
ALSO_MUADIR(CONFIG_SYSROOT "/usr/local/include") \
":" ALSO_MUADIR(CONFIG_SYSROOT "/usr/include") \
":" "{B}/include"
# endif
#endif
@ -198,12 +233,12 @@
/* library search paths */
#ifndef CONFIG_TCC_LIBPATHS
# ifdef TCC_TARGET_PE
# define CONFIG_TCC_LIBPATHS "{B}/lib;{B}"
# define CONFIG_TCC_LIBPATHS "{B}/lib"
# else
# define CONFIG_TCC_LIBPATHS \
CONFIG_SYSROOT "/usr/" CONFIG_LDDIR \
":" CONFIG_SYSROOT "/" CONFIG_LDDIR \
":" CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR
ALSO_MUADIR(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \
":" ALSO_MUADIR(CONFIG_SYSROOT "/" CONFIG_LDDIR) \
":" ALSO_MUADIR(CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR)
# endif
#endif
@ -217,25 +252,30 @@
# else
# define CONFIG_TCC_ELFINTERP "/lib/ld.so.1"
# endif
# elif defined __DragonFly__
# define CONFIG_TCC_ELFINTERP "/usr/libexec/ld-elf.so.2"
# elif defined __GNU__
# define CONFIG_TCC_ELFINTERP "/lib/ld.so"
# elif defined TCC_ARM_HARDFLOAT
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-armhf.so.3"
# elif defined TCC_ARM_EABI
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.3"
# elif defined(TCC_TARGET_X86_64)
# define CONFIG_TCC_ELFINTERP "/lib64/ld-linux-x86-64.so.2"
# elif defined(TCC_UCLIBC)
# define CONFIG_TCC_ELFINTERP "/lib/ld-uClibc.so.0"
# elif defined(TCC_TARGET_PE)
# define CONFIG_TCC_ELFINTERP "-"
# else
# elif !defined(TCC_ARM_EABI)
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2"
# endif
#endif
/* var elf_interp dans *-gen.c */
#ifdef CONFIG_TCC_ELFINTERP
# define DEFAULT_ELFINTERP(s) CONFIG_TCC_ELFINTERP
#else
# define DEFAULT_ELFINTERP(s) default_elfinterp(s)
#endif
/* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */
#define TCC_LIBGCC CONFIG_SYSROOT "/" CONFIG_LDDIR "/libgcc_s.so.1"
#define TCC_LIBGCC USE_MUADIR(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1"
/* -------------------------------------------- */
/* include the target specific definitions */
@ -310,7 +350,7 @@ typedef union CValue {
long long ll;
unsigned long long ull;
struct CString *cstr;
void *ptr;
addr_t ptr_offset;
int tab[LDOUBLE_SIZE/4];
} CValue;
@ -324,11 +364,36 @@ typedef struct SValue {
struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
} SValue;
struct Attribute {
unsigned
func_call : 3, /* calling convention (0..5), see below */
aligned : 5, /* alignement (0..16) */
packed : 1,
func_export : 1,
func_import : 1,
func_args : 5,
func_proto : 1,
mode : 4,
weak : 1,
visibility : 2,
fill : 8; // 8 bits left to fit well in union below
};
/* GNUC attribute definition */
typedef struct AttributeDef {
struct Attribute a;
struct Section *section;
int alias_target; /* token */
} AttributeDef;
/* symbol management */
typedef struct Sym {
int v; /* symbol token */
char *asm_label; /* associated asm label */
long r; /* associated register */
union {
long r; /* associated register */
struct Attribute a;
};
union {
long c; /* associated number */
int *d; /* define token stream */
@ -379,32 +444,6 @@ typedef struct DLLReference {
char name[1];
} DLLReference;
/* GNUC attribute definition */
typedef struct AttributeDef {
unsigned
func_call : 3, /* calling convention (0..5), see below */
aligned : 5, /* alignement (0..16) */
packed : 1,
func_export : 1,
func_import : 1,
func_args : 5,
mode : 4,
weak : 1,
fill : 11;
struct Section *section;
int alias_target; /* token */
} AttributeDef;
/* gr: wrappers for casting sym->r for other purposes */
#define FUNC_CALL(r) (((AttributeDef*)&(r))->func_call)
#define FUNC_EXPORT(r) (((AttributeDef*)&(r))->func_export)
#define FUNC_IMPORT(r) (((AttributeDef*)&(r))->func_import)
#define FUNC_ARGS(r) (((AttributeDef*)&(r))->func_args)
#define FUNC_ALIGN(r) (((AttributeDef*)&(r))->aligned)
#define FUNC_PACKED(r) (((AttributeDef*)&(r))->packed)
#define ATTR_MODE(r) (((AttributeDef*)&(r))->mode)
#define INT_ATTR(ad) (*(int*)(ad))
/* -------------------------------------------------- */
#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
@ -519,6 +558,7 @@ typedef struct ASMOperand {
struct sym_attr {
unsigned long got_offset;
unsigned long plt_offset;
#ifdef TCC_TARGET_ARM
unsigned char plt_thumb_stub:1;
#endif
@ -561,6 +601,9 @@ struct TCCState {
/* compile with built-in memory and bounds checker */
int do_bounds_check;
#endif
#ifdef TCC_TARGET_ARM
enum float_abi float_abi; /* float ABI of the generated code*/
#endif
addr_t text_addr; /* address of text section */
int has_text_addr;
@ -665,18 +708,13 @@ struct TCCState {
#endif
#ifdef TCC_IS_NATIVE
const char *runtime_main;
/* for tcc_relocate */
void *runtime_mem;
# ifdef HAVE_SELINUX
void *write_mem;
unsigned long mem_size;
# endif
# if !defined TCC_TARGET_PE && (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM)
/* write PLT and GOT here */
char *runtime_plt_and_got;
unsigned runtime_plt_and_got_offset;
# define TCC_HAS_RUNTIME_PLTGOT
# endif
#endif
/* used by main and tcc_parse_args only */
@ -738,7 +776,7 @@ struct TCCState {
#define VT_BITFIELD 0x0040 /* bitfield modifier */
#define VT_CONSTANT 0x0800 /* const modifier */
#define VT_VOLATILE 0x1000 /* volatile modifier */
#define VT_SIGNED 0x2000 /* signed type */
#define VT_DEFSIGN 0x2000 /* signed type */
#define VT_VLA 0x00020000 /* VLA type (also has VT_PTR and VT_ARRAY) */
/* storage */
@ -749,11 +787,19 @@ struct TCCState {
#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */
#define VT_EXPORT 0x00008000 /* win32: data exported from dll */
#define VT_WEAK 0x00010000 /* weak symbol */
#define VT_TLS 0x00040000 /* thread-local storage */
#define VT_VIS_SHIFT 19 /* shift for symbol visibility, overlapping
bitfield values, because bitfields never
have linkage and hence never have
visibility. */
#define VT_VIS_SIZE 2 /* We have four visibilities. */
#define VT_VIS_MASK (((1 << VT_VIS_SIZE)-1) << VT_VIS_SHIFT)
#define VT_STRUCT_SHIFT 19 /* shift for bitfield shift values (max: 32 - 2*6) */
#define VT_STRUCT_SHIFT 18 /* shift for bitfield shift values (max: 32 - 2*6) */
/* type mask (except storage) */
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK)
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK | VT_VIS_MASK)
#define VT_TYPE (~(VT_STORAGE))
/* token values */
@ -774,35 +820,39 @@ struct TCCState {
#define TOK_LAND 0xa0
#define TOK_LOR 0xa1
#define TOK_DEC 0xa2
#define TOK_MID 0xa3 /* inc/dec, to void constant */
#define TOK_INC 0xa4
#define TOK_UDIV 0xb0 /* unsigned division */
#define TOK_UMOD 0xb1 /* unsigned modulo */
#define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
#define TOK_CINT 0xb3 /* number in tokc */
#define TOK_CCHAR 0xb4 /* char constant in tokc */
#define TOK_STR 0xb5 /* pointer to string in tokc */
#define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
#define TOK_LCHAR 0xb7
#define TOK_LSTR 0xb8
#define TOK_CFLOAT 0xb9 /* float constant */
#define TOK_LINENUM 0xba /* line number info */
#define TOK_CDOUBLE 0xc0 /* double constant */
#define TOK_CLDOUBLE 0xc1 /* long double constant */
/* tokens that carry values (in additional token string space / tokc) --> */
#define TOK_CCHAR 0xb3 /* char constant in tokc */
#define TOK_LCHAR 0xb4
#define TOK_CINT 0xb5 /* number in tokc */
#define TOK_CUINT 0xb6 /* unsigned int constant */
#define TOK_CLLONG 0xb7 /* long long constant */
#define TOK_CULLONG 0xb8 /* unsigned long long constant */
#define TOK_STR 0xb9 /* pointer to string in tokc */
#define TOK_LSTR 0xba
#define TOK_CFLOAT 0xbb /* float constant */
#define TOK_CDOUBLE 0xbc /* double constant */
#define TOK_CLDOUBLE 0xbd /* long double constant */
#define TOK_PPNUM 0xbe /* preprocessor number */
#define TOK_LINENUM 0xbf /* line number info */
/* <-- */
#define TOK_TWOSHARPS 0xc0 /* ## preprocessing token */
#define TOK_PLCHLDR 0xc1 /* placeholder token as defined in C99 */
#define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
#define TOK_ADDC1 0xc3 /* add with carry generation */
#define TOK_ADDC2 0xc4 /* add with carry use */
#define TOK_SUBC1 0xc5 /* add with carry generation */
#define TOK_SUBC2 0xc6 /* add with carry use */
#define TOK_CUINT 0xc8 /* unsigned int constant */
#define TOK_CLLONG 0xc9 /* long long constant */
#define TOK_CULLONG 0xca /* unsigned long long constant */
#define TOK_ARROW 0xcb
#define TOK_DOTS 0xcc /* three dots */
#define TOK_SHR 0xcd /* unsigned shift right */
#define TOK_PPNUM 0xce /* preprocessor number */
#define TOK_NOSUBST 0xcf /* means following token has already been pp'd */
#define TOK_SHL 0x01 /* shift left */
@ -926,37 +976,6 @@ enum tcc_token {
#define TOK_UIDENT TOK_DEFINE
#ifdef _WIN32
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#ifndef __GNUC__
# define strtold (long double)strtod
# define strtof (float)strtod
# define strtoll _strtoi64
# define strtoull _strtoui64
#endif
#else
/* XXX: need to define this to use them in non ISOC99 context */
extern float strtof (const char *__nptr, char **__endptr);
extern long double strtold (const char *__nptr, char **__endptr);
#endif
#ifdef _WIN32
#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
#else
#define IS_DIRSEP(c) (c == '/')
#define IS_ABSPATH(p) IS_DIRSEP(p[0])
#define PATHCMP strcmp
#endif
#ifdef TCC_TARGET_PE
#define PATHSEP ';'
#else
#define PATHSEP ':'
#endif
/* space exlcuding newline */
static inline int is_space(int ch)
{
@ -1033,7 +1052,7 @@ PUB_FUNC char *tcc_strdup(const char *str);
#define strdup(s) use_tcc_strdup(s)
PUB_FUNC void tcc_memstats(void);
PUB_FUNC void tcc_error_noabort(const char *fmt, ...);
PUB_FUNC void tcc_error(const char *fmt, ...);
PUB_FUNC NORETURN void tcc_error(const char *fmt, ...);
PUB_FUNC void tcc_warning(const char *fmt, ...);
/* other utilities */
@ -1131,7 +1150,7 @@ ST_FUNC void preprocess_init(TCCState *s1);
ST_FUNC void preprocess_new(void);
ST_FUNC int tcc_preprocess(TCCState *s1);
ST_FUNC void skip(int c);
ST_FUNC void expect(const char *msg);
ST_FUNC NORETURN void expect(const char *msg);
/* ------------ tccgen.c ------------ */
@ -1169,6 +1188,7 @@ ST_DATA int const_wanted; /* true if constant wanted */
ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */
ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
ST_DATA CType func_vt; /* current function return type (used by return instruction) */
ST_DATA int func_var; /* true if current function is variadic */
ST_DATA int func_vc;
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
ST_DATA char *funcname;
@ -1250,6 +1270,7 @@ ST_FUNC void put_stabd(int type, int other, int desc);
ST_FUNC void relocate_common_syms(void);
ST_FUNC void relocate_syms(TCCState *s1, int do_resolve);
ST_FUNC void relocate_section(TCCState *s1, Section *s);
ST_FUNC void relocate_plt(TCCState *s1);
ST_FUNC void tcc_add_linker_symbols(TCCState *s1);
ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
@ -1260,7 +1281,7 @@ ST_FUNC void build_got_entries(TCCState *s1);
ST_FUNC void tcc_add_runtime(TCCState *s1);
ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err);
#ifdef TCC_IS_NATIVE
#if defined TCC_IS_NATIVE || defined TCC_TARGET_PE
ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name);
#endif
@ -1281,7 +1302,7 @@ ST_FUNC void gsym_addr(int t, int a);
ST_FUNC void gsym(int t);
ST_FUNC void load(int r, SValue *sv);
ST_FUNC void store(int r, SValue *v);
ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *align);
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align);
ST_FUNC void gfunc_call(int nb_args);
ST_FUNC void gfunc_prolog(CType *func_type);
ST_FUNC void gfunc_epilog(void);
@ -1326,7 +1347,10 @@ ST_FUNC void gen_opl(int op);
/* ------------ arm-gen.c ------------ */
#ifdef TCC_TARGET_ARM
ST_FUNC void arm_init_types(void);
#ifdef TCC_ARM_EABI
ST_FUNC char *default_elfinterp(struct TCCState *s);
#endif
ST_FUNC void arm_init(struct TCCState *s);
ST_FUNC uint32_t encbranch(int pos, int addr, int fail);
ST_FUNC void gen_cvt_itof1(int t);
#endif
@ -1368,6 +1392,10 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
#ifdef TCC_TARGET_X86_64
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
#endif
/* symbol properties stored in Elf32_Sym->st_other */
# define ST_PE_EXPORT 0x10
# define ST_PE_IMPORT 0x20
# define ST_PE_STDCALL 0x40
#endif
/* ------------ tccrun.c ----------------- */

View File

@ -232,7 +232,7 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
} else {
goto cannot_relocate;
}
pe->sym = NULL; /* same symbols can be substracted to NULL */
pe->sym = NULL; /* same symbols can be subtracted to NULL */
} else {
cannot_relocate:
tcc_error("invalid operation with label");
@ -483,6 +483,7 @@ static void asm_parse_directive(TCCState *s1)
case TOK_ASM_globl:
case TOK_ASM_global:
case TOK_ASM_weak:
case TOK_ASM_hidden:
tok1 = tok;
do {
Sym *sym;
@ -493,9 +494,12 @@ static void asm_parse_directive(TCCState *s1)
sym = label_push(&s1->asm_labels, tok, 0);
sym->type.t = VT_VOID;
}
sym->type.t &= ~VT_STATIC;
if (tok1 != TOK_ASM_hidden)
sym->type.t &= ~VT_STATIC;
if (tok1 == TOK_ASM_weak)
sym->type.t |= VT_WEAK;
else if (tok1 == TOK_ASM_hidden)
sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT;
next();
} while (tok == ',');
break;
@ -588,12 +592,12 @@ static void asm_parse_directive(TCCState *s1)
tcc_error("label not found: %s", get_tok_str(tok, NULL));
}
next();
skip(',');
/* XXX .size name,label2-label1 */
if (s1->warn_unsupported)
tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL));
next();
skip(',');
while (tok != '\n' && tok != CH_EOF) {
next();
}
@ -622,7 +626,7 @@ static void asm_parse_directive(TCCState *s1)
}
if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
sym->type.t = VT_FUNC;
sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC;
}
else if (s1->warn_unsupported)
tcc_warning("change type of '%s' from 0x%x to '%s' ignored",

2102
tccelf.c

File diff suppressed because it is too large Load Diff

514
tccgen.c

File diff suppressed because it is too large Load Diff

112
tccpe.c
View File

@ -363,7 +363,7 @@ struct pe_info {
static const char *pe_export_name(TCCState *s1, ElfW(Sym) *sym)
{
const char *name = symtab_section->link->data + sym->st_name;
if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & 2))
if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL))
return name + 1;
return name;
}
@ -378,7 +378,7 @@ static int pe_find_import(TCCState * s1, ElfW(Sym) *sym)
s = pe_export_name(s1, sym);
if (n) {
/* second try: */
if (sym->st_other & 2) {
if (sym->st_other & ST_PE_STDCALL) {
/* try w/0 stdcall deco (windows API convention) */
p = strrchr(s, '@');
if (!p || s[0] != '_')
@ -663,7 +663,7 @@ static int pe_write(struct pe_info *pe)
}
}
pstrcpy((char*)psh->Name, sizeof psh->Name, sh_name);
strncpy((char*)psh->Name, sh_name, sizeof psh->Name);
psh->Characteristics = pe_sec_flags[si->cls];
psh->VirtualAddress = addr;
@ -819,27 +819,39 @@ static void pe_build_imports(struct pe_info *pe)
ElfW(Sym) *imp_sym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
ElfW(Sym) *org_sym = (ElfW(Sym) *)symtab_section->data + iat_index;
const char *name = pe->s1->dynsymtab_section->link->data + imp_sym->st_name;
int ordinal;
org_sym->st_value = thk_ptr;
org_sym->st_shndx = pe->thunk->sh_num;
v = pe->thunk->data_offset + rva_base;
section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */
put_elf_str(pe->thunk, name);
if (dllref)
v = 0, ordinal = imp_sym->st_value; /* ordinal from pe_load_def */
else
ordinal = 0, v = imp_sym->st_value; /* address from tcc_add_symbol() */
#ifdef TCC_IS_NATIVE
if (pe->type == PE_RUN) {
v = imp_sym->st_value;
if (dllref) {
if ( !dllref->handle )
dllref->handle = LoadLibrary(dllref->name);
v = (ADDR3264)GetProcAddress(dllref->handle, name);
v = (ADDR3264)GetProcAddress(dllref->handle, ordinal?(LPCSTR)NULL+ordinal:name);
}
if (!v)
tcc_error_noabort("undefined symbol '%s'", name);
}
tcc_error_noabort("can't build symbol '%s'", name);
} else
#endif
if (ordinal) {
v = ordinal | (ADDR3264)1 << (sizeof(ADDR3264)*8 - 1);
} else {
v = pe->thunk->data_offset + rva_base;
section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */
put_elf_str(pe->thunk, name);
}
} else {
v = 0; /* last entry is zero */
}
*(ADDR3264*)(pe->thunk->data+thk_ptr) =
*(ADDR3264*)(pe->thunk->data+ent_ptr) = v;
thk_ptr += sizeof (ADDR3264);
@ -887,7 +899,7 @@ static void pe_build_exports(struct pe_info *pe)
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
sym = (ElfW(Sym)*)symtab_section->data + sym_index;
name = pe_export_name(pe->s1, sym);
if ((sym->st_other & 1)
if ((sym->st_other & ST_PE_EXPORT)
/* export only symbols from actually written sections */
&& pe->s1->sections[sym->st_shndx]->sh_addr) {
p = tcc_malloc(sizeof *p);
@ -896,9 +908,9 @@ static void pe_build_exports(struct pe_info *pe)
dynarray_add((void***)&sorted, &sym_count, p);
}
#if 0
if (sym->st_other & 1)
if (sym->st_other & ST_PE_EXPORT)
printf("export: %s\n", name);
if (sym->st_other & 2)
if (sym->st_other & ST_PE_STDCALL)
printf("stdcall: %s\n", name);
#endif
}
@ -1270,7 +1282,7 @@ static int pe_check_symbols(struct pe_info *pe)
/* patch the original symbol */
sym->st_value = offset;
sym->st_shndx = text_section->sh_num;
sym->st_other &= ~1; /* do not export */
sym->st_other &= ~ST_PE_EXPORT; /* do not export */
continue;
}
@ -1289,7 +1301,7 @@ static int pe_check_symbols(struct pe_info *pe)
} else if (pe->s1->rdynamic
&& ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
/* if -rdynamic option, then export all non local symbols */
sym->st_other |= 1;
sym->st_other |= ST_PE_EXPORT;
}
}
return ret;
@ -1451,7 +1463,7 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2)
if (!sym->c)
put_extern_sym(sym, NULL, 0, 0);
esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
if (!(esym->st_other & 4))
if (!(esym->st_other & ST_PE_IMPORT))
return sv;
// printf("import %04x %04x %04x %s\n", sv->type.t, sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL));
@ -1571,30 +1583,20 @@ static char *trimback(char *a, char *e)
return a;
}
static char *get_line(char *line, int size, int fd)
{
int n;
for (n = 0; n < size - 1; )
if (read(fd, line + n, 1) < 1 || line[n++] == '\n')
break;
if (0 == n)
return NULL;
trimback(line, line + n);
return trimfront(line);
}
/* ------------------------------------------------------------- */
static int pe_load_def(TCCState *s1, int fd)
{
int state = 0, ret = -1, dllindex = 0;
char line[400], dllname[80], *p;
int state = 0, ret = -1, dllindex = 0, ord;
char line[400], dllname[80], *p, *x;
FILE *fp;
for (;;) {
p = get_line(line, sizeof line, fd);
if (NULL == p)
break;
fp = fdopen(dup(fd), "rb");
while (fgets(line, sizeof line, fp))
{
p = trimfront(trimback(line, strchr(line, 0)));
if (0 == *p || ';' == *p)
continue;
switch (state) {
case 0:
if (0 != strnicmp(p, "LIBRARY", 7))
@ -1612,14 +1614,27 @@ static int pe_load_def(TCCState *s1, int fd)
case 2:
dllindex = add_dllref(s1, dllname);
++state;
/* fall through */
default:
pe_putimport(s1, dllindex, p, 0);
/* get ordinal and will store in sym->st_value */
ord = 0;
x = strchr(p, ' ');
if (x) {
*x = 0, x = strrchr(x + 1, '@');
if (x) {
char *d;
ord = (int)strtol(x + 1, &d, 10);
if (*d)
ord = 0;
}
}
pe_putimport(s1, dllindex, p, ord);
continue;
}
}
ret = 0;
quit:
fclose(fp);
return ret;
}
@ -1726,7 +1741,6 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
{
const char *start_symbol;
ADDR3264 addr = 0;
int pe_type = 0;
if (find_elf_sym(symtab_section, PE_STDSYM("WinMain","@16")))
@ -1747,14 +1761,11 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
: PE_GUI == pe_type ? "__winstart" : "__start"
;
if (!s1->leading_underscore || strchr(start_symbol, '@')) {
if (!s1->leading_underscore || strchr(start_symbol, '@'))
++start_symbol;
if (start_symbol[0] != '_')
start_symbol = NULL;
}
/* grab the startup code from libtcc1 */
if (start_symbol)
if (TCC_OUTPUT_MEMORY != s1->output_type || PE_GUI == pe_type)
add_elf_sym(symtab_section,
0, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
@ -1776,21 +1787,16 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
}
}
if (TCC_OUTPUT_MEMORY == s1->output_type)
if (TCC_OUTPUT_MEMORY == s1->output_type) {
pe_type = PE_RUN;
if (start_symbol) {
addr = get_elf_sym_addr(s1, start_symbol, 1);
if (PE_RUN == pe_type && addr)
/* for -run GUI's, put '_runwinmain' instead of 'main' */
add_elf_sym(symtab_section,
addr, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
text_section->sh_num, "main");
#ifdef TCC_IS_NATIVE
s1->runtime_main = start_symbol;
#endif
} else {
pe->start_addr = (DWORD)(uintptr_t)tcc_get_symbol_err(s1, start_symbol);
}
pe->type = pe_type;
pe->start_addr = addr;
}
ST_FUNC int pe_output_file(TCCState * s1, const char *filename)

472
tccpp.c
View File

@ -58,7 +58,6 @@ static const int *unget_saved_macro_ptr;
static int unget_saved_buffer[TOK_MAX_SIZE + 1];
static int unget_buffer_enabled;
static TokenSym *hash_ident[TOK_HASH_SIZE];
static char token_buf[STRING_MAX_SIZE + 1];
/* true if isid(c) || isnum(c) */
static unsigned char isidnum_table[256-CH_EOF];
@ -70,8 +69,33 @@ static const char tcc_keywords[] =
/* WARNING: the content of this string encodes token numbers */
static const unsigned char tok_two_chars[] =
/* outdated -- gr
"<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253"
"-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
*/{
'<','=', TOK_LE,
'>','=', TOK_GE,
'!','=', TOK_NE,
'&','&', TOK_LAND,
'|','|', TOK_LOR,
'+','+', TOK_INC,
'-','-', TOK_DEC,
'=','=', TOK_EQ,
'<','<', TOK_SHL,
'>','>', TOK_SAR,
'+','=', TOK_A_ADD,
'-','=', TOK_A_SUB,
'*','=', TOK_A_MUL,
'/','=', TOK_A_DIV,
'%','=', TOK_A_MOD,
'&','=', TOK_A_AND,
'^','=', TOK_A_XOR,
'|','=', TOK_A_OR,
'-','>', TOK_ARROW,
'.','.', 0xa8, // C++ token ?
'#','#', TOK_TWOSHARPS,
0
};
struct macro_level {
struct macro_level *prev;
@ -197,7 +221,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
int i;
if (tok_ident >= SYM_FIRST_ANOM)
tcc_error("memory full");
tcc_error("memory full (symbols)");
/* expand token table if needed */
i = tok_ident - TOK_IDENT;
@ -264,6 +288,10 @@ ST_FUNC char *get_tok_str(int v, CValue *cv)
cstr_buf.size_allocated = sizeof(buf);
p = buf;
/* just an explanation, should never happen:
if (v <= TOK_LINENUM && v >= TOK_CINT && cv == NULL)
tcc_error("internal error: get_tok_str"); */
switch(v) {
case TOK_CINT:
case TOK_CUINT:
@ -276,7 +304,7 @@ ST_FUNC char *get_tok_str(int v, CValue *cv)
#ifdef _WIN32
sprintf(p, "%u", (unsigned)cv->ull);
#else
sprintf(p, "%Lu", cv->ull);
sprintf(p, "%llu", cv->ull);
#endif
break;
case TOK_LCHAR:
@ -311,6 +339,15 @@ ST_FUNC char *get_tok_str(int v, CValue *cv)
cstr_ccat(&cstr_buf, '\"');
cstr_ccat(&cstr_buf, '\0');
break;
case TOK_CFLOAT:
case TOK_CDOUBLE:
case TOK_CLDOUBLE:
case TOK_LINENUM:
return NULL; /* should not happen */
/* above tokens have value, the ones below don't */
case TOK_LT:
v = '<';
goto addv;
@ -1175,9 +1212,9 @@ static void tok_print(int *str)
ST_FUNC void parse_define(void)
{
Sym *s, *first, **ps;
int v, t, varg, is_vaargs, spc;
int v, t, varg, is_vaargs, spc, ptok, macro_list_start;
TokenString str;
v = tok;
if (v < TOK_IDENT)
tcc_error("invalid macro name '%s'", get_tok_str(tok, &tokc));
@ -1216,8 +1253,13 @@ ST_FUNC void parse_define(void)
tok_str_new(&str);
spc = 2;
/* EOF testing necessary for '-D' handling */
ptok = 0;
macro_list_start = 1;
while (tok != TOK_LINEFEED && tok != TOK_EOF) {
/* remove spaces around ## and after '#' */
if (!macro_list_start && spc == 2 && tok == TOK_TWOSHARPS)
tcc_error("'##' invalid at start of macro");
ptok = tok;
/* remove spaces around ## and after '#' */
if (TOK_TWOSHARPS == tok) {
if (1 == spc)
--str.len;
@ -1230,7 +1272,10 @@ ST_FUNC void parse_define(void)
tok_str_add2(&str, tok, &tokc);
skip:
next_nomacro_spc();
macro_list_start = 0;
}
if (ptok == TOK_TWOSHARPS)
tcc_error("'##' invalid at end of macro");
if (spc == 1)
--str.len; /* remove trailing space */
tok_str_add(&str, 0);
@ -1247,7 +1292,7 @@ static inline int hash_cached_include(const char *filename)
unsigned int h;
h = TOK_HASH_INIT;
s = filename;
s = (unsigned char *) filename;
while (*s) {
h = TOK_HASH_FUNC(h, *s);
s++;
@ -1528,7 +1573,7 @@ include_done:
c = (define_find(tok) != 0) ^ c;
do_if:
if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
tcc_error("memory full");
tcc_error("memory full (ifdef)");
*s1->ifdef_stack_ptr++ = c;
goto test_skip;
case TOK_ELSE:
@ -1744,261 +1789,156 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long
cstr_wccat(outstr, '\0');
}
/* we use 64 bit numbers */
#define BN_SIZE 2
/* bn = (bn << shift) | or_val */
static void bn_lshift(unsigned int *bn, int shift, int or_val)
{
int i;
unsigned int v;
for(i=0;i<BN_SIZE;i++) {
v = bn[i];
bn[i] = (v << shift) | or_val;
or_val = v >> (32 - shift);
}
}
static void bn_zero(unsigned int *bn)
{
int i;
for(i=0;i<BN_SIZE;i++) {
bn[i] = 0;
}
}
/* parse number in null terminated string 'p' and return it in the
current token */
static void parse_number(const char *p)
{
int b, t, shift, frac_bits, s, exp_val, ch;
char *q;
unsigned int bn[BN_SIZE];
double d;
int b, t, c;
/* number */
q = token_buf;
ch = *p++;
t = ch;
ch = *p++;
*q++ = t;
c = *p++;
t = *p++;
b = 10;
if (t == '.') {
goto float_frac_parse;
} else if (t == '0') {
if (ch == 'x' || ch == 'X') {
q--;
ch = *p++;
if(c=='.'){
--p;
goto float_frac_parse;
}
if(c == '0'){
if (t == 'x' || t == 'X') {
b = 16;
} else if (tcc_ext && (ch == 'b' || ch == 'B')) {
q--;
ch = *p++;
c = *p++;
} else if (tcc_ext && (t == 'b' || t == 'B')) {
b = 2;
}
}
/* parse all digits. cannot check octal numbers at this stage
because of floating point constants */
while (1) {
if (ch >= 'a' && ch <= 'f')
t = ch - 'a' + 10;
else if (ch >= 'A' && ch <= 'F')
t = ch - 'A' + 10;
else if (isnum(ch))
t = ch - '0';
else
break;
if (t >= b)
break;
if (q >= token_buf + STRING_MAX_SIZE) {
num_too_long:
tcc_error("number too long");
}
*q++ = ch;
ch = *p++;
}
if (ch == '.' ||
((ch == 'e' || ch == 'E') && b == 10) ||
((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
if (b != 10) {
/* NOTE: strtox should support that for hexa numbers, but
non ISOC99 libcs do not support it, so we prefer to do
it by hand */
/* hexadecimal or binary floats */
/* XXX: handle overflows */
*q = '\0';
if (b == 16)
shift = 4;
else
shift = 2;
bn_zero(bn);
q = token_buf;
while (1) {
t = *q++;
if (t == '\0') {
break;
} else if (t >= 'a') {
t = t - 'a' + 10;
} else if (t >= 'A') {
t = t - 'A' + 10;
} else {
t = t - '0';
}
bn_lshift(bn, shift, t);
}
frac_bits = 0;
if (ch == '.') {
ch = *p++;
while (1) {
t = ch;
if (t >= 'a' && t <= 'f') {
t = t - 'a' + 10;
} else if (t >= 'A' && t <= 'F') {
t = t - 'A' + 10;
} else if (t >= '0' && t <= '9') {
t = t - '0';
} else {
break;
}
if (t >= b)
tcc_error("invalid digit");
bn_lshift(bn, shift, t);
frac_bits += shift;
ch = *p++;
}
}
if (ch != 'p' && ch != 'P')
expect("exponent");
ch = *p++;
s = 1;
exp_val = 0;
if (ch == '+') {
ch = *p++;
} else if (ch == '-') {
s = -1;
ch = *p++;
}
if (ch < '0' || ch > '9')
expect("exponent digits");
while (ch >= '0' && ch <= '9') {
exp_val = exp_val * 10 + ch - '0';
ch = *p++;
}
exp_val = exp_val * s;
/* now we can generate the number */
/* XXX: should patch directly float number */
d = (double)bn[1] * 4294967296.0 + (double)bn[0];
d = ldexp(d, exp_val - frac_bits);
t = toup(ch);
if (t == 'F') {
ch = *p++;
tok = TOK_CFLOAT;
/* float : should handle overflow */
tokc.f = (float)d;
} else if (t == 'L') {
ch = *p++;
#ifdef TCC_TARGET_PE
tok = TOK_CDOUBLE;
tokc.d = d;
#else
tok = TOK_CLDOUBLE;
/* XXX: not large enough */
tokc.ld = (long double)d;
#endif
} else {
tok = TOK_CDOUBLE;
tokc.d = d;
}
} else {
/* decimal floats */
if (ch == '.') {
if (q >= token_buf + STRING_MAX_SIZE)
goto num_too_long;
*q++ = ch;
ch = *p++;
float_frac_parse:
while (ch >= '0' && ch <= '9') {
if (q >= token_buf + STRING_MAX_SIZE)
goto num_too_long;
*q++ = ch;
ch = *p++;
}
}
if (ch == 'e' || ch == 'E') {
if (q >= token_buf + STRING_MAX_SIZE)
goto num_too_long;
*q++ = ch;
ch = *p++;
if (ch == '-' || ch == '+') {
if (q >= token_buf + STRING_MAX_SIZE)
goto num_too_long;
*q++ = ch;
ch = *p++;
}
if (ch < '0' || ch > '9')
expect("exponent digits");
while (ch >= '0' && ch <= '9') {
if (q >= token_buf + STRING_MAX_SIZE)
goto num_too_long;
*q++ = ch;
ch = *p++;
}
}
*q = '\0';
t = toup(ch);
errno = 0;
if (t == 'F') {
ch = *p++;
tok = TOK_CFLOAT;
tokc.f = strtof(token_buf, NULL);
} else if (t == 'L') {
ch = *p++;
#ifdef TCC_TARGET_PE
tok = TOK_CDOUBLE;
tokc.d = strtod(token_buf, NULL);
#else
tok = TOK_CLDOUBLE;
tokc.ld = strtold(token_buf, NULL);
#endif
} else {
tok = TOK_CDOUBLE;
tokc.d = strtod(token_buf, NULL);
}
}
} else {
unsigned long long n, n1;
int lcount, ucount;
c = *p++;
}else{
--p;
}
}else
--p;
if(strchr(p , '.') || (b == 10 && (strchr(p,'e') || strchr(p,'E'))) ||
((b == 2 || b == 16)&& (strchr(p,'p') || strchr(p,'P')))){
long double ld, sh, fb;
int exp;
/* NOTE: strtox should support that for hexa numbers, but
non ISOC99 libcs do not support it, so we prefer to do
it by hand */
/* hexadecimal or binary floats */
/* XXX: handle overflows */
float_frac_parse:
fb = 1.0L/b;
sh = b;
ld = 0.0;
/* integer number */
*q = '\0';
q = token_buf;
if (b == 10 && *q == '0') {
while(1){
if (c == '\0')
break;
if (c >= 'a' && c <= 'f')
t = c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
t = c - 'A' + 10;
else if(isnum(c))
t = c - '0';
else
break;
if (t >= b)
tcc_error("invalid digit");
ld = ld * b + t;
c = *p++;
}
if (c == '.'){
c = *p++;
sh = fb;
while (1){
if (c == '\0')
break;
if (c >= 'a' && c <= 'f')
t = c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
t = c - 'A' + 10;
else if (isnum(c))
t =c - '0';
else
break;
if (t >= b){
if(b == 10 && (c == 'e' || c == 'E' || c == 'f' || c == 'F'))
break;
tcc_error("invalid digit");
}
ld += sh*t;
sh*=fb;
c = *p++;
}
}
if ((b == 16 || b == 2) && c != 'p' && c != 'P')
expect("exponent");
if(((c == 'e' || c == 'E') && b == 10) ||
((c == 'p' || c == 'P') && (b == 16 || b == 2))){
c = *p++;
if(c == '+' || c == '-'){
if (c == '-')
sh = fb;
c = *p++;
}else
sh = b;
if (!isnum(c))
expect("exponent digits");
exp = 0;
do{
exp = exp * 10 + c - '0';
c = *p++;
}while(isnum(c));
while (exp != 0){
if (exp & 1)
ld *= sh;
exp >>= 1;
sh *= sh;
}
}
t = toup(c);
if (t == 'F') {
c = *p++;
tok = TOK_CFLOAT;
tokc.f = (float)ld;
} else if (t == 'L') {
c = *p++;
#ifdef TCC_TARGET_PE
tok = TOK_CDOUBLE;
tokc.d = (double)ld;
#else
tok = TOK_CLDOUBLE;
tokc.ld = ld;
#endif
} else {
tok = TOK_CDOUBLE;
tokc.d = (double)ld;
}
} else {
uint64_t n = 0, n1;
int warn = 1;
int lcount, ucount;
if (b == 10 && c == '0') {
b = 8;
q++;
}
n = 0;
while(1) {
t = *q++;
/* no need for checks except for base 10 / 8 errors */
if (t == '\0') {
break;
} else if (t >= 'a') {
t = t - 'a' + 10;
} else if (t >= 'A') {
t = t - 'A' + 10;
} else {
t = t - '0';
if (t >= b)
tcc_error("invalid digit");
}
n1 = n;
n = n * b + t;
/* detect overflow */
/* XXX: this test is not reliable */
if (n < n1)
tcc_error("integer constant overflow");
}
while(1){
if (c == '\0')
break;
if (c >= 'a' && c <= 'f')
t = c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
t = c - 'A' + 10;
else if(isnum(c))
t = c - '0';
else
break;
if (t >= b)
tcc_error("invalid digit");
n1 = n;
n = n * b + t;
if (n < n1 && warn){
tcc_warning("integer constant overflow");
warn = 0;
}
c = *p++;
}
/* XXX: not exactly ANSI compliant */
if ((n & 0xffffffff00000000LL) != 0) {
if ((n >> 63) != 0)
@ -2013,7 +1953,7 @@ static void parse_number(const char *p)
lcount = 0;
ucount = 0;
for(;;) {
t = toup(ch);
t = toup(c);
if (t == 'L') {
if (lcount >= 2)
tcc_error("three 'l's in integer constant");
@ -2028,7 +1968,7 @@ static void parse_number(const char *p)
#if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE
}
#endif
ch = *p++;
c = *p++;
} else if (t == 'U') {
if (ucount >= 1)
tcc_error("two 'u's in integer constant");
@ -2037,7 +1977,7 @@ static void parse_number(const char *p)
tok = TOK_CUINT;
else if (tok == TOK_CLLONG)
tok = TOK_CULLONG;
ch = *p++;
c = *p++;
} else {
break;
}
@ -2047,7 +1987,7 @@ static void parse_number(const char *p)
else
tokc.ull = n;
}
if (ch)
if (c)
tcc_error("invalid number\n");
}
@ -2222,7 +2162,7 @@ maybe_newline:
goto token_found;
pts = &(ts->hash_next);
}
ts = tok_alloc_new(pts, p1, len);
ts = tok_alloc_new(pts, (char *) p1, len);
token_found: ;
} else {
/* slower case */
@ -2519,7 +2459,8 @@ ST_FUNC void next_nomacro(void)
} while (is_space(tok));
}
/* substitute args in macro_str and return allocated string */
/* substitute arguments in replacement lists in macro_str by the values in
args (field d) and return allocated string */
static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
{
int last_tok, t, spc;
@ -2576,7 +2517,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
if (gnu_ext && s->type.t &&
last_tok == TOK_TWOSHARPS &&
str.len >= 2 && str.str[str.len - 2] == ',') {
if (*st == 0) {
if (*st == TOK_PLCHLDR) {
/* suppress ',' '##' */
str.len -= 2;
} else {
@ -2747,6 +2688,8 @@ static int macro_subst_tok(TokenString *tok_str,
tok_str_add2(&str, tok, &tokc);
next_nomacro_spc();
}
if (!str.len)
tok_str_add(&str, TOK_PLCHLDR);
str.len -= spc;
tok_str_add(&str, 0);
sa1 = sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, 0);
@ -2839,9 +2782,11 @@ static inline int *macro_twosharps(const int *macro_str)
TOK_GET(&t, &ptr, &cval);
/* We concatenate the two tokens */
cstr_new(&cstr);
cstr_cat(&cstr, get_tok_str(tok, &tokc));
if (tok != TOK_PLCHLDR)
cstr_cat(&cstr, get_tok_str(tok, &tokc));
n = cstr.size;
cstr_cat(&cstr, get_tok_str(t, &cval));
if (t != TOK_PLCHLDR || tok == TOK_PLCHLDR)
cstr_cat(&cstr, get_tok_str(t, &cval));
cstr_ccat(&cstr, '\0');
tcc_open_bf(tcc_state, ":paste:", cstr.size);
@ -2858,8 +2803,11 @@ static inline int *macro_twosharps(const int *macro_str)
cstr_free(&cstr);
}
}
if (tok != TOK_NOSUBST)
if (tok != TOK_NOSUBST) {
tok_str_add2(&macro_str1, tok, &tokc);
tok = ' ';
start_of_nosubsts = -1;
}
tok_str_add2(&macro_str1, tok, &tokc);
}
tok_str_add(&macro_str1, 0);

View File

@ -97,7 +97,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
return -1;
prog_main = tcc_get_symbol_err(s1, "main");
prog_main = tcc_get_symbol_err(s1, s1->runtime_main);
#ifdef CONFIG_TCC_BACKTRACE
if (s1->do_debug) {
@ -110,13 +110,30 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
if (s1->do_bounds_check) {
void (*bound_init)(void);
void (*bound_exit)(void);
void (*bound_new_region)(void *p, unsigned long size);
int (*bound_delete_region)(void *p);
int i;
/* set error function */
rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
/* XXX: use .init section so that it also work in binary ? */
bound_init = tcc_get_symbol_err(s1, "__bound_init");
bound_exit = tcc_get_symbol_err(s1, "__bound_exit");
bound_new_region = tcc_get_symbol_err(s1, "__bound_new_region");
bound_delete_region = tcc_get_symbol_err(s1, "__bound_delete_region");
bound_init();
/* mark argv area as valid */
bound_new_region(argv, argc*sizeof(argv[0]));
for (i=0; i<argc; ++i)
bound_new_region(argv[i], strlen(argv[i]));
ret = (*prog_main)(argc, argv);
/* unmark argv area */
for (i=0; i<argc; ++i)
bound_delete_region(argv[i]);
bound_delete_region(argv);
bound_exit();
} else
#endif
@ -163,14 +180,6 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
if (s1->nb_errors)
return -1;
#ifdef TCC_HAS_RUNTIME_PLTGOT
s1->runtime_plt_and_got_offset = 0;
s1->runtime_plt_and_got = (char *)(mem + offset);
/* double the size of the buffer for got and plt entries
XXX: calculate exact size for them? */
offset *= 2;
#endif
if (0 == mem)
return offset;
@ -180,6 +189,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
if (s->reloc)
relocate_section(s1, s);
}
relocate_plt(s1);
for(i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
@ -197,11 +207,6 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
set_pages_executable(ptr, length);
}
#ifdef TCC_HAS_RUNTIME_PLTGOT
set_pages_executable(s1->runtime_plt_and_got,
s1->runtime_plt_and_got_offset);
#endif
#ifdef _WIN64
win64_add_function_table(s1);
#endif
@ -217,6 +222,7 @@ static void set_pages_executable(void *ptr, unsigned long length)
unsigned long old_protect;
VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
#else
extern void __clear_cache(char *beginning, char *end);
#ifndef PAGESIZE
# define PAGESIZE 4096
#endif
@ -254,7 +260,7 @@ static addr_t rt_printline(addr_t wanted_pc, const char *msg)
if (stab_section) {
stab_len = stab_section->data_offset;
stab_sym = (Stab_Sym *)stab_section->data;
stab_str = stabstr_section->data;
stab_str = (char *) stabstr_section->data;
}
func_name[0] = '\0';
@ -347,7 +353,7 @@ no_stabs:
if (wanted_pc >= sym->st_value &&
wanted_pc < sym->st_value + sym->st_size) {
pstrcpy(last_func_name, sizeof(last_func_name),
strtab_section->data + sym->st_name);
(char *) strtab_section->data + sym->st_name);
func_addr = sym->st_value;
goto found;
}
@ -480,10 +486,12 @@ static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
if (level == 0) {
#if defined(__APPLE__)
*paddr = uc->uc_mcontext->__ss.__eip;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
*paddr = uc->uc_mcontext.mc_eip;
#elif defined(__dietlibc__)
*paddr = uc->uc_mcontext.eip;
#elif defined(__NetBSD__)
*paddr = uc->uc_mcontext.__gregs[_REG_EIP];
#else
*paddr = uc->uc_mcontext.gregs[REG_EIP];
#endif
@ -491,10 +499,12 @@ static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
} else {
#if defined(__APPLE__)
fp = uc->uc_mcontext->__ss.__ebp;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
fp = uc->uc_mcontext.mc_ebp;
#elif defined(__dietlibc__)
fp = uc->uc_mcontext.ebp;
#elif defined(__NetBSD__)
fp = uc->uc_mcontext.__gregs[_REG_EBP];
#else
fp = uc->uc_mcontext.gregs[REG_EBP];
#endif
@ -522,8 +532,10 @@ static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
/* XXX: only support linux */
#if defined(__APPLE__)
*paddr = uc->uc_mcontext->__ss.__rip;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
*paddr = uc->uc_mcontext.mc_rip;
#elif defined(__NetBSD__)
*paddr = uc->uc_mcontext.__gregs[_REG_RIP];
#else
*paddr = uc->uc_mcontext.gregs[REG_RIP];
#endif
@ -531,8 +543,10 @@ static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
} else {
#if defined(__APPLE__)
fp = uc->uc_mcontext->__ss.__rbp;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
fp = uc->uc_mcontext.mc_rbp;
#elif defined(__NetBSD__)
fp = uc->uc_mcontext.__gregs[_REG_RBP];
#else
fp = uc->uc_mcontext.gregs[REG_RBP];
#endif

121
tcctok.h
View File

@ -121,6 +121,8 @@
DEF(TOK_DLLIMPORT, "dllimport")
DEF(TOK_NORETURN1, "noreturn")
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_constant_p, "__builtin_constant_p")
DEF(TOK_builtin_frame_address, "__builtin_frame_address")
@ -143,23 +145,34 @@
#endif
/* builtin functions or variables */
#ifdef TCC_ARM_EABI
DEF(TOK_memcpy, "__aeabi_memcpy")
DEF(TOK_memcpy4, "__aeabi_memcpy4")
DEF(TOK_memcpy8, "__aeabi_memcpy8")
DEF(TOK_memset, "__aeabi_memset")
DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
#else
#ifndef TCC_ARM_EABI
DEF(TOK_memcpy, "memcpy")
DEF(TOK_memset, "memset")
DEF(TOK___divdi3, "__divdi3")
DEF(TOK___moddi3, "__moddi3")
DEF(TOK___udivdi3, "__udivdi3")
DEF(TOK___umoddi3, "__umoddi3")
DEF(TOK___ashrdi3, "__ashrdi3")
DEF(TOK___lshrdi3, "__lshrdi3")
DEF(TOK___ashldi3, "__ashldi3")
DEF(TOK___floatundisf, "__floatundisf")
DEF(TOK___floatundidf, "__floatundidf")
# ifndef TCC_ARM_VFP
DEF(TOK___floatundixf, "__floatundixf")
DEF(TOK___fixunsxfdi, "__fixunsxfdi")
# endif
DEF(TOK___fixunssfdi, "__fixunssfdi")
DEF(TOK___fixunsdfdi, "__fixunsdfdi")
#endif
#if defined(TCC_TARGET_ARM)
#ifdef TCC_ARM_EABI
#if defined TCC_TARGET_ARM
# ifdef TCC_ARM_EABI
DEF(TOK_memcpy, "__aeabi_memcpy")
DEF(TOK_memcpy4, "__aeabi_memcpy4")
DEF(TOK_memcpy8, "__aeabi_memcpy8")
DEF(TOK_memset, "__aeabi_memset")
DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
DEF(TOK___aeabi_idivmod, "__aeabi_idivmod")
DEF(TOK___aeabi_uidivmod, "__aeabi_uidivmod")
DEF(TOK___divsi3, "__aeabi_idiv")
@ -168,36 +181,6 @@
DEF(TOK___floatdidf, "__aeabi_l2d")
DEF(TOK___fixsfdi, "__aeabi_f2lz")
DEF(TOK___fixdfdi, "__aeabi_d2lz")
#else
DEF(TOK___modsi3, "__modsi3")
DEF(TOK___umodsi3, "__umodsi3")
DEF(TOK___divsi3, "__divsi3")
DEF(TOK___udivsi3, "__udivsi3")
DEF(TOK___floatdisf, "__floatdisf")
DEF(TOK___floatdidf, "__floatdidf")
#ifndef TCC_ARM_VFP
DEF(TOK___floatdixf, "__floatdixf")
DEF(TOK___fixunssfsi, "__fixunssfsi")
DEF(TOK___fixunsdfsi, "__fixunsdfsi")
DEF(TOK___fixunsxfsi, "__fixunsxfsi")
DEF(TOK___fixxfdi, "__fixxfdi")
#endif
DEF(TOK___fixsfdi, "__fixsfdi")
DEF(TOK___fixdfdi, "__fixdfdi")
#endif
#elif defined(TCC_TARGET_C67)
DEF(TOK__divi, "_divi")
DEF(TOK__divu, "_divu")
DEF(TOK__divf, "_divf")
DEF(TOK__divd, "_divd")
DEF(TOK__remi, "_remi")
DEF(TOK__remu, "_remu")
#endif
#ifdef TCC_TARGET_I386
DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
#endif
#ifdef TCC_ARM_EABI
DEF(TOK___ashrdi3, "__aeabi_lasr")
DEF(TOK___lshrdi3, "__aeabi_llsr")
DEF(TOK___ashldi3, "__aeabi_llsl")
@ -205,20 +188,45 @@
DEF(TOK___floatundidf, "__aeabi_ul2d")
DEF(TOK___fixunssfdi, "__aeabi_f2ulz")
DEF(TOK___fixunsdfdi, "__aeabi_d2ulz")
#else
DEF(TOK___ashrdi3, "__ashrdi3")
DEF(TOK___lshrdi3, "__lshrdi3")
DEF(TOK___ashldi3, "__ashldi3")
DEF(TOK___floatundisf, "__floatundisf")
DEF(TOK___floatundidf, "__floatundidf")
#ifndef TCC_ARM_VFP
DEF(TOK___floatundixf, "__floatundixf")
DEF(TOK___fixunsxfdi, "__fixunsxfdi")
# else
DEF(TOK___modsi3, "__modsi3")
DEF(TOK___umodsi3, "__umodsi3")
DEF(TOK___divsi3, "__divsi3")
DEF(TOK___udivsi3, "__udivsi3")
DEF(TOK___floatdisf, "__floatdisf")
DEF(TOK___floatdidf, "__floatdidf")
# ifndef TCC_ARM_VFP
DEF(TOK___floatdixf, "__floatdixf")
DEF(TOK___fixunssfsi, "__fixunssfsi")
DEF(TOK___fixunsdfsi, "__fixunsdfsi")
DEF(TOK___fixunsxfsi, "__fixunsxfsi")
DEF(TOK___fixxfdi, "__fixxfdi")
# endif
DEF(TOK___fixsfdi, "__fixsfdi")
DEF(TOK___fixdfdi, "__fixdfdi")
# endif
#endif
DEF(TOK___fixunssfdi, "__fixunssfdi")
DEF(TOK___fixunsdfdi, "__fixunsdfdi")
#if defined TCC_TARGET_C67
DEF(TOK__divi, "_divi")
DEF(TOK__divu, "_divu")
DEF(TOK__divf, "_divf")
DEF(TOK__divd, "_divd")
DEF(TOK__remi, "_remi")
DEF(TOK__remu, "_remu")
#endif
#ifdef TCC_TARGET_PE
#if defined TCC_TARGET_I386
DEF(TOK___fixsfdi, "__fixsfdi")
DEF(TOK___fixdfdi, "__fixdfdi")
DEF(TOK___fixxfdi, "__fixxfdi")
#endif
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
DEF(TOK_alloca, "alloca")
#endif
#if defined TCC_TARGET_PE
DEF(TOK___chkstk, "__chkstk")
#endif
@ -231,22 +239,20 @@
DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
DEF(TOK___bound_main_arg, "__bound_main_arg")
DEF(TOK___bound_local_new, "__bound_local_new")
DEF(TOK___bound_local_delete, "__bound_local_delete")
#ifdef TCC_TARGET_PE
# ifdef TCC_TARGET_PE
DEF(TOK_malloc, "malloc")
DEF(TOK_free, "free")
DEF(TOK_realloc, "realloc")
DEF(TOK_memalign, "memalign")
DEF(TOK_calloc, "calloc")
#endif
# endif
DEF(TOK_memmove, "memmove")
DEF(TOK_strlen, "strlen")
DEF(TOK_strcpy, "strcpy")
#endif
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
DEF(TOK_alloca, "alloca")
#endif
/* Tiny Assembler */
DEF_ASM(byte)
@ -260,6 +266,7 @@
DEF_ASM(file)
DEF_ASM(globl)
DEF_ASM(global)
DEF_ASM(hidden)
DEF_ASM(ident)
DEF_ASM(size)
DEF_ASM(type)

View File

@ -5,7 +5,7 @@
TOP = ..
include $(TOP)/Makefile
SRCDIR = $(top_srcdir)/tests
VPATH = $(SRCDIR)
VPATH = $(SRCDIR) $(top_srcdir)
# what tests to run
TESTS = \
@ -13,24 +13,30 @@ TESTS = \
hello-run \
libtest \
test3 \
$(BTESTS) \
abitest \
vla_test-run \
moretests
BTESTS = test1b test3b btest
ifdef CONFIG_CROSS
TESTS += hello-cross
endif
# test4 -- problem with -static
# asmtest -- minor differences with gcc
# btest -- works on i386 (including win32)
# test3 -- win32 does not know how to printf long doubles
# bounds-checking is supported only on i386
ifneq ($(ARCH),i386)
TESTS := $(filter-out btest,$(TESTS))
TESTS := $(filter-out $(BTESTS),$(TESTS))
endif
ifdef CONFIG_WIN32
TESTS := $(filter-out test3,$(TESTS))
TESTS := w32-prep $(filter-out $(BTESTS),$(TESTS))
endif
ifeq ($(TARGETOS),Darwin)
TESTS := $(filter-out hello-exe test3 btest,$(TESTS))
TESTS := $(filter-out hello-exe test3 $(BTESTS),$(TESTS))
endif
ifeq ($(ARCH),i386)
else ifneq ($(ARCH),x86-64)
@ -52,6 +58,7 @@ TCCFLAGS = -B$(TOP) -I$(TOP) -I$(top_srcdir) -I$(top_srcdir)/include
ifdef CONFIG_WIN32
TCCFLAGS = -B$(top_srcdir)/win32 -I$(top_srcdir) -I$(top_srcdir)/include -I$(TOP) -L$(TOP)
endif
XTCCFLAGS = -B$(TOP) -B$(top_srcdir)/win32 -I$(TOP) -I$(top_srcdir) -I$(top_srcdir)/include
TCC = $(TOP)/tcc $(TCCFLAGS)
RUN_TCC = $(NATIVE_DEFINES) -DONE_SOURCE -run $(top_srcdir)/tcc.c $(TCCFLAGS)
@ -69,6 +76,15 @@ hello-exe: ../examples/ex1.c
@echo ------------ $@ ------------
$(TCC) $< -o hello$(EXESUF) || ($(TOP)/tcc -vv; exit 1) && ./hello$(EXESUF)
hello-cross: ../examples/ex1.c
@echo ------------ $@ ------------
for XTCC in $(PROGS_CROSS) ; \
do echo -n "Test of $$XTCC... "; \
out=$$($(TOP)/$$XTCC $(XTCCFLAGS) -c $< 2>&1); \
test $$? -ne 0 && { echo "Failed\n$$out\n" ; $(TOP)/$$XTCC -vv; exit 1; } ; \
echo "Success"; \
done
hello-run: ../examples/ex1.c
@echo ------------ $@ ------------
$(TCC) -run $<
@ -84,48 +100,52 @@ moretests:
@echo ------------ $@ ------------
$(MAKE) -C tests2
# test.ref - generate using gcc
# copy only tcclib.h so GCC's stddef and stdarg will be used
w32-prep:
cp ../libtcc1.a ../lib
# test.ref - generate using cc
test.ref: tcctest.c
gcc -o tcctest.gcc $< -I$(top_srcdir) $(CPPFLAGS) -w $(CFLAGS) $(NATIVE_DEFINES) -std=gnu99 -O0 -fno-omit-frame-pointer $(LDFLAGS)
./tcctest.gcc > $@
$(CC) -o tcctest.cc $< -I$(top_srcdir) $(CPPFLAGS) -w $(CFLAGS) $(NATIVE_DEFINES) -std=gnu99 -O0 -fno-omit-frame-pointer $(LDFLAGS)
./tcctest.cc > $@
# auto test
test1: test.ref
test1 test1b: tcctest.c test.ref
@echo ------------ $@ ------------
$(TCC) -run $(SRCDIR)/tcctest.c > test.out1
@if diff -u test.ref test.out1 ; then echo "Auto Test OK"; fi
$(TCC) -run $< > test.out1
@diff -u test.ref test.out1 && echo "Auto Test OK"
# iterated test2 (compile tcc then compile tcctest.c !)
test2: test.ref
test2 test2b: tcctest.c test.ref
@echo ------------ $@ ------------
$(TCC) $(RUN_TCC) $(RUN_TCC) -run $(SRCDIR)/tcctest.c > test.out2
@if diff -u test.ref test.out2 ; then echo "Auto Test2 OK"; fi
$(TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out2
@diff -u test.ref test.out2 && echo "Auto Test2 OK"
# iterated test3 (compile tcc then compile tcc then compile tcctest.c !)
test3: test.ref
test3 test3b: tcctest.c test.ref
@echo ------------ $@ ------------
$(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $(SRCDIR)/tcctest.c > test.out3
@if diff -u test.ref test.out3 ; then echo "Auto Test3 OK"; fi
$(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out3
@diff -u test.ref test.out3 && echo "Auto Test3 OK"
test%b : TCCFLAGS += -b
# binary output test
test4: test.ref
test4: tcctest.c test.ref
@echo ------------ $@ ------------
# object + link output
$(TCC) -c -o tcctest3.o $(SRCDIR)/tcctest.c
$(TCC) -c -o tcctest3.o $<
$(TCC) -o tcctest3 tcctest3.o
./tcctest3 > test3.out
@if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi
# dynamic output
$(TCC) -o tcctest1 $(SRCDIR)/tcctest.c
$(TCC) -o tcctest1 $<
./tcctest1 > test1.out
@if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi
# dynamic output + bound check
$(TCC) -b -o tcctest4 $(SRCDIR)/tcctest.c
$(TCC) -b -o tcctest4 $<
./tcctest4 > test4.out
@if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi
# static output
$(TCC) -static -o tcctest2 $(SRCDIR)/tcctest.c
$(TCC) -static -o tcctest2 $<
./tcctest2 > test2.out
@if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi
@ -137,15 +157,15 @@ btest: boundtest.c
@echo ------------ $@ ------------
@for i in $(BOUNDS_OK); do \
echo ; echo --- boundtest $$i ---; \
if $(TCC) -b -run boundtest.c $$i ; then \
echo succeded as expected; \
if $(TCC) -b -run $< $$i ; then \
echo succeeded as expected; \
else\
echo Failed positive test $$i ; exit 1 ; \
fi ;\
done ;\
for i in $(BOUNDS_FAIL); do \
echo ; echo --- boundtest $$i ---; \
if $(TCC) -b -run boundtest.c $$i ; then \
if $(TCC) -b -run $< $$i ; then \
echo Failed negative test $$i ; exit 1 ;\
else\
echo failed as expected; \
@ -161,12 +181,12 @@ speedtest: ex2 ex3
time ./ex3 35
time $(TCC) -run $(top_srcdir)/examples/ex3.c 35
weaktest: test.ref
$(TCC) -c tcctest.c -o weaktest.tcc.o $(CPPFLAGS) $(CFLAGS)
$(CC) -c tcctest.c -o weaktest.gcc.o -I. $(CPPFLAGS) -w $(CFLAGS)
weaktest: tcctest.c test.ref
$(TCC) -c $< -o weaktest.tcc.o $(CPPFLAGS) $(CFLAGS)
$(CC) -c $< -o weaktest.cc.o -I. $(CPPFLAGS) -w $(CFLAGS)
objdump -t weaktest.tcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.tcc.o.txt
objdump -t weaktest.gcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.gcc.o.txt
diff weaktest.gcc.o.txt weaktest.tcc.o.txt && echo "Weak Auto Test OK"
objdump -t weaktest.cc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.cc.o.txt
diff weaktest.cc.o.txt weaktest.tcc.o.txt && echo "Weak Auto Test OK"
ex%: $(top_srcdir)/examples/ex%.c
$(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
@ -187,8 +207,8 @@ asmtest: asmtest.ref
abitest-cc$(EXESUF): abitest.c $(top_builddir)/$(LIBTCC)
$(CC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(NATIVE_DEFINES) $(LIBS) $(LINK_LIBTCC) $(LDFLAGS) -I$(top_srcdir)
abitest-tcc$(EXESUF): abitest.c $(top_builddir)/$(LIBTCC)
$(TCC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(NATIVE_DEFINES) $(LIBS) $(LINK_LIBTCC) $(LDFLAGS) -I$(top_srcdir)
abitest-tcc$(EXESUF): abitest.c libtcc.c
$(TCC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(NATIVE_DEFINES) -DONE_SOURCE $(LIBS) $(LDFLAGS) -I$(top_srcdir)
abitest: abitest-cc$(EXESUF) abitest-tcc$(EXESUF)
@echo ------------ $@ ------------
@ -219,8 +239,7 @@ cache: tcc_g
# clean
clean:
$(MAKE) -C tests2 $@
rm -vf *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.gcc *.exe \
hello libtcc_test tcctest[1234] ex? tcc_g tcclib.h
Makefile: $(SRCDIR)/Makefile
cp $< $@
rm -vf *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.cc \
*-cc *-tcc *.exe \
hello libtcc_test vla_test tcctest[1234] ex? tcc_g tcclib.h \
../lib/libtcc1.a

View File

@ -88,7 +88,7 @@ static int ret_2float_test_callback(void *ptr) {
ret_2float_test_type a = {10, 35};
ret_2float_test_type r;
r = f(a);
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
return ((r.x == a.x*5) && (r.y == a.y*3) && (f(a).x == a.x*5) && (f(a).y == a.y*3)) ? 0 : -1;
}
static int ret_2float_test(void) {
@ -116,7 +116,7 @@ static int ret_2double_test_callback(void *ptr) {
ret_2double_test_type a = {10, 35};
ret_2double_test_type r;
r = f(a);
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
return ((r.x == a.x*5) && (r.y == a.y*3) && (f(a).x == a.x*5) && (f(a).y == a.y*3)) ? 0 : -1;
}
static int ret_2double_test(void) {
@ -130,6 +130,50 @@ static int ret_2double_test(void) {
return run_callback(src, ret_2double_test_callback);
}
typedef struct ret_longdouble_test_type_s2 {LONG_DOUBLE x;} ret_longdouble_test_type;
typedef ret_longdouble_test_type (*ret_longdouble_test_function_type) (ret_longdouble_test_type);
static int ret_longdouble_test_callback2(void *ptr) {
ret_longdouble_test_function_type f = (ret_longdouble_test_function_type)ptr;
ret_longdouble_test_type a = {10};
ret_longdouble_test_type r;
r = f(a);
return ((r.x == a.x*5) && (f(a).x == a.x*5)) ? 0 : -1;
}
static int ret_longdouble_test2(void) {
const char *src =
"typedef struct ret_longdouble_test_type_s2 {long double x;} ret_longdouble_test_type;"
"ret_longdouble_test_type f(ret_longdouble_test_type a) {\n"
" ret_longdouble_test_type r = {a.x*5};\n"
" return r;\n"
"}\n";
return run_callback(src, ret_longdouble_test_callback2);
}
typedef struct ret_longlong_test_type_s2 {int x[4];} ret_longlong_test_type;
typedef ret_longlong_test_type (*ret_longlong_test_function_type) (ret_longlong_test_type);
static int ret_longlong_test_callback2(void *ptr) {
ret_longlong_test_function_type f = (ret_longlong_test_function_type)ptr;
ret_longlong_test_type a = {{10,11,12,13}};
ret_longlong_test_type r;
r = f(a);
return ((r.x[2] == a.x[2]*5) && (f(a).x[2] == a.x[2]*5)) ? 0 : -1;
}
static int ret_longlong_test2(void) {
const char *src =
"typedef struct ret_longlong_test_type_s2 {int x[4];} ret_longlong_test_type;"
"ret_longlong_test_type f(ret_longlong_test_type a) {\n"
" ret_longlong_test_type r = {.x[2] = a.x[2]*5};\n"
" return r;\n"
"}\n";
return run_callback(src, ret_longlong_test_callback2);
}
/*
* reg_pack_test: return a small struct which should be packed into
* registers (Win32) during return.
@ -142,7 +186,7 @@ static int reg_pack_test_callback(void *ptr) {
reg_pack_test_type a = {10, 35};
reg_pack_test_type r;
r = f(a);
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
return ((r.x == a.x*5) && (r.y == a.y*3) && (f(a).x == a.x*5) && (f(a).y == a.y*3)) ? 0 : -1;
}
static int reg_pack_test(void) {
@ -168,7 +212,7 @@ static int reg_pack_longlong_test_callback(void *ptr) {
reg_pack_longlong_test_type a = {10, 35};
reg_pack_longlong_test_type r;
r = f(a);
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
return ((r.x == a.x*5) && (r.y == a.y*3) && (f(a).x == a.x*5) && (f(a).y == a.y*3)) ? 0 : -1;
}
static int reg_pack_longlong_test(void) {
@ -248,7 +292,7 @@ static int two_member_union_test_callback(void *ptr) {
two_member_union_test_type a, b;
a.x = 34;
b = f(a);
return (b.x == a.x*2) ? 0 : -1;
return ((b.x == a.x*2) && (f(a).x == a.x*2)) ? 0 : -1;
}
static int two_member_union_test(void) {
@ -339,8 +383,8 @@ static int stdarg_test(void) {
"#include <stdarg.h>\n"
"typedef struct {long long a, b, c;} stdarg_test_struct_type;\n"
"void f(int n_int, int n_float, int n_struct, ...) {\n"
" int i, ti;\n"
" double td;\n"
" int i, ti = 0;\n"
" double td = 0.0;\n"
" stdarg_test_struct_type ts = {0,0,0}, tmp;\n"
" va_list ap;\n"
" va_start(ap, n_struct);\n"
@ -441,6 +485,8 @@ int main(int argc, char **argv) {
RUN_TEST(ret_longdouble_test);
RUN_TEST(ret_2float_test);
RUN_TEST(ret_2double_test);
RUN_TEST(ret_longlong_test2);
RUN_TEST(ret_longdouble_test2);
RUN_TEST(reg_pack_test);
RUN_TEST(reg_pack_longlong_test);
RUN_TEST(sret_test);

View File

@ -59,6 +59,7 @@
#include "tcclib.h"
void intdiv_test();
void string_test();
void expr_test();
void macro_test();
@ -167,6 +168,71 @@ int qq(int x)
#define wq_spin_lock spin_lock
#define TEST2() wq_spin_lock(a)
#define UINT_MAX ((unsigned) -1)
void intdiv_test(void)
{
printf("18/21=%u\n", 18/21);
printf("18%21=%u\n", 18%21);
printf("41/21=%u\n", 41/21);
printf("41%21=%u\n", 41%21);
printf("42/21=%u\n", 42/21);
printf("42%21=%u\n", 42%21);
printf("43/21=%u\n", 43/21);
printf("43%21=%u\n", 43%21);
printf("126/21=%u\n", 126/21);
printf("12%/21=%u\n", 126%21);
printf("131/21=%u\n", 131/21);
printf("131%21=%u\n", 131%21);
printf("(UINT_MAX/2+3)/2=%u\n", (UINT_MAX/2+3)/2);
printf("(UINT_MAX/2+3)%2=%u\n", (UINT_MAX/2+3)%2);
printf("18/-21=%u\n", 18/-21);
printf("18%-21=%u\n", 18%-21);
printf("41/-21=%u\n", 41/-21);
printf("41%-21=%u\n", 41%-21);
printf("42/-21=%u\n", 42/-21);
printf("42%-21=%u\n", 42%-21);
printf("43/-21=%u\n", 43/-21);
printf("43%-21=%u\n", 43%-21);
printf("126/-21=%u\n", 126/-21);
printf("12%/-21=%u\n", 126%-21);
printf("131/-21=%u\n", 131/-21);
printf("131%-21=%u\n", 131%-21);
printf("(UINT_MAX/2+3)/-2=%u\n", (UINT_MAX/2+3)/-2);
printf("(UINT_MAX/2+3)%-2=%u\n", (UINT_MAX/2+3)%-2);
printf("-18/21=%u\n", -18/21);
printf("-18%21=%u\n", -18%21);
printf("-41/21=%u\n", -41/21);
printf("-41%21=%u\n", -41%21);
printf("-42/21=%u\n", -42/21);
printf("-42%21=%u\n", -42%21);
printf("-43/21=%u\n", -43/21);
printf("-43%21=%u\n", -43%21);
printf("-126/21=%u\n", -126/21);
printf("-12%/21=%u\n", -126%21);
printf("-131/21=%u\n", -131/21);
printf("-131%21=%u\n", -131%21);
printf("-(UINT_MAX/2+3)/2=%u\n", (0-(UINT_MAX/2+3))/2);
printf("-(UINT_MAX/2+3)%2=%u\n", (0-(UINT_MAX/2+3))%2);
printf("-18/-21=%u\n", -18/-21);
printf("-18%-21=%u\n", -18%-21);
printf("-41/-21=%u\n", -41/-21);
printf("-41%-21=%u\n", -41%-21);
printf("-42/-21=%u\n", -42/-21);
printf("-42%-21=%u\n", -42%-21);
printf("-43/-21=%u\n", -43/-21);
printf("-43%-21=%u\n", -43%-21);
printf("-126/-21=%u\n", -126/-21);
printf("-12%/-21=%u\n", -126%-21);
printf("-131/-21=%u\n", -131/-21);
printf("-131%-21=%u\n", -131%-21);
printf("-(UINT_MAX/2+3)/-2=%u\n", (0-(UINT_MAX/2+3))/-2);
printf("-(UINT_MAX/2+3)%-2=%u\n", (0-(UINT_MAX/2+3))%-2);
}
void macro_test(void)
{
printf("macro:\n");
@ -619,6 +685,7 @@ int main(int argc, char **argv)
math_cmp_test();
callsave_test();
builtin_frame_address_test();
intdiv_test();
return 0;
}
@ -1603,21 +1670,32 @@ void prefix ## fcast(type a)\
double da;\
LONG_DOUBLE la;\
int ia;\
long long llia;\
unsigned int ua;\
unsigned long long llua;\
type b;\
fa = a;\
da = a;\
la = a;\
printf("ftof: %f %f %Lf\n", fa, da, la);\
ia = (int)a;\
llia = (long long)a;\
a = (a >= 0) ? a : -a;\
ua = (unsigned int)a;\
printf("ftoi: %d %u\n", ia, ua);\
llua = (unsigned long long)a;\
printf("ftoi: %d %u %lld %llu\n", ia, ua, llia, llua);\
ia = -1234;\
ua = 0x81234500;\
llia = -0x123456789012345LL;\
llua = 0xf123456789012345LLU;\
b = ia;\
printf("itof: " fmt "\n", b);\
b = ua;\
printf("utof: " fmt "\n", b);\
b = llia;\
printf("lltof: " fmt "\n", b);\
b = llua;\
printf("ulltof: " fmt "\n", b);\
}\
\
float prefix ## retf(type a) { return a; }\
@ -1632,6 +1710,35 @@ void prefix ## call(void)\
printf("strto%s: %f\n", #prefix, (double)strto ## prefix("1.2", NULL));\
}\
\
void prefix ## signed_zeros(void) \
{\
type x = 0.0, y = -0.0, n, p;\
if (x == y)\
printf ("Test 1.0 / x != 1.0 / y returns %d (should be 1).\n",\
1.0 / x != 1.0 / y);\
else\
printf ("x != y; this is wrong!\n");\
\
n = -x;\
if (x == n)\
printf ("Test 1.0 / x != 1.0 / -x returns %d (should be 1).\n",\
1.0 / x != 1.0 / n);\
else\
printf ("x != -x; this is wrong!\n");\
\
p = +y;\
if (x == p)\
printf ("Test 1.0 / x != 1.0 / +y returns %d (should be 1).\n",\
1.0 / x != 1.0 / p);\
else\
printf ("x != +y; this is wrong!\n");\
p = -y;\
if (x == p)\
printf ("Test 1.0 / x != 1.0 / -y returns %d (should be 0).\n",\
1.0 / x != 1.0 / p);\
else\
printf ("x != -y; this is wrong!\n");\
}\
void prefix ## test(void)\
{\
printf("testing '%s'\n", #typename);\
@ -1641,6 +1748,7 @@ void prefix ## test(void)\
prefix ## fcast(234.6);\
prefix ## fcast(-2334.6);\
prefix ## call();\
prefix ## signed_zeros();\
}
FTEST(f, float, float, "%f")
@ -2113,7 +2221,7 @@ void old_style_function(void)
void alloca_test()
{
#if defined __i386__ || defined __x86_64__
#if defined __i386__ || defined __x86_64__ || defined __arm__
char *p = alloca(16);
strcpy(p,"123456789012345");
printf("alloca: p is %s\n", p);
@ -2146,7 +2254,7 @@ void c99_vla_test(int size1, int size2)
printf("%s\n", (sizeof tab1 == size1 * size2 * 2 * sizeof(int)) ? "PASSED" : "FAILED");
tab1_ptr = tab1;
tab2_ptr = tab2;
printf("Test C99 VLA 2 (ptrs substract): ");
printf("Test C99 VLA 2 (ptrs subtract): ");
printf("%s\n", (tab2 - tab1 == (tab2_ptr - tab1_ptr) / (sizeof(int) * 2)) ? "PASSED" : "FAILED");
printf("Test C99 VLA 3 (ptr add): ");
printf("%s\n", &tab1[5][1] == (tab1_ptr + (5 * 2 + 1) * sizeof(int)) ? "PASSED" : "FAILED");
@ -2686,7 +2794,7 @@ double get100 () { return 100.0; }
void callsave_test(void)
{
#if defined __i386__ || defined __x86_64__
#if defined __i386__ || defined __x86_64__ || defined __arm__
int i, s; double *d; double t;
s = sizeof (double);
printf ("callsavetest: %d\n", s);
@ -2715,16 +2823,17 @@ void bfa2(ptrdiff_t str_offset)
void bfa1(ptrdiff_t str_offset)
{
printf("bfa1: %s\n", (char *)__builtin_frame_address(1) + str_offset);
#if defined(__arm__) && !defined(__GNUC__)
bfa2(str_offset);
#endif
}
void builtin_frame_address_test(void)
{
/* builtin_frame_address fails on ARM with gcc which make test3 fail */
#ifndef __arm__
char str[] = "__builtin_frame_address";
char *fp0 = __builtin_frame_address(0);
printf("str: %s\n", str);
bfa1(str-fp0);
#endif
}

View File

@ -6,7 +6,7 @@ struct fred
int natasha;
};
void main()
int main()
{
struct fred bloggs;

View File

@ -68,7 +68,7 @@ void PrintAll()
/* Returns the value moved (not used.) */
int Move(int *source, int *dest)
{
int i,j;
int i = 0, j = 0;
while (i<N && (source[i])==0) i++;
while (j<N && (dest[j])==0) j++;

View File

@ -5,7 +5,7 @@ int main(int argc, char **argv)
int Count;
printf("hello world %d\n", argc);
for (Count = 0; Count < argc; Count++)
for (Count = 1; Count < argc; Count++)
printf("arg %d: %s\n", Count, argv[Count]);
return 0;

View File

@ -1,7 +1,6 @@
hello world 6
arg 0: 31_args.c
arg 1: -
arg 2: arg1
arg 3: arg2
arg 4: arg3
arg 5: arg4
arg 1: arg1
arg 2: arg2
arg 3: arg3
arg 4: arg4
arg 5: arg5

View File

@ -15,6 +15,7 @@
* privileges were granted by DECUS.
*/
#include <stdio.h>
#include <stdlib.h>
/*
* grep
@ -25,14 +26,13 @@
* See below for more information.
*/
#if 0
char *documentation[] = {
"grep searches a file for a given pattern. Execute by",
" grep [flags] regular_expression file_list\n",
"Flags are single characters preceeded by '-':",
"Flags are single characters preceded by '-':",
" -c Only a count of matching lines is printed",
" -f Print file name for matching lines switch, see below",
" -n Each line is preceeded by its line number",
" -n Each line is preceded by its line number",
" -v Only print non-matching lines\n",
"The file_list is a list of files (wildcards are acceptable on RSX modes).",
"\nThe file name is normally printed if there is a file given.",
@ -54,10 +54,10 @@ char *patdoc[] = {
"':n' \":n\" matches alphanumerics, \": \" matches spaces, tabs, and",
"': ' other control characters, such as new-line.",
"'*' An expression followed by an asterisk matches zero or more",
" occurrances of that expression: \"fo*\" matches \"f\", \"fo\"",
" occurrences of that expression: \"fo*\" matches \"f\", \"fo\"",
" \"foo\", etc.",
"'+' An expression followed by a plus sign matches one or more",
" occurrances of that expression: \"fo+\" matches \"fo\", etc.",
" occurrences of that expression: \"fo+\" matches \"fo\", etc.",
"'-' An expression followed by a minus sign optionally matches",
" the expression.",
"'[]' A string enclosed in square brackets matches any character in",
@ -70,7 +70,6 @@ char *patdoc[] = {
" [a-z] matches alphabetics, while [z-a] never matches.",
"The concatenation of regular expressions is a regular expression.",
0};
#endif
#define LMAX 512
#define PMAX 256
@ -97,6 +96,10 @@ char *pp, lbuf[LMAX], pbuf[PMAX];
char *cclass();
char *pmatch();
void store(int);
void error(char *);
void badpat(char *, char *, char *);
int match(void);
/*** Display a file name *******************************/
@ -153,7 +156,7 @@ void compile(char *source)
o == STAR ||
o == PLUS ||
o == MINUS)
badpat("Illegal occurrance op.", source, s);
badpat("Illegal occurrence op.", source, s);
store(ENDPAT);
store(ENDPAT);
spp = pp; /* Save pattern end */
@ -300,7 +303,7 @@ void badpat(char *message, char *source, char *stop)
/* char *stop; // Pattern end */
{
fprintf(stderr, "-GREP-E-%s, pattern is\"%s\"\n", message, source);
fprintf(stderr, "-GREP-E-Stopped at byte %d, '%c'\n",
fprintf(stderr, "-GREP-E-Stopped at byte %ld, '%c'\n",
stop-source, stop[-1]);
error("?GREP-E-Bad pattern\n");
}
@ -338,7 +341,7 @@ void grep(FILE *fp, char *fn)
}
/*** Match line (lbuf) with pattern (pbuf) return 1 if match ***/
void match()
int match()
{
char *l; /* Line pointer */
@ -368,7 +371,7 @@ char *pmatch(char *line, char *pattern)
p = pattern;
while ((op = *p++) != ENDPAT) {
if (debug > 1)
printf("byte[%d] = 0%o, '%c', op = 0%o\n",
printf("byte[%ld] = 0%o, '%c', op = 0%o\n",
l-line, *l, *l, op);
switch(op) {

View File

@ -0,0 +1,3 @@
File 46_grep.c:
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/

View File

@ -0,0 +1 @@
struct A {} int i;

View File

@ -0,0 +1 @@
56_btype_excess-1.c:1: error: too many basic types

View File

@ -0,0 +1 @@
char int i;

View File

@ -0,0 +1 @@
57_btype_excess-2.c:1: error: too many basic types

View File

@ -0,0 +1,9 @@
int f(void)
{
return 0;
}
int f(void)
{
return 1;
}

View File

@ -0,0 +1 @@
58_function_redefinition.c:7: error: redefinition of 'f'

View File

@ -0,0 +1 @@
int (*fct)[42](int x);

View File

@ -0,0 +1 @@
59_function_array.c:1: error: declaration of an array of functions

View File

@ -0,0 +1,4 @@
enum color {RED, GREEN, BLUE};
enum color {R, G, B};
enum color c;

View File

@ -0,0 +1 @@
60_enum_redefinition.c:2: error: struct/union/enum already defined

View File

@ -0,0 +1 @@
enum rgb c = 42;

View File

@ -0,0 +1 @@
61_undefined_enum.c:1: error: unknown struct/union/enum

View File

@ -0,0 +1,4 @@
enum color {RED, GREEN, BLUE};
enum rgb {RED, G, B};
enum color c = RED;

View File

@ -0,0 +1 @@
62_enumerator_redefinition.c:2: error: redefinition of enumerator 'RED'

View File

@ -0,0 +1,14 @@
enum {
FOO,
BAR
};
int main(void)
{
enum {
FOO = 2,
BAR
};
return BAR - FOO;
}

View File

@ -0,0 +1,10 @@
#define CAT2(a,b) a##b
#define CAT(a,b) CAT2(a,b)
#define AB(x) CAT(x,y)
int main(void)
{
int xy = 42;
printf("%d\n", CAT(A,B)(x));
return 0;
}

View File

@ -0,0 +1 @@
42

View File

@ -0,0 +1,2 @@
#define paste(A,B) ##A B
paste(x,y)

View File

@ -0,0 +1 @@
65_macro_concat_start.c:1: error: '##' invalid at start of macro

View File

@ -0,0 +1,2 @@
#define paste(A,B) A B##
paste(x,y)

View File

@ -0,0 +1 @@
66_macro_concat_end.c:2: error: '##' invalid at end of macro

View File

@ -0,0 +1,14 @@
#include <stdio.h>
#define P(A,B) A ## B ; bob
#define Q(A,B) A ## B+
int main(void)
{
int bob, jim = 21;
bob = P(jim,) *= 2;
printf("jim: %d, bob: %d\n", jim, bob);
jim = 60 Q(+,)3;
printf("jim: %d\n", jim);
return 0;
}

View File

@ -0,0 +1,2 @@
jim: 21, bob: 42
jim: 63

View File

@ -1,10 +1,10 @@
TOP = ../..
include $(TOP)/Makefile
VPATH = $(top_srcdir)/tests/tests2
TCCFLAGS = -B$(TOP) -I$(top_srcdir)/include
ifdef CONFIG_WIN32
TCCFLAGS = -B$(top_srcdir)/win32 -I$(top_srcdir)/include -L$(TOP)
else
TCCFLAGS = -B$(TOP) -I$(top_srcdir)/include -lm
endif
ifeq ($(TARGETOS),Darwin)
@ -46,9 +46,11 @@ TESTS = \
27_sizeof.test \
28_strings.test \
29_array_address.test \
30_hanoi.test \
31_args.test \
32_led.test \
33_ternary_op.test \
34_array_assignment.test \
35_sizeof.test \
36_array_initialisers.test \
37_sprintf.test \
@ -60,6 +62,7 @@ TESTS = \
43_void_param.test \
44_scoped_declarations.test \
45_empty_for.test \
46_grep.test \
47_switch_return.test \
48_nested_break.test \
49_bracket_evaluation.test \
@ -67,35 +70,48 @@ TESTS = \
51_static.test \
52_unnamed_enum.test \
54_goto.test \
55_lshift_type.test
55_lshift_type.test \
56_btype_excess-1.test \
57_btype_excess-2.test \
58_function_redefinition.test \
59_function_array.test \
60_enum_redefinition.test \
61_undefined_enum.test \
62_enumerator_redefinition.test \
63_local_enumerator_redefinition.test \
64_macro_nesting.test \
65_macro_concat_start.test \
66_macro_concat_end.test \
67_macro_concat.test
# 30_hanoi.test -- seg fault in the code, gcc as well
# 34_array_assignment.test -- array assignment is not in C standard
# 46_grep.test -- does not compile even with gcc
SKIP = 34_array_assignment.test
# some tests do not pass on all platforms, remove them for now
ifeq ($(TARGETOS),Darwin)
TESTS := $(filter-out 40_stdio.test,$(TESTS))
SKIP += 40_stdio.test
endif
ifdef CONFIG_WIN32
TESTS := $(filter-out 24_math_library.test 28_strings.test,$(TESTS))
SKIP += 24_math_library.test # don't have round()
SKIP += 28_strings.test # don't have r/index() / strings.h
endif
# Some tests might need arguments
ARGS =
31_args.test : ARGS = arg1 arg2 arg3 arg4 arg5
46_grep.test : ARGS = '[^* ]*[:a:d: ]+\:\*-/: $$' 46_grep.c
all test: $(filter-out $(SKIP),$(TESTS))
%.test: %.c %.expect
@echo Test: $*...
@if [ "x`echo $* | grep args`" != "x" ]; \
then $(TCC) $< -norunsrc -run $(notdir $<) - arg1 arg2 arg3 arg4 >$*.output; \
else $(TCC) -run $< >$*.output; \
fi
@if diff -bu $(<:.c=.expect) $*.output ; \
then rm -f $*.output; \
else exit 1; \
fi
all test: $(TESTS)
@$(TCC) -run $< $(ARGS) >$*.output 2>&1 || true
@diff -bu $*.expect $*.output && rm -f $*.output
@($(TCC) $< -o $*.exe && ./$*.exe $(ARGS)) >$*.output2 2>&1 || true
@diff -bu $*.expect $*.output2 && rm -f $*.output2 $*.exe
clean:
rm -vf fred.txt *.output
Makefile: $(top_srcdir)/tests/tests2/Makefile
cp $< $@
rm -vf fred.txt *.output* *.exe

View File

@ -5,7 +5,7 @@
@set /p VERSION= < ..\VERSION
echo>..\config.h #define TCC_VERSION "%VERSION%"
@if _%PROCESSOR_ARCHITEW6432%_==_AMD64_ goto x86_64
@rem @if _%PROCESSOR_ARCHITEW6432%_==_AMD64_ goto x86_64
@if _%PROCESSOR_ARCHITECTURE%_==_AMD64_ goto x86_64
@set target=-DTCC_TARGET_PE -DTCC_TARGET_I386
@ -25,7 +25,7 @@ echo>..\config.h #define TCC_VERSION "%VERSION%"
%CC% %target% tools/tiny_libmaker.c -o tiny_libmaker.exe
:libtcc
if not exist libtcc\nul mkdir libtcc
if not exist libtcc mkdir libtcc
copy ..\libtcc.h libtcc\libtcc.h
%CC% %target% -shared -DLIBTCC_AS_DLL -DONE_SOURCE ../libtcc.c -o libtcc.dll -Wl,-out-implib,libtcc/libtcc.a
tiny_impdef libtcc.dll -o libtcc/libtcc.def
@ -58,3 +58,10 @@ tiny_libmaker lib/libtcc1.a libtcc1.o alloca86_64.o crt1.o wincrt1.o dllcrt1.o d
:the_end
del *.o
:makedoc
echo>..\config.texi @set VERSION %VERSION%
if not exist doc md doc
makeinfo --html --no-split -o doc\tcc-doc.html ../tcc-doc.texi
copy tcc-win32.txt doc
copy ..\tests\libtcc_test.c examples

View File

@ -666,6 +666,7 @@ extern "C" {
extern long double __cdecl fmal (long double, long double, long double);
#if 0 // gr: duplicate, see below
/* 7.12.14 */
/*
* With these functions, comparisons involving quiet NaNs set the FP
@ -708,6 +709,7 @@ extern "C" {
& 0x4500) == 0x4500)
#endif
#endif //0
#endif /* __STDC_VERSION__ >= 199901L */

View File

@ -153,20 +153,20 @@ extern "C" {
stupid warnings, define them in POSIX way. This is save, because those
methods do not return in success case, so that the return value is not
really dependent to its scalar width. */
int __cdecl execv(const char *_Filename,char *const _ArgList[]);
int __cdecl execve(const char *_Filename,char *const _ArgList[],char *const _Env[]);
int __cdecl execvp(const char *_Filename,char *const _ArgList[]);
int __cdecl execvpe(const char *_Filename,char *const _ArgList[],char *const _Env[]);
int __cdecl execv(const char *_Filename,const char *const _ArgList[]);
int __cdecl execve(const char *_Filename,const char *const _ArgList[],const char *const _Env[]);
int __cdecl execvp(const char *_Filename,const char *const _ArgList[]);
int __cdecl execvpe(const char *_Filename,const char *const _ArgList[],const char *const _Env[]);
#else
intptr_t __cdecl execv(const char *_Filename,char *const _ArgList[]);
intptr_t __cdecl execve(const char *_Filename,char *const _ArgList[],char *const _Env[]);
intptr_t __cdecl execvp(const char *_Filename,char *const _ArgList[]);
intptr_t __cdecl execvpe(const char *_Filename,char *const _ArgList[],char *const _Env[]);
intptr_t __cdecl execv(const char *_Filename,const char *const _ArgList[]);
intptr_t __cdecl execve(const char *_Filename,const char *const _ArgList[],const char *const _Env[]);
intptr_t __cdecl execvp(const char *_Filename,const char *const _ArgList[]);
intptr_t __cdecl execvpe(const char *_Filename,const char *const _ArgList[],const char *const _Env[]);
#endif
intptr_t __cdecl spawnv(int,const char *_Filename,char *const _ArgList[]);
intptr_t __cdecl spawnve(int,const char *_Filename,char *const _ArgList[],char *const _Env[]);
intptr_t __cdecl spawnvp(int,const char *_Filename,char *const _ArgList[]);
intptr_t __cdecl spawnvpe(int,const char *_Filename,char *const _ArgList[],char *const _Env[]);
intptr_t __cdecl spawnv(int,const char *_Filename,const char *const _ArgList[]);
intptr_t __cdecl spawnve(int,const char *_Filename,const char *const _ArgList[],const char *const _Env[]);
intptr_t __cdecl spawnvp(int,const char *_Filename,const char *const _ArgList[]);
intptr_t __cdecl spawnvpe(int,const char *_Filename,const char *const _ArgList[],char *const _Env[]);
#endif
#ifdef __cplusplus

View File

@ -968,15 +968,15 @@ extern "C" {
LONG64 InterlockedExchangeAdd64(LONG64 volatile *Addend,LONG64 Value);
LONG64 InterlockedCompareExchange64(LONG64 volatile *Destination,LONG64 ExChange,LONG64 Comperand);
#else
LONG InterlockedIncrement(LONG volatile *lpAddend);
LONG InterlockedDecrement(LONG volatile *lpAddend);
LONG InterlockedExchange(LONG volatile *Target,LONG Value);
LONG WINAPI InterlockedIncrement(LONG volatile *lpAddend);
LONG WINAPI InterlockedDecrement(LONG volatile *lpAddend);
LONG WINAPI InterlockedExchange(LONG volatile *Target,LONG Value);
#define InterlockedExchangePointer(Target,Value) (PVOID)InterlockedExchange((PLONG)(Target),(LONG)(Value))
LONG InterlockedExchangeAdd(LONG volatile *Addend,LONG Value);
LONG InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange,LONG Comperand);
LONGLONG InterlockedCompareExchange64(LONGLONG volatile *Destination,LONGLONG Exchange,LONGLONG Comperand);
LONG WINAPI InterlockedExchangeAdd(LONG volatile *Addend,LONG Value);
LONG WINAPI InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange,LONG Comperand);
LONGLONG WINAPI InterlockedCompareExchange64(LONGLONG volatile *Destination,LONGLONG Exchange,LONGLONG Comperand);
__CRT_INLINE LONGLONG InterlockedAnd64 (LONGLONG volatile *Destination,LONGLONG Value) {
LONGLONG Old;

View File

@ -59,6 +59,6 @@ int _runwinmain(int argc, char **argv)
szCmd = "";
else if (szCmd > p && szCmd[-1] == '\"')
--szCmd;
_controlfp(0x10000, 0x30000);
return WinMain(GetModuleHandle(NULL), NULL, szCmd, SW_SHOWDEFAULT);
}

View File

@ -18,6 +18,12 @@
system PATH.
Include and library search paths
--------------------------------
On windows, the standard "include" and "lib" directories are searched
relatively from the location of the executables (tcc.exe, libtcc.dll).
Examples:
---------
Open a console window (DOS box) and 'cd' to the examples directory.

View File

@ -226,7 +226,7 @@ found:
for (l = 0;;) {
if (n+1 >= n0)
p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
if (!read_mem(fd, ptr - ref + l, p + n, 1) || ++l >= 80) {
if (!read_mem(fd, ptr - ref + l++, p + n, 1)) {
tcc_free(p), p = NULL;
goto the_end;
}

View File

@ -438,7 +438,7 @@ ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) /* must be last !OP0 */
#undef ALT
#undef DEF_ASM_OP0

View File

@ -112,8 +112,8 @@ enum {
#define R_JMP_SLOT R_X86_64_JUMP_SLOT
#define R_COPY R_X86_64_COPY
#define ELF_START_ADDR 0x08048000
#define ELF_PAGE_SIZE 0x1000
#define ELF_START_ADDR 0x400000
#define ELF_PAGE_SIZE 0x200000
/******************************************************/
#else /* ! TARGET_DEFS_ONLY */
@ -239,13 +239,6 @@ static int is64_type(int t)
(t & VT_BTYPE) == VT_LLONG);
}
static int is_sse_float(int t) {
int bt;
bt = t & VT_BTYPE;
return bt == VT_DOUBLE || bt == VT_FLOAT;
}
/* instruction + 4 bytes data. Return the address of the data */
ST_FUNC int oad(int c, int s)
{
@ -373,7 +366,7 @@ void load(int r, SValue *sv)
#endif
fr = sv->r;
ft = sv->type.t;
ft = sv->type.t & ~VT_DEFSIGN;
fc = sv->c.ul;
#ifndef TCC_TARGET_PE
@ -508,7 +501,7 @@ void load(int r, SValue *sv)
o(0xc0 + REG_VALUE(v) + REG_VALUE(r)*8);
}
} else if (r == TREG_ST0) {
assert((v >= TREG_XMM0) || (v <= TREG_XMM7));
assert((v >= TREG_XMM0) && (v <= TREG_XMM7));
/* gen_cvt_ftof(VT_LDOUBLE); */
/* movsd %xmmN,-0x10(%rsp) */
o(0x110ff2);
@ -611,7 +604,7 @@ static void gcall_or_jmp(int is_jmp)
if (vtop->r & VT_SYM) {
/* relocation case */
greloc(cur_text_section, vtop->sym,
ind + 1, R_X86_64_PC32);
ind + 1, R_X86_64_PLT32);
} else {
/* put an empty PC32 relocation */
put_elf_reloc(symtab_section, cur_text_section,
@ -663,30 +656,37 @@ void gen_offs_sp(int b, int r, int d)
}
}
/* Return 1 if this function returns via an sret pointer, 0 otherwise */
ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align)
/* Return the number of registers needed to return the struct, or 0 if
returning via struct pointer. */
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align)
{
int size, align;
*ret_align = 1; // Never have to re-align return values for x86-64
size = type_size(vt, &align);
ret->ref = NULL;
if (size > 8) {
return 1;
return 0;
} else if (size > 4) {
ret->t = VT_LLONG;
return 0;
return 1;
} else if (size > 2) {
ret->t = VT_INT;
return 0;
return 1;
} else if (size > 1) {
ret->t = VT_SHORT;
return 0;
return 1;
} else {
ret->t = VT_BYTE;
return 0;
return 1;
}
}
static int is_sse_float(int t) {
int bt;
bt = t & VT_BTYPE;
return bt == VT_DOUBLE || bt == VT_FLOAT;
}
int gfunc_arg_size(CType *type) {
int align;
if (type->t & (VT_ARRAY|VT_BITFIELD))
@ -833,6 +833,7 @@ void gfunc_prolog(CType *func_type)
/* if the function returns a structure, then add an
implicit pointer parameter */
func_vt = sym->type;
func_var = (sym->c == FUNC_ELLIPSIS);
size = gfunc_arg_size(&func_vt);
if (size > 8) {
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
@ -932,7 +933,8 @@ typedef enum X86_64_Mode {
x86_64_mode_x87
} X86_64_Mode;
static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) {
static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b)
{
if (a == b)
return a;
else if (a == x86_64_mode_none)
@ -949,7 +951,8 @@ static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) {
return x86_64_mode_sse;
}
static X86_64_Mode classify_x86_64_inner(CType *ty) {
static X86_64_Mode classify_x86_64_inner(CType *ty)
{
X86_64_Mode mode;
Sym *f;
@ -978,7 +981,7 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) {
return x86_64_mode_memory;
mode = x86_64_mode_none;
for (; f; f = f->next)
for (f = f->next; f; f = f->next)
mode = classify_x86_64_merge(mode, classify_x86_64_inner(&f->type));
return mode;
@ -987,12 +990,14 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) {
assert(0);
}
static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count) {
static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count)
{
X86_64_Mode mode;
int size, align, ret_t;
int size, align, ret_t = 0;
if (ty->t & (VT_BITFIELD|VT_ARRAY)) {
*psize = 8;
*palign = 8;
*reg_count = 1;
ret_t = ty->t;
mode = x86_64_mode_integer;
@ -1030,6 +1035,7 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p
ret_t = (size > 4) ? VT_DOUBLE : VT_FLOAT;
}
break;
default: break; /* nothing to be done for x86_64_mode_memory and x86_64_mode_none*/
}
}
}
@ -1042,7 +1048,8 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p
return mode;
}
ST_FUNC int classify_x86_64_va_arg(CType *ty) {
ST_FUNC int classify_x86_64_va_arg(CType *ty)
{
/* This definition must be synced with stdarg.h */
enum __va_arg_type {
__va_gen_reg, __va_float_reg, __va_stack
@ -1056,11 +1063,13 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty) {
}
}
/* Return 1 if this function returns via an sret pointer, 0 otherwise */
int gfunc_sret(CType *vt, CType *ret, int *ret_align) {
/* Return the number of registers needed to return the struct, or 0 if
returning via struct pointer. */
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align)
{
int size, align, reg_count;
*ret_align = 1; // Never have to re-align return values for x86-64
return (classify_x86_64_arg(vt, ret, &size, &align, &reg_count) == x86_64_mode_memory);
return (classify_x86_64_arg(vt, ret, &size, &align, &reg_count) != x86_64_mode_memory);
}
#define REGN 6
@ -1083,7 +1092,7 @@ void gfunc_call(int nb_args)
{
X86_64_Mode mode;
CType type;
int size, align, r, args_size, stack_adjust, run_start, run_end, i, j, reg_count;
int size, align, r, args_size, stack_adjust, run_start, run_end, i, reg_count;
int nb_reg_args = 0;
int nb_sse_args = 0;
int sse_reg, gen_reg;
@ -1133,6 +1142,7 @@ void gfunc_call(int nb_args)
gen_reg -= reg_count;
if (gen_reg + reg_count > REGN) goto stack_arg;
break;
default: break; /* nothing to be done for x86_64_mode_none */
}
}
@ -1262,7 +1272,7 @@ void gfunc_call(int nb_args)
g(0x00);
args_size += size;
} else {
assert(mode == x86_64_mode_memory);
//assert(mode == x86_64_mode_memory);
/* allocate the necessary size on stack */
o(0x48);
@ -1366,7 +1376,7 @@ void gfunc_prolog(CType *func_type)
{
X86_64_Mode mode;
int i, addr, align, size, reg_count;
int param_addr, reg_param_index, sse_param_index;
int param_addr = 0, reg_param_index, sse_param_index;
Sym *sym;
CType *type;
@ -1499,6 +1509,7 @@ void gfunc_prolog(CType *func_type)
}
break;
}
default: break; /* nothing to be done for x86_64_mode_none */
}
sym_push(sym->v & ~SYM_FIELD, type,
VT_LOCAL | VT_LVAL, param_addr);
@ -1577,7 +1588,7 @@ int gtst(int inv, int t)
}
g(0x0f);
t = psym((vtop->c.i - 16) ^ inv, t);
} else if (v == VT_JMP || v == VT_JMPI) {
} else { /* VT_JMP || VT_JMPI */
/* && or || optimization */
if ((v & 1) == inv) {
/* insert vtop->c jump list in t */
@ -1590,23 +1601,6 @@ int gtst(int inv, int t)
t = gjmp(t);
gsym(vtop->c.i);
}
} else {
if (is_float(vtop->type.t) ||
(vtop->type.t & VT_BTYPE) == VT_LLONG) {
vpushi(0);
gen_op(TOK_NE);
}
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
/* constant jmp optimization */
if ((vtop->c.i != 0) != inv)
t = gjmp(t);
} else {
v = gv(RC_INT);
orex(0,v,v,0x85);
o(0xc0 + REG_VALUE(v) * 9);
g(0x0f);
t = psym(0x85 ^ inv, t);
}
}
vtop--;
return t;
@ -1788,7 +1782,10 @@ void gen_opf(int op)
swapped = 0;
if (swapped)
o(0xc9d9); /* fxch %st(1) */
o(0xe9da); /* fucompp */
if (op == TOK_EQ || op == TOK_NE)
o(0xe9da); /* fucompp */
else
o(0xd9de); /* fcompp */
o(0xe0df); /* fnstsw %ax */
if (op == TOK_EQ) {
o(0x45e480); /* and $0x45, %ah */
@ -1872,8 +1869,11 @@ void gen_opf(int op)
if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
o(0x66);
o(0x2e0f); /* ucomisd */
if (op == TOK_EQ || op == TOK_NE)
o(0x2e0f); /* ucomisd */
else
o(0x2f0f); /* comisd */
if (vtop->r & VT_LVAL) {
gen_modrm(vtop[-1].r, r, vtop->sym, fc);
} else {