summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Preud'homme <robotux@celest.fr>2013-02-16 14:16:00 +0100
committerThomas Preud'homme <robotux@celest.fr>2013-02-16 14:16:00 +0100
commit494749572823610f5ac6dcc3b3d4afe5ebb6371e (patch)
tree013cbe30c811cae87ebd7adf9f9fc7237718709a
parentdd8534ea8d48a37285f0304b730b1f456e73274a (diff)
Imported Upstream version 0.9.26
-rw-r--r--.gitignore9
-rw-r--r--Changelog40
-rw-r--r--Makefile174
-rw-r--r--README10
-rw-r--r--VERSION2
-rw-r--r--arm-gen.c74
-rw-r--r--c67-gen.c56
-rwxr-xr-xconfigure487
-rw-r--r--conftest.c71
-rw-r--r--i386-gen.c9
-rw-r--r--include/stddef.h2
-rw-r--r--lib/Makefile50
-rw-r--r--lib/bcheck.c65
-rw-r--r--lib/libtcc1.c9
-rw-r--r--libtcc.c687
-rw-r--r--libtcc.h41
-rw-r--r--tcc-doc.html2332
-rw-r--r--tcc-doc.texi73
-rw-r--r--tcc.c601
-rw-r--r--tcc.h516
-rw-r--r--tccasm.c3
-rw-r--r--tcccoff.c10
-rw-r--r--tccelf.c220
-rw-r--r--tccgen.c57
-rw-r--r--tccpe.c98
-rw-r--r--tccpp.c107
-rw-r--r--tccrun.c160
-rw-r--r--tests/Makefile123
-rw-r--r--tests/tcctest.c35
-rw-r--r--tests/tests2/00_assignment.c (renamed from tests2/00_assignment.c)0
-rw-r--r--tests/tests2/00_assignment.expect (renamed from tests2/00_assignment.expect)0
-rw-r--r--tests/tests2/01_comment.c (renamed from tests2/01_comment.c)0
-rw-r--r--tests/tests2/01_comment.expect (renamed from tests2/01_comment.expect)0
-rw-r--r--tests/tests2/02_printf.c (renamed from tests2/02_printf.c)0
-rw-r--r--tests/tests2/02_printf.expect (renamed from tests2/02_printf.expect)0
-rw-r--r--tests/tests2/03_struct.c (renamed from tests2/03_struct.c)0
-rw-r--r--tests/tests2/03_struct.expect (renamed from tests2/03_struct.expect)0
-rw-r--r--tests/tests2/04_for.c (renamed from tests2/04_for.c)0
-rw-r--r--tests/tests2/04_for.expect (renamed from tests2/04_for.expect)0
-rw-r--r--tests/tests2/05_array.c (renamed from tests2/05_array.c)0
-rw-r--r--tests/tests2/05_array.expect (renamed from tests2/05_array.expect)0
-rw-r--r--tests/tests2/06_case.c (renamed from tests2/06_case.c)0
-rw-r--r--tests/tests2/06_case.expect (renamed from tests2/06_case.expect)0
-rw-r--r--tests/tests2/07_function.c (renamed from tests2/07_function.c)0
-rw-r--r--tests/tests2/07_function.expect (renamed from tests2/07_function.expect)0
-rw-r--r--tests/tests2/08_while.c (renamed from tests2/08_while.c)0
-rw-r--r--tests/tests2/08_while.expect (renamed from tests2/08_while.expect)0
-rw-r--r--tests/tests2/09_do_while.c (renamed from tests2/09_do_while.c)0
-rw-r--r--tests/tests2/09_do_while.expect (renamed from tests2/09_do_while.expect)0
-rw-r--r--tests/tests2/10_pointer.c (renamed from tests2/10_pointer.c)0
-rw-r--r--tests/tests2/10_pointer.expect (renamed from tests2/10_pointer.expect)0
-rw-r--r--tests/tests2/11_precedence.c (renamed from tests2/11_precedence.c)0
-rw-r--r--tests/tests2/11_precedence.expect (renamed from tests2/11_precedence.expect)0
-rw-r--r--tests/tests2/12_hashdefine.c (renamed from tests2/12_hashdefine.c)0
-rw-r--r--tests/tests2/12_hashdefine.expect (renamed from tests2/12_hashdefine.expect)0
-rw-r--r--tests/tests2/13_integer_literals.c (renamed from tests2/13_integer_literals.c)0
-rw-r--r--tests/tests2/13_integer_literals.expect (renamed from tests2/13_integer_literals.expect)0
-rw-r--r--tests/tests2/14_if.c (renamed from tests2/14_if.c)0
-rw-r--r--tests/tests2/14_if.expect (renamed from tests2/14_if.expect)0
-rw-r--r--tests/tests2/15_recursion.c (renamed from tests2/15_recursion.c)0
-rw-r--r--tests/tests2/15_recursion.expect (renamed from tests2/15_recursion.expect)0
-rw-r--r--tests/tests2/16_nesting.c (renamed from tests2/16_nesting.c)0
-rw-r--r--tests/tests2/16_nesting.expect (renamed from tests2/16_nesting.expect)36
-rw-r--r--tests/tests2/17_enum.c (renamed from tests2/17_enum.c)0
-rw-r--r--tests/tests2/17_enum.expect (renamed from tests2/17_enum.expect)6
-rw-r--r--tests/tests2/18_include.c (renamed from tests2/18_include.c)0
-rw-r--r--tests/tests2/18_include.expect (renamed from tests2/18_include.expect)6
-rw-r--r--tests/tests2/18_include.h (renamed from tests2/18_include.h)2
-rw-r--r--tests/tests2/19_pointer_arithmetic.c (renamed from tests2/19_pointer_arithmetic.c)0
-rw-r--r--tests/tests2/19_pointer_arithmetic.expect (renamed from tests2/19_pointer_arithmetic.expect)0
-rw-r--r--tests/tests2/20_pointer_comparison.c (renamed from tests2/20_pointer_comparison.c)0
-rw-r--r--tests/tests2/20_pointer_comparison.expect (renamed from tests2/20_pointer_comparison.expect)0
-rw-r--r--tests/tests2/21_char_array.c (renamed from tests2/21_char_array.c)0
-rw-r--r--tests/tests2/21_char_array.expect (renamed from tests2/21_char_array.expect)0
-rw-r--r--tests/tests2/22_floating_point.c (renamed from tests2/22_floating_point.c)0
-rw-r--r--tests/tests2/22_floating_point.expect (renamed from tests2/22_floating_point.expect)0
-rw-r--r--tests/tests2/23_type_coercion.c (renamed from tests2/23_type_coercion.c)0
-rw-r--r--tests/tests2/23_type_coercion.expect (renamed from tests2/23_type_coercion.expect)0
-rw-r--r--tests/tests2/24_math_library.c (renamed from tests2/24_math_library.c)0
-rw-r--r--tests/tests2/24_math_library.expect (renamed from tests2/24_math_library.expect)0
-rw-r--r--tests/tests2/25_quicksort.c (renamed from tests2/25_quicksort.c)0
-rw-r--r--tests/tests2/25_quicksort.expect (renamed from tests2/25_quicksort.expect)0
-rw-r--r--tests/tests2/26_character_constants.c (renamed from tests2/26_character_constants.c)0
-rw-r--r--tests/tests2/26_character_constants.expect (renamed from tests2/26_character_constants.expect)0
-rw-r--r--tests/tests2/27_sizeof.c (renamed from tests2/27_sizeof.c)0
-rw-r--r--tests/tests2/27_sizeof.expect (renamed from tests2/27_sizeof.expect)0
-rw-r--r--tests/tests2/28_strings.c (renamed from tests2/28_strings.c)0
-rw-r--r--tests/tests2/28_strings.expect (renamed from tests2/28_strings.expect)0
-rw-r--r--tests/tests2/29_array_address.c (renamed from tests2/29_array_address.c)0
-rw-r--r--tests/tests2/29_array_address.expect (renamed from tests2/29_array_address.expect)0
-rw-r--r--tests/tests2/30_hanoi.c (renamed from tests2/30_hanoi.c)0
-rw-r--r--tests/tests2/30_hanoi.expect (renamed from tests2/30_hanoi.expect)0
-rw-r--r--tests/tests2/31_args.c (renamed from tests2/31_args.c)0
-rw-r--r--tests/tests2/31_args.expect (renamed from tests2/31_args.expect)0
-rw-r--r--tests/tests2/32_led.c (renamed from tests2/32_led.c)0
-rw-r--r--tests/tests2/32_led.expect (renamed from tests2/32_led.expect)0
-rw-r--r--tests/tests2/33_ternary_op.c (renamed from tests2/33_ternary_op.c)0
-rw-r--r--tests/tests2/33_ternary_op.expect (renamed from tests2/33_ternary_op.expect)0
-rw-r--r--tests/tests2/34_array_assignment.c (renamed from tests2/34_array_assignment.c)0
-rw-r--r--tests/tests2/34_array_assignment.expect (renamed from tests2/34_array_assignment.expect)0
-rw-r--r--tests/tests2/35_sizeof.c (renamed from tests2/35_sizeof.c)0
-rw-r--r--tests/tests2/35_sizeof.expect (renamed from tests2/35_sizeof.expect)0
-rw-r--r--tests/tests2/36_array_initialisers.c (renamed from tests2/36_array_initialisers.c)0
-rw-r--r--tests/tests2/36_array_initialisers.expect (renamed from tests2/36_array_initialisers.expect)0
-rw-r--r--tests/tests2/37_sprintf.c (renamed from tests2/37_sprintf.c)0
-rw-r--r--tests/tests2/37_sprintf.expect (renamed from tests2/37_sprintf.expect)0
-rw-r--r--tests/tests2/38_multiple_array_index.c (renamed from tests2/38_multiple_array_index.c)0
-rw-r--r--tests/tests2/38_multiple_array_index.expect (renamed from tests2/38_multiple_array_index.expect)0
-rw-r--r--tests/tests2/39_typedef.c (renamed from tests2/39_typedef.c)0
-rw-r--r--tests/tests2/39_typedef.expect (renamed from tests2/39_typedef.expect)0
-rw-r--r--tests/tests2/40_stdio.c (renamed from tests2/40_stdio.c)2
-rw-r--r--tests/tests2/40_stdio.expect (renamed from tests2/40_stdio.expect)0
-rw-r--r--tests/tests2/41_hashif.c (renamed from tests2/41_hashif.c)0
-rw-r--r--tests/tests2/41_hashif.expect (renamed from tests2/41_hashif.expect)0
-rw-r--r--tests/tests2/42_function_pointer.c (renamed from tests2/42_function_pointer.c)0
-rw-r--r--tests/tests2/42_function_pointer.expect (renamed from tests2/42_function_pointer.expect)0
-rw-r--r--tests/tests2/43_void_param.c (renamed from tests2/43_void_param.c)0
-rw-r--r--tests/tests2/43_void_param.expect (renamed from tests2/43_void_param.expect)0
-rw-r--r--tests/tests2/44_scoped_declarations.c (renamed from tests2/44_scoped_declarations.c)34
-rw-r--r--tests/tests2/44_scoped_declarations.expect (renamed from tests2/44_scoped_declarations.expect)0
-rw-r--r--tests/tests2/45_empty_for.c (renamed from tests2/45_empty_for.c)36
-rw-r--r--tests/tests2/45_empty_for.expect (renamed from tests2/45_empty_for.expect)0
-rw-r--r--tests/tests2/46_grep.c (renamed from tests2/46_grep.c)0
-rw-r--r--tests/tests2/47_switch_return.c (renamed from tests2/47_switch_return.c)0
-rw-r--r--tests/tests2/47_switch_return.expect (renamed from tests2/47_switch_return.expect)0
-rw-r--r--tests/tests2/48_nested_break.c (renamed from tests2/48_nested_break.c)0
-rw-r--r--tests/tests2/48_nested_break.expect (renamed from tests2/48_nested_break.expect)0
-rw-r--r--tests/tests2/49_bracket_evaluation.c (renamed from tests2/49_bracket_evaluation.c)0
-rw-r--r--tests/tests2/49_bracket_evaluation.expect (renamed from tests2/49_bracket_evaluation.expect)0
-rw-r--r--tests/tests2/50_logical_second_arg.c (renamed from tests2/50_logical_second_arg.c)58
-rw-r--r--tests/tests2/50_logical_second_arg.expect (renamed from tests2/50_logical_second_arg.expect)0
-rw-r--r--tests/tests2/51_static.c (renamed from tests2/51_static.c)0
-rw-r--r--tests/tests2/51_static.expect (renamed from tests2/51_static.expect)0
-rw-r--r--tests/tests2/52_unnamed_enum.c (renamed from tests2/52_unnamed_enum.c)0
-rw-r--r--tests/tests2/52_unnamed_enum.expect (renamed from tests2/52_unnamed_enum.expect)0
-rw-r--r--tests/tests2/54_goto.c (renamed from tests2/54_goto.c)112
-rw-r--r--tests/tests2/54_goto.expect (renamed from tests2/54_goto.expect)0
-rw-r--r--tests/tests2/55_lshift_type.c (renamed from tests2/55_lshift_type.c)0
-rw-r--r--tests/tests2/55_lshift_type.expect (renamed from tests2/55_lshift_type.expect)0
-rw-r--r--tests/tests2/LICENSE (renamed from tests2/LICENSE)0
-rw-r--r--tests/tests2/Makefile98
-rw-r--r--tests2/Makefile99
-rw-r--r--win32/build-tcc.bat124
-rw-r--r--win32/include/_mingw.h4
-rw-r--r--win32/include/malloc.h2
-rw-r--r--win32/lib/wincrt1.c1
-rw-r--r--win32/tcc-win32.txt313
-rw-r--r--win32/tools/tiny_impdef.c33
-rw-r--r--win32/tools/tiny_libmaker.c66
-rw-r--r--x86_64-gen.c5
150 files changed, 4837 insertions, 2321 deletions
diff --git a/.gitignore b/.gitignore
index bfcf93a..376ea52 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
*.a
tcc_g
tcc
+/*-tcc
tc2.c
doc
tc3s.c
@@ -9,8 +10,12 @@ p3.c
tc1.c
error.c
i386-gen1.c
+test.out1
+test.out1b
test.out2
+test.out2b
test.out3
+test.out3b
web.sh
memdebug.c
bench
@@ -32,6 +37,8 @@ tcctest[1234]
test[1234].out
tests/tcclib.h
tests/tcctest.gcc
+tests/weaktest.*.o.txt
+tests2/fred.txt
.gdb_history
tcc.1
tcc.pod
@@ -43,6 +50,8 @@ tags
*.swp
lib/x86_64
lib/i386
+lib/x86_64-win32
+lib/i386-win32
tcc-doc.info
conftest*
tiny_libmaker
diff --git a/Changelog b/Changelog
index 2a19902..bab887c 100644
--- a/Changelog
+++ b/Changelog
@@ -1,20 +1,30 @@
-not released:
-
-- Add support for -MD/-MF (automatically generate dependencies for make)
-- Add tcc_open_bf() function for BufferedFile compilation (grischka)
-- Support Security-Enhanced Linux (Henry Kroll III)
-- Split libtcc1.a build into separate directories (Henry Kroll III)
-- Add -pthread option = -D_REENTRANT -lpthread (Henry Kroll III)
-- Register __TRY__ SEH in startup code only for i386 (grischka)
+version 0.9.26:
+
+User interface:
+- -MD/-MF (automatically generate dependencies for make)
+- -pthread option (same as -D_REENTRANT -lpthread) (Henry Kroll III)
+- -m32/-m64 to re-exec cross compiler (Henry Kroll III)
+- -Wl, Mimic all GNU -option forms supported by ld (Kirill Smelkov)
+- new LIBTCCAPI tcc_set_options() (grischka)
+
+Platforms:
+- Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka)
+- x86-64 assembler (Frederic Feret)
+- Many improvements for ARM target (Daniel Glöckner, Thomas Preud'homme)
+- Support WinCE PE ARM (Timo VJ Lahde)
+- Support ARM hardfloat calling convention (Thomas Preud'homme)
+- Support SELinux (Security-Enhanced Linux) (Henry Kroll III)
- Support Debian GNU/kFreeBSD kernels (Pierre Chifflier)
- Support GNU/Hurd kernels (Thomas Preud'homme)
-- support for asm labels for variables and functions (Thomas Preud'homme)
-- Fix 32 to 64 bit casts, alignment and struct issues (Shinichiro Hamaji)
-- Mimic all GNU -option forms supported by ld (Kirill Smelkov)
-- Support indirect functions as externals (Thomas Preud'homme)
-- Add support for C99 variable length arrays (Thomas Preud'homme & Joe Soroka)
-- Improve support of ARM (Daniel Glöckner)
-- Support ARM hardfloat calling convention (Thomas Preud'homme)
+- Support OSX (tcc -run only) (Milutin Jovanovic)
+- Support multiarch configuration (Thomas Preud'homme)
+- Support out-of-tree build (Akim Demaille)
+
+Features:
+- C99 variable length arrays (Thomas Preud'homme & Joe Soroka)
+- Asm labels for variables and functions (Thomas Preud'homme)
+- STT_GNU_IFUNC (Indirect functions as externals) (Thomas Preud'homme)
+- More tests (tests2) (Milutin Jovanovic)
version 0.9.25:
diff --git a/Makefile b/Makefile
index 8062a3d..705b585 100644
--- a/Makefile
+++ b/Makefile
@@ -4,28 +4,34 @@
TOP ?= .
include $(TOP)/config.mak
+VPATH = $(top_srcdir)
-CFLAGS_P=$(CFLAGS) -pg -static -DCONFIG_TCC_STATIC
-LIBS_P=
+CPPFLAGS = -I$(TOP) # for config.h
-ifneq ($(GCC_MAJOR),2)
+ifeq (-$(findstring gcc,$(CC))-,-gcc-)
+ifeq (-$(findstring $(GCC_MAJOR),01)-,--)
CFLAGS+=-fno-strict-aliasing
-ifneq ($(GCC_MAJOR),3)
-CFLAGS+=-Wno-pointer-sign -Wno-sign-compare -D_FORTIFY_SOURCE=0
+ifeq (-$(findstring $(GCC_MAJOR),23)-,--)
+CFLAGS+=-Wno-pointer-sign -Wno-sign-compare
+ifeq (-$(GCC_MAJOR)-$(findstring $(GCC_MINOR),56789)-,-4--)
+CFLAGS+=-D_FORTIFY_SOURCE=0
+else
+CFLAGS+=-Wno-unused-result
endif
endif
-
-ifneq ($(TARGETOS),Darwin)
-ifeq ($(ARCH),i386)
-CFLAGS+=-mpreferred-stack-boundary=2
-ifeq ($(GCC_MAJOR),2)
-CFLAGS+=-m386 -malign-functions=0
-else
-CFLAGS+=-march=i386 -falign-functions=0
endif
+else # not GCC
+ifeq (-$(findstring clang,$(CC))-,-clang-)
+# make clang accept gnuisms in libtcc1.c
+CFLAGS+=-fheinous-gnu-extensions
endif
endif
+CPPFLAGS_P=$(CPPFLAGS) -DCONFIG_TCC_STATIC
+CFLAGS_P=$(CFLAGS) -pg -static
+LIBS_P=
+LDFLAGS_P=$(LDFLAGS)
+
ifdef CONFIG_WIN64
CONFIG_WIN32=yes
endif
@@ -37,43 +43,6 @@ LIBS+=-ldl
endif
endif
-ifeq ($(ARCH),i386)
-NATIVE_DEFINES=-DTCC_TARGET_I386
-NATIVE_DEFINES+=$(if $(wildcard /lib/i386-linux-gnu),-DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\")
-NATIVE_DEFINES+=$(if $(wildcard /lib/i386-kfreebsd-gnu),-DCONFIG_MULTIARCHDIR=\"i386-kfreebsd-gnu\")
-NATIVE_DEFINES+=$(if $(wildcard /lib/i386-gnu),-DCONFIG_MULTIARCHDIR=\"i386-gnu\")
-CFLAGS+=-m32
-else
-ifeq ($(ARCH),x86-64)
-NATIVE_DEFINES=-DTCC_TARGET_X86_64
-CFLAGS+=-m64
-NATIVE_DEFINES+=$(if $(wildcard /usr/lib64),-DCONFIG_LDDIR=\"lib64\")
-NATIVE_DEFINES+=$(if $(wildcard /lib/x86_64-linux-gnu),-DCONFIG_MULTIARCHDIR=\"x86_64-linux-gnu\")
-NATIVE_DEFINES+=$(if $(wildcard /lib/x86_64-kfreebsd-gnu),-DCONFIG_MULTIARCHDIR=\"x86_64-kfreebsd-gnu\")
-endif
-endif
-
-ifeq ($(ARCH),arm)
-NATIVE_DEFINES=-DTCC_TARGET_ARM
-NATIVE_DEFINES+=-DWITHOUT_LIBTCC
-NATIVE_DEFINES+=$(if $(wildcard /lib/ld-linux.so.3),-DTCC_ARM_EABI)
-ifneq (,$(wildcard /lib/arm-linux-gnueabi))
-NATIVE_DEFINES+=-DCONFIG_MULTIARCHDIR=\"arm-linux-gnueabi\"
-else
-NATIVE_DEFINES+=$(if $(wildcard /lib/arm-linux-gnueabihf),-DCONFIG_MULTIARCHDIR=\"arm-linux-gnueabihf\" -DTCC_ARM_HARDFLOAT)
-endif
-NATIVE_DEFINES+=$(if $(shell grep -l "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo),-DTCC_ARM_VFP)
-endif
-
-ifdef CONFIG_WIN32
-NATIVE_DEFINES+=-DTCC_TARGET_PE
-endif
-
-ifneq ($(wildcard /lib/ld-uClibc.so.0),)
-NATIVE_DEFINES+=-DTCC_UCLIBC
-CONFIG_UCLIBC = 1
-endif
-
# make libtcc as static or dynamic library?
ifdef DISABLE_STATIC
LIBTCC=libtcc.so.1.0
@@ -86,6 +55,17 @@ LIBTCC=libtcc.a
LINK_LIBTCC=
endif
+CONFIG_$(ARCH) = yes
+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_eabihf) += -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT
+NATIVE_DEFINES_$(CONFIG_arm_eabi) += -DTCC_ARM_EABI
+NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP
+NATIVE_DEFINES += $(NATIVE_DEFINES_yes)
+
ifeq ($(TOP),.)
PROGS=tcc$(EXESUF)
@@ -117,41 +97,28 @@ NATIVE_FILES=$(WIN64_FILES)
PROGS_CROSS=$(WIN32_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(C67_CROSS)
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a
LIBTCC1=libtcc1.a
-else
-ifdef CONFIG_WIN32
+else ifdef CONFIG_WIN32
PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF)
NATIVE_FILES=$(WIN32_FILES)
PROGS_CROSS=$(WIN64_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(C67_CROSS)
LIBTCC1_CROSS=lib/x86_64-win32/libtcc1.a
LIBTCC1=libtcc1.a
-else
-ifeq ($(ARCH),i386)
+else ifeq ($(ARCH),i386)
NATIVE_FILES=$(I386_FILES)
PROGS_CROSS=$(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS)
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a
LIBTCC1=libtcc1.a
-BCHECK_O=bcheck.o
-else
-ifeq ($(ARCH),x86-64)
+else ifeq ($(ARCH),x86-64)
NATIVE_FILES=$(X86_64_FILES)
PROGS_CROSS=$(I386_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS)
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a lib/i386/libtcc1.a
LIBTCC1=libtcc1.a
-else
-ifeq ($(ARCH),arm)
+else ifeq ($(ARCH),arm)
NATIVE_FILES=$(ARM_FILES)
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(C67_CROSS)
endif
-endif
-endif
-endif
-endif
-ifdef CONFIG_UCLIBC
-BCHECK_O=
-endif
ifeq ($(TARGETOS),Darwin)
-BCHECK_O=
PROGS+=tiny_libmaker$(EXESUF)
endif
@@ -159,7 +126,7 @@ ifdef CONFIG_USE_LIBGCC
LIBTCC1=
endif
-TCCLIBS = $(LIBTCC1) $(LIBTCC) $(BCHECK_O)
+TCCLIBS = $(LIBTCC1) $(LIBTCC)
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
ifdef CONFIG_CROSS
@@ -171,11 +138,15 @@ all: $(PROGS) $(TCCLIBS) $(TCCDOCS)
# Host Tiny C Compiler
tcc$(EXESUF): tcc.o $(LIBTCC)
- $(CC) -o $@ $^ $(LIBS) $(CFLAGS) $(LDFLAGS) $(LINK_LIBTCC)
+ $(CC) -o $@ $^ $(LIBS) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LINK_LIBTCC)
# Cross Tiny C Compilers
-%-tcc$(EXESUF):
- $(CC) -o $@ tcc.c -DONE_SOURCE $(DEFINES) $(CFLAGS) $(LIBS) $(LDFLAGS)
+%-tcc$(EXESUF): tcc.c
+ $(CC) -o $@ $< -DONE_SOURCE $(DEFINES) $(CPPFLAGS) $(CFLAGS) $(LIBS) $(LDFLAGS)
+
+# profiling version
+tcc_p$(EXESUF): $(NATIVE_FILES)
+ $(CC) -o $@ $< -DONE_SOURCE $(NATIVE_DEFINES) $(CPPFLAGS_P) $(CFLAGS_P) $(LIBS_P) $(LDFLAGS_P)
$(I386_CROSS): DEFINES = -DTCC_TARGET_I386 \
-DCONFIG_TCCDIR="\"$(tccdir)/i386\""
@@ -212,33 +183,28 @@ libtcc.o : NATIVE_DEFINES += -DONE_SOURCE
endif
$(LIBTCC_OBJ) tcc.o : %.o : %.c $(LIBTCC_INC)
- $(CC) -o $@ -c $< $(NATIVE_DEFINES) $(CFLAGS)
+ $(CC) -o $@ -c $< $(NATIVE_DEFINES) $(CPPFLAGS) $(CFLAGS)
libtcc.a: $(LIBTCC_OBJ)
$(AR) rcs $@ $^
libtcc.so.1.0: $(LIBTCC_OBJ)
- $(CC) -shared -Wl,-soname,$@ -o $@ $^
+ $(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDFLAGS)
libtcc.so.1.0: CFLAGS+=-fPIC
-# profiling version
-tcc_p$(EXESUF): $(NATIVE_FILES)
- $(CC) -o $@ $< $(NATIVE_DEFINES) $(CFLAGS_P) $(LIBS_P)
-
# windows utilities
tiny_impdef$(EXESUF): win32/tools/tiny_impdef.c
- $(CC) -o $@ $< $(CFLAGS)
+ $(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
tiny_libmaker$(EXESUF): win32/tools/tiny_libmaker.c
- $(CC) -o $@ $< $(CFLAGS)
+ $(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
# TinyCC runtime libraries
libtcc1.a : FORCE
- @$(MAKE) -C lib native
+ $(MAKE) -C lib native
lib/%/libtcc1.a : FORCE $(PROGS_CROSS)
- @$(MAKE) -C lib cross TARGET=$*
-bcheck.o : lib/bcheck.c
- gcc -c $< -o $@ $(CFLAGS)
+ $(MAKE) -C lib cross TARGET=$*
+
FORCE:
# install
@@ -267,10 +233,7 @@ endif
ifneq ($(LIBTCC1),)
$(INSTALL) -m644 $(LIBTCC1) "$(tccdir)"
endif
-ifneq ($(BCHECK_O),)
- $(INSTALL) -m644 $(BCHECK_O) "$(tccdir)"
-endif
- $(INSTALL) -m644 $(addprefix include/,$(TCC_INCLUDES)) "$(tccdir)/include"
+ $(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) "$(tccdir)/include"
mkdir -p "$(libdir)"
$(INSTALL) -m755 $(LIBTCC) "$(libdir)"
ifdef DISABLE_STATIC
@@ -278,7 +241,7 @@ ifdef DISABLE_STATIC
ln -sf "$(ln_libdir)/libtcc.so.1.0" "$(libdir)/libtcc.so"
endif
mkdir -p "$(includedir)"
- $(INSTALL) -m644 libtcc.h "$(includedir)"
+ $(INSTALL) -m644 $(top_srcdir)/libtcc.h "$(includedir)"
mkdir -p "$(docdir)"
-$(INSTALL) -m644 tcc-doc.html "$(docdir)"
ifdef CONFIG_CROSS
@@ -298,7 +261,7 @@ endif
uninstall:
rm -fv $(foreach P,$(PROGS),"$(bindir)/$P")
- rm -fv $(foreach P,$(LIBTCC1) $(BCHECK_O),"$(tccdir)/$P")
+ rm -fv $(foreach P,$(LIBTCC1),"$(tccdir)/$P")
rm -fv $(foreach P,$(TCC_INCLUDES),"$(tccdir)/include/$P")
rm -fv "$(docdir)/tcc-doc.html" "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info"
rm -fv "$(libdir)/$(LIBTCC)" "$(includedir)/libtcc.h"
@@ -340,32 +303,20 @@ tcc-doc.html: tcc-doc.texi
-texi2html -monolithic -number $<
tcc.1: tcc-doc.texi
- -./texi2pod.pl $< tcc.pod
+ -$(top_srcdir)/texi2pod.pl $< tcc.pod
-pod2man --section=1 --center=" " --release=" " tcc.pod > $@
tcc-doc.info: tcc-doc.texi
- -makeinfo tcc-doc.texi
-
-.PHONY: all clean tar distclean install uninstall FORCE
-
-# tar release (use 'make -k tar' on a checkouted tree)
-TCC-VERSION=tcc-$(shell cat VERSION)
-tar:
- rm -rf /tmp/$(TCC-VERSION)
- cp -r . /tmp/$(TCC-VERSION)
- ( cd /tmp ; tar zcvf ~/$(TCC-VERSION).tar.gz $(TCC-VERSION) --exclude CVS )
- rm -rf /tmp/$(TCC-VERSION)
+ -makeinfo $<
# in tests subdir
export LIBTCC1
%est:
- $(MAKE) -C tests2 $@
$(MAKE) -C tests $@
clean:
rm -vf $(PROGS) tcc_p$(EXESUF) tcc.pod *~ *.o *.a *.so* *.out *.exe libtcc_test$(EXESUF)
- $(MAKE) -C tests2 $@
$(MAKE) -C tests $@
ifneq ($(LIBTCC1),)
$(MAKE) -C lib $@
@@ -378,4 +329,21 @@ config.mak:
@echo "Please run ./configure."
@exit 1
+# create release tarball from *current* git branch (including tcc-doc.html
+# and converting two files to CRLF)
+TCC-VERSION := tcc-$(shell cat $(top_srcdir)/VERSION)
+tar: tcc-doc.html
+ mkdir $(TCC-VERSION)
+ ( cd $(TCC-VERSION) && git --git-dir ../.git checkout -f )
+ cp tcc-doc.html $(TCC-VERSION)
+ for f in tcc-win32.txt build-tcc.bat ; do \
+ cat win32/$$f | sed 's,\(.*\),\1\r,g' > $(TCC-VERSION)/win32/$$f ; \
+ done
+ tar cjf $(TCC-VERSION).tar.bz2 $(TCC-VERSION)
+ rm -rf $(TCC-VERSION)
+ git reset
+
+
+.PHONY: all clean tar distclean install uninstall FORCE
+
endif # ifeq ($(TOP),.)
diff --git a/README b/README
index 0ead1ee..43e6c3b 100644
--- a/README
+++ b/README
@@ -35,6 +35,16 @@ Documentation:
make test
make install
+Alternatively, out-of-tree builds are supported: you may use different
+directories to hold build objects, kept separate from your source tree:
+
+ mkdir _build
+ cd _build
+ ../configure
+ make
+ make test
+ make install
+
By default, tcc is installed in /usr/local/bin.
./configure --help shows configuration options.
diff --git a/VERSION b/VERSION
index f5b38be..46e7a71 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.9.25 \ No newline at end of file
+0.9.26
diff --git a/arm-gen.c b/arm-gen.c
index d8e68ae..6981395 100644
--- a/arm-gen.c
+++ b/arm-gen.c
@@ -2,6 +2,7 @@
* ARMv4 code generator for TCC
*
* Copyright (c) 2003 Daniel Glöckner
+ * Copyright (c) 2012 Thomas Preud'homme
*
* Based on i386-gen.c by Fabrice Bellard
*
@@ -35,6 +36,10 @@
#define NB_REGS 9
#endif
+#ifndef TCC_ARM_VERSION
+# define TCC_ARM_VERSION 5
+#endif
+
/* a register can belong to several classes. The classes must be
sorted from more general to more precise (see gv2() code which does
assumptions on it). */
@@ -101,15 +106,6 @@ enum {
are directly pushed on stack. */
//#define FUNC_STRUCT_PARAM_AS_PTR
-#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
-ST_DATA CType float_type, double_type, func_float_type, func_double_type;
-#define func_ldouble_type func_double_type
-#else
-#define func_float_type func_old_type
-#define func_double_type func_old_type
-#define func_ldouble_type func_old_type
-#endif
-
/* pointer size, in bytes */
#define PTR_SIZE 4
@@ -170,14 +166,27 @@ ST_DATA const int reg_classes[NB_REGS] = {
#endif
};
-/* keep in sync with line 104 above */
-#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
-ST_DATA CType float_type, double_type, func_float_type, func_double_type;
-#endif
-
static int func_sub_sp_offset, last_itod_magic;
static int leaffunc;
+#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
+static CType float_type, double_type, func_float_type, func_double_type;
+ST_FUNC void arm_init_types(void)
+{
+ float_type.t = VT_FLOAT;
+ double_type.t = VT_DOUBLE;
+ func_float_type.t = VT_FUNC;
+ func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
+ func_double_type.t = VT_FUNC;
+ func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
+}
+#else
+#define func_float_type func_old_type
+#define func_double_type func_old_type
+#define func_ldouble_type func_old_type
+ST_FUNC void arm_init_types(void) {}
+#endif
+
static int two2mask(int a,int b) {
return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT);
}
@@ -829,11 +838,10 @@ void gfunc_call(int nb_args)
--nb_args;
}
- vpushi(0);
+ vpushi(0), nb_args++;
vtop->type.t = VT_LLONG;
- args_size = 0;
#endif
- ncrn = ncprn = argno = vfp_argno = 0;
+ ncrn = ncprn = argno = vfp_argno = args_size = 0;
/* Assign argument to registers and stack with alignment.
If, considering alignment constraints, enough registers of the correct type
(core or VFP) are free for the current argument, assign them to it, else
@@ -845,7 +853,7 @@ void gfunc_call(int nb_args)
structures in the first zone are moved just after the SValue pointed by
before_vfpreg_hfa. SValue's representing structures in the second zone are
moved just after the SValue pointer by before_stack. */
- for(i = nb_args + 1 ; i-- ;) {
+ for(i = nb_args; i-- ;) {
int j, assigned_vfpreg = 0;
size = type_size(&vtop[-i].type, &align);
switch(vtop[-i].type.t & VT_BTYPE) {
@@ -920,9 +928,11 @@ void gfunc_call(int nb_args)
}
continue;
default:
+#ifdef TCC_ARM_EABI
if (!i) {
break;
}
+#endif
if (ncrn < 4) {
int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG;
@@ -953,7 +963,9 @@ void gfunc_call(int nb_args)
#endif
args_size += (size + 3) & -4;
}
- vtop--;
+#ifdef TCC_ARM_EABI
+ vtop--, nb_args--;
+#endif
args_size = keep = 0;
for(i = 0;i < nb_args; i++) {
vrotb(keep+1);
@@ -1053,10 +1065,12 @@ void gfunc_call(int nb_args)
for(i = 0; i < keep; i++) {
vrotb(keep);
gv(regmask(plan2[i]));
+#ifdef TCC_ARM_HARDFLOAT
/* arg is in s(2d+1): plan2[i]<plan2[i+1] => alignment occured (ex f,d,f) */
if (i < keep - 1 && is_float(vtop->type.t) && (plan2[i] <= plan2[i + 1])) {
o(0xEEF00A40|(vfpr(plan2[i])<<12)|vfpr(plan2[i]));
}
+#endif
}
save_regs(keep); /* save used temporary registers */
keep++;
@@ -1146,6 +1160,7 @@ void gfunc_prolog(CType *func_type)
{
n++;
struct_ret = 1;
+ func_vc = 12; /* Offset from fp of the place to store the result */
}
for(sym2=sym->next;sym2 && (n<4 || nf<16);sym2=sym2->next) {
size = type_size(&sym2->type, &align);
@@ -1159,8 +1174,6 @@ void gfunc_prolog(CType *func_type)
if (n < 4)
n += (size + 3) / 4;
}
- if (struct_ret)
- func_vc = nf * 4;
o(0xE1A0C00D); /* mov ip,sp */
if(variadic)
n=4;
@@ -1179,7 +1192,7 @@ void gfunc_prolog(CType *func_type)
o(0xED2D0A00|nf); /* save s0-s15 on stack if needed */
}
o(0xE92D5800); /* save fp, ip, lr */
- o(0xE28DB00C); /* add fp, sp, #12 */
+ o(0xE1A0B00D); /* mov fp, sp */
func_sub_sp_offset = ind;
o(0xE1A00000); /* nop, leave space for stack adjustment in epilogue */
{
@@ -1193,6 +1206,7 @@ void gfunc_prolog(CType *func_type)
type = &sym->type;
size = type_size(type, &align);
size = (size + 3) >> 2;
+ align = (align + 3) & ~3;
#ifdef TCC_ARM_HARDFLOAT
if (!variadic && (is_float(sym->type.t)
|| is_float_hgen_aggr(&sym->type))) {
@@ -1221,12 +1235,12 @@ from_stack:
addr = (n + nf + sn) * 4;
sn += size;
}
- sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
+ sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr+12);
}
}
last_itod_magic=0;
leaffunc = 1;
- loc = -12;
+ loc = 0;
}
/* generate function epilog */
@@ -1246,13 +1260,13 @@ void gfunc_epilog(void)
}
}
#endif
- o(0xE91BA800); /* restore fp, sp, pc */
+ o(0xE89BA800); /* restore fp, sp, pc */
diff = (-loc + 3) & -4;
#ifdef TCC_ARM_EABI
if(!leaffunc)
- diff = (diff + 7) & -8;
+ diff = ((diff + 11) & -8) - 4;
#endif
- if(diff > 12) {
+ if(diff > 0) {
x=stuff_const(0xE24BD000, diff); /* sub sp,fp,# */
if(x)
*(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = x;
@@ -1564,7 +1578,7 @@ void gen_opf(int op)
x|=0x800000;
break;
default:
- if(op < TOK_ULT && op > TOK_GT) {
+ if(op < TOK_ULT || op > TOK_GT) {
tcc_error("unknown fp op %x!",op);
return;
}
@@ -1837,7 +1851,7 @@ ST_FUNC void gen_cvt_itof1(int t)
#ifdef TCC_ARM_VFP
r2=vfpr(vtop->r=get_reg(RC_FLOAT));
o(0xEE000A10|(r<<12)|(r2<<16)); /* fmsr */
- r2<<=12;
+ r2|=r2<<12;
if(!(vtop->type.t & VT_UNSIGNED))
r2|=0x80; /* fuitoX -> fsituX */
o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/
@@ -1916,7 +1930,7 @@ void gen_cvt_ftoi(int t)
#ifdef TCC_ARM_VFP
r=vfpr(gv(RC_FLOAT));
u=u?0:0x10000;
- o(0xEEBC0A40|(r<<12)|r|T2CPR(r2)); /* ftoXiY */
+ o(0xEEBC0AC0|(r<<12)|r|T2CPR(r2)|u); /* ftoXizY */
r2=intr(vtop->r=get_reg(RC_INT));
o(0xEE100A10|(r<<16)|(r2<<12));
return;
diff --git a/c67-gen.c b/c67-gen.c
index 52d9f3b..b423ba6 100644
--- a/c67-gen.c
+++ b/c67-gen.c
@@ -92,12 +92,6 @@ enum {
#define REG_LRET TREG_C67_A5 /* second word return register (for long long) */
#define REG_FRET TREG_C67_A4 /* float return register */
-#define ALWAYS_ASSERT(x) \
-do {\
- if (!(x))\
- tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
-} while (0)
-
/* defined if function parameters must be evaluated in reverse order */
//#define INVERT_FUNC_PARAMS
@@ -174,11 +168,24 @@ int TranslateStackToReg[NoCallArgsPassedOnStack];
int ParamLocOnStack[NoCallArgsPassedOnStack];
int TotalBytesPushedOnStack;
+#ifndef FALSE
+# define FALSE 0
+# define TRUE 1
+#endif
+
+#undef BOOL
+#define BOOL int
+
+#define ALWAYS_ASSERT(x) \
+do {\
+ if (!(x))\
+ tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
+} while (0)
+
/******************************************************/
static unsigned long func_sub_sp_offset;
static int func_ret_sub;
-
static BOOL C67_invert_test;
static int C67_compare_reg;
@@ -186,7 +193,6 @@ static int C67_compare_reg;
FILE *f = NULL;
#endif
-
void C67_g(int c)
{
int ind1;
@@ -1556,7 +1562,7 @@ void C67_SHR(int r, int v)
void load(int r, SValue * sv)
{
int v, t, ft, fc, fr, size = 0, element;
- BOOL Unsigned = false;
+ BOOL Unsigned = FALSE;
SValue v1;
fr = sv->r;
@@ -2182,34 +2188,34 @@ void gen_opi(int op)
if (op == TOK_LT) {
C67_CMPLT(r, fr, C67_B2);
- C67_invert_test = false;
+ C67_invert_test = FALSE;
} else if (op == TOK_GE) {
C67_CMPLT(r, fr, C67_B2);
- C67_invert_test = true;
+ C67_invert_test = TRUE;
} else if (op == TOK_GT) {
C67_CMPGT(r, fr, C67_B2);
- C67_invert_test = false;
+ C67_invert_test = FALSE;
} else if (op == TOK_LE) {
C67_CMPGT(r, fr, C67_B2);
- C67_invert_test = true;
+ C67_invert_test = TRUE;
} else if (op == TOK_EQ) {
C67_CMPEQ(r, fr, C67_B2);
- C67_invert_test = false;
+ C67_invert_test = FALSE;
} else if (op == TOK_NE) {
C67_CMPEQ(r, fr, C67_B2);
- C67_invert_test = true;
+ C67_invert_test = TRUE;
} else if (op == TOK_ULT) {
C67_CMPLTU(r, fr, C67_B2);
- C67_invert_test = false;
+ C67_invert_test = FALSE;
} else if (op == TOK_UGE) {
C67_CMPLTU(r, fr, C67_B2);
- C67_invert_test = true;
+ C67_invert_test = TRUE;
} else if (op == TOK_UGT) {
C67_CMPGTU(r, fr, C67_B2);
- C67_invert_test = false;
+ C67_invert_test = FALSE;
} else if (op == TOK_ULE) {
C67_CMPGTU(r, fr, C67_B2);
- C67_invert_test = true;
+ C67_invert_test = TRUE;
} else if (op == '+')
C67_ADD(fr, r); // ADD r,fr,r
else if (op == '-')
@@ -2344,42 +2350,42 @@ void gen_opf(int op)
else
C67_CMPLTSP(r, fr, C67_B2);
- C67_invert_test = false;
+ C67_invert_test = FALSE;
} else if (op == TOK_GE) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPLTDP(r, fr, C67_B2);
else
C67_CMPLTSP(r, fr, C67_B2);
- C67_invert_test = true;
+ C67_invert_test = TRUE;
} else if (op == TOK_GT) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPGTDP(r, fr, C67_B2);
else
C67_CMPGTSP(r, fr, C67_B2);
- C67_invert_test = false;
+ C67_invert_test = FALSE;
} else if (op == TOK_LE) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPGTDP(r, fr, C67_B2);
else
C67_CMPGTSP(r, fr, C67_B2);
- C67_invert_test = true;
+ C67_invert_test = TRUE;
} else if (op == TOK_EQ) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPEQDP(r, fr, C67_B2);
else
C67_CMPEQSP(r, fr, C67_B2);
- C67_invert_test = false;
+ C67_invert_test = FALSE;
} else if (op == TOK_NE) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPEQDP(r, fr, C67_B2);
else
C67_CMPEQSP(r, fr, C67_B2);
- C67_invert_test = true;
+ C67_invert_test = TRUE;
} else {
ALWAYS_ASSERT(FALSE);
}
diff --git a/configure b/configure
index 1efe9cc..6a7fae5 100755
--- a/configure
+++ b/configure
@@ -3,21 +3,18 @@
# tcc configure script (c) 2003 Fabrice Bellard
# set temporary file name
-if test ! -z "$TMPDIR" ; then
- TMPDIR1="${TMPDIR}"
-elif test ! -z "$TEMPDIR" ; then
- TMPDIR1="${TEMPDIR}"
-else
- TMPDIR1="/tmp"
-fi
-
+# if test ! -z "$TMPDIR" ; then
+# TMPDIR1="${TMPDIR}"
+# elif test ! -z "$TEMPDIR" ; then
+# TMPDIR1="${TEMPDIR}"
+# else
+# TMPDIR1="/tmp"
+# fi
+#
# bashism: TMPN="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.c"
-TMPN="./conftest-$$"
-TMPC=$TMPN.c
+TMPN="./conftest-$$"
TMPH=$TMPN.h
-TMPO=$TMPN.o
-TMPE=$TMPN
# default parameters
build_cross="no"
@@ -37,12 +34,39 @@ host_cc="gcc"
ar="ar"
strip="strip"
cygwin="no"
-cpu=`uname -m`
-
+gprof="no"
+bigendian="no"
+mingw32="no"
+LIBSUF=".a"
+EXESUF=""
tcc_sysincludepaths=""
tcc_libpaths=""
tcc_crtprefix=""
tcc_elfinterp=""
+tcc_lddir=
+confvars=
+
+cpu=`uname -m`
+
+# OS specific
+targetos=`uname -s`
+case $targetos in
+ MINGW32*) mingw32=yes;;
+ DragonFly) noldl=yes;;
+ OpenBSD) noldl=yes;;
+ *) ;;
+esac
+
+# find source path
+# XXX: we assume an absolute path is given when launching configure,
+# except in './configure' case.
+source_path=${0%configure}
+source_path=${source_path%/}
+source_path_used="yes"
+if test -z "$source_path" -o "$source_path" = "." ; then
+ source_path=`pwd`
+ source_path_used="no"
+fi
case "$cpu" in
i386|i486|i586|i686|i86pc|BePC|i686-AT386)
@@ -51,7 +75,21 @@ case "$cpu" in
x86_64)
cpu="x86-64"
;;
- arm|armv4l|armv5tel|armv5tejl|armv6j|armv7a|armv7l)
+ arm*)
+ case "$cpu" in
+ arm|armv4l)
+ cpuver=4
+ ;;
+ armv5tel|armv5tejl)
+ cpuver=5
+ ;;
+ armv6j|armv6l)
+ cpuver=6
+ ;;
+ armv7a|armv7l)
+ cpuver=7
+ ;;
+ esac
cpu="armv4l"
;;
alpha)
@@ -70,40 +108,9 @@ case "$cpu" in
cpu="unknown"
;;
esac
-gprof="no"
-bigendian="no"
-mingw32="no"
-LIBSUF=".a"
-EXESUF=""
-
-# OS specific
-targetos=`uname -s`
-case $targetos in
-MINGW32*)
-mingw32="yes"
-;;
-DragonFly)
-noldl="yes"
-;;
-OpenBSD)
-noldl="yes"
-;;
-*) ;;
-esac
-
-# find source path
-# XXX: we assume an absolute path is given when launching configure,
-# except in './configure' case.
-source_path=${0%configure}
-source_path=${source_path%/}
-source_path_used="yes"
-if test -z "$source_path" -o "$source_path" = "." ; then
- source_path=`pwd`
- source_path_used="no"
-fi
for opt do
- eval opt=$opt
+ eval opt=\"$opt\"
case "$opt" in
--prefix=*) prefix=`echo $opt | cut -d '=' -f 2`
;;
@@ -179,118 +186,6 @@ if test -z "$CFLAGS"; then
CFLAGS="-Wall -g -O2"
fi
-cc="${cross_prefix}${cc}"
-ar="${cross_prefix}${ar}"
-strip="${cross_prefix}${strip}"
-
-if test "$mingw32" = "yes" ; then
- LIBSUF=".lib"
- EXESUF=".exe"
-fi
-
-if test -z "$cross_prefix" ; then
-
-# ---
-# big/little endian test
-cat > $TMPC << EOF
-#include <inttypes.h>
-int main(int argc, char ** argv){
- volatile uint32_t i=0x01234567;
- return (*((uint8_t*)(&i))) == 0x67;
-}
-EOF
-
-if $cc -o $TMPE $TMPC 2>/dev/null ; then
- $TMPE && bigendian="yes"
-else
- echo big/little test failed
-fi
-
-else
-
-# if cross compiling, cannot launch a program, so make a static guess
-if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" ; then
- bigendian="yes"
-fi
-
-fi
-
-# check gcc version
-cat > $TMPC <<EOF
-int main(void) {
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)
-return 0;
-#else
-#error gcc < 3.2
-#endif
-}
-EOF
-
-gcc_major="2"
-if $cc -o $TMPO $TMPC 2> /dev/null ; then
- gcc_major="3"
-fi
-cat > $TMPC <<EOF
-int main(void) {
-#if __GNUC__ >= 4
-return 0;
-#else
-#error gcc < 4
-#endif
-}
-EOF
-
-if $cc -o $TMPO $TMPC 2> /dev/null ; then
- gcc_major="4"
-fi
-
-if test x"$show_help" = "xyes" ; then
-cat << EOF
-
-Usage: configure [options]
-Options: [defaults in brackets after descriptions]
-
-EOF
-echo "Standard options:"
-echo " --help print this message"
-echo " --prefix=PREFIX install in PREFIX [$prefix]"
-echo " --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX"
-echo " [same as prefix]"
-echo " --bindir=DIR user executables in DIR [EPREFIX/bin]"
-echo " --libdir=DIR object code libraries in DIR [EPREFIX/lib]"
-echo " --tccdir=DIR installation directory [EPREFIX/lib/tcc]"
-echo " --includedir=DIR C header files in DIR [PREFIX/include]"
-echo " --sharedir=DIR documentation root DIR [PREFIX]/share"
-echo " --docdir=DIR documentation in DIR [SHAREDIR/doc/tcc]"
-echo " --mandir=DIR man documentation in DIR [SHAREDIR/man]"
-echo " --infodir=DIR info documentation in DIR [SHAREDIR/info]"
-echo ""
-echo "Advanced options (experts only):"
-echo " --source-path=PATH path of source code [$source_path]"
-echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
-echo " --sysroot=PREFIX prepend PREFIX to library/include paths []"
-echo " --cc=CC use C compiler CC [$cc]"
-echo " --disable-static make libtcc.so instead of libtcc.a"
-echo " --disable-rpath disable use of -rpath with the above"
-echo " --strip-binaries strip symbol tables from resulting binaries"
-echo " --with-libgcc use /lib/libgcc_s.so.1 instead of libtcc.a"
-echo " --enable-mingw32 build windows version on linux with mingw32"
-echo " --enable-cygwin build windows version on windows with cygwin"
-echo " [requires cygwin and mingw32-make]"
-echo " --enable-cross build cross compilers"
-echo " --extra-cflags= extra compiler flags"
-echo " --extra-ldflags= extra linker options"
-echo " --with-selinux use mmap instead of exec mem"
-echo " [requires write access to /tmp]"
-echo " --sysincludepaths=... specify system include paths, colon separated"
-echo " --libpaths=... specify system library paths, colon separated"
-echo " --crtprefix=... specify locations of crt?.o, colon separated"
-echo " --elfinterp=... specify elf interpreter"
-echo ""
-#echo "NOTE: The object files are build at the place where configure is launched"
-exit 1
-fi
-
if test "$mingw32" = "yes" ; then
if test x"$tccdir" = x""; then
tccdir="tcc"
@@ -308,6 +203,8 @@ if test "$mingw32" = "yes" ; then
docdir="${sharedir}/doc"
mandir="${sharedir}/man"
infodir="${sharedir}/info"
+ LIBSUF=".lib"
+ EXESUF=".exe"
else
if test -z "$prefix" ; then
prefix="/usr/local"
@@ -343,64 +240,175 @@ if test x"$includedir" = x""; then
includedir="${prefix}/include"
fi
-echo "Binary directory $bindir"
-echo "TinyCC directory $tccdir"
-echo "Library directory $libdir"
-echo "Include directory $includedir"
-echo "Manual directory $mandir"
-echo "Info directory $infodir"
-echo "Doc directory $docdir"
-echo "Target root prefix $sysroot"
-echo "Source path $source_path"
-echo "C compiler $cc"
-echo "Target OS $targetos"
-echo "CPU $cpu"
-echo "Big Endian $bigendian"
-echo "gprof enabled $gprof"
-echo "cross compilers $build_cross"
-echo "use libgcc $use_libgcc"
+if test x"$show_help" = "xyes" ; then
+cat << EOF
+Usage: configure [options]
+Options: [defaults in brackets after descriptions]
+
+Standard options:
+ --help print this message
+ --prefix=PREFIX install in PREFIX [$prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --tccdir=DIR installation directory [EPREFIX/lib/tcc]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --sharedir=DIR documentation root DIR [PREFIX/share]
+ --docdir=DIR documentation in DIR [SHAREDIR/doc/tcc]
+ --mandir=DIR man documentation in DIR [SHAREDIR/man]
+ --infodir=DIR info documentation in DIR [SHAREDIR/info]
+
+Advanced options (experts only):
+ --source-path=PATH path of source code [$source_path]
+ --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
+ --sysroot=PREFIX prepend PREFIX to library/include paths []
+ --cc=CC use C compiler CC [$cc]
+ --extra-cflags= specify compiler flags [$CFLAGS]
+ --extra-ldflags= specify linker options []
+ --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
+ --enable-mingw32 build windows version on linux with mingw32
+ --enable-cygwin build windows version on windows with cygwin
+ --enable-cross build cross compilers
+ --with-selinux use mmap for exec mem [needs writable /tmp]
+ --sysincludepaths=... specify system include paths, colon separated
+ --libpaths=... specify system library paths, colon separated
+ --crtprefix=... specify locations of crt?.o, colon separated
+ --elfinterp=... specify elf interpreter
+EOF
+#echo "NOTE: The object files are build at the place where configure is launched"
+exit 1
+fi
+
+cc="${cross_prefix}${cc}"
+ar="${cross_prefix}${ar}"
+strip="${cross_prefix}${strip}"
+
+CONFTEST=./conftest$EXESUF
+
+if test -z "$cross_prefix" ; then
+ if ! $cc -o $CONFTEST $source_path/conftest.c 2>/dev/null ; then
+ echo "configure: error: '$cc' failed to compile conftest.c."
+ else
+ bigendian="$($CONFTEST bigendian)"
+ gcc_major="$($CONFTEST version)"
+ gcc_minor="$($CONFTEST minor)"
+ if test "$mingw32" = "no" ; then
+ triplet="$($CONFTEST triplet)"
+ if test -f "/usr/lib/$triplet/crti.o" ; then
+ tcc_lddir="lib/$triplet"
+ multiarch_triplet="$triplet"
+ elif test -f "/usr/lib64/crti.o" ; then
+ tcc_lddir="lib64"
+ fi
+
+ if test "$cpu" = "armv4l" ; then
+ if test "${triplet%eabihf}" != "$triplet" ; then
+ confvars="$confvars arm_eabihf"
+ elif test "${triplet%eabi}" != "$triplet" ; then
+ confvars="$confvars arm_eabi"
+ fi
+ if grep -s -q "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo ; then
+ confvars="$confvars arm_vfp"
+ fi
+ fi
+
+# multiarch_triplet=${libc_dir#*/}
+# multiarch_triplet=${multiarch_triplet%/}
+# tcc_lddir="${libc_dir%%/*}"
+# if test -n "$multiarch_triplet" ; then
+# tcc_lddir="$tcc_lddir/$multiarch_triplet"
+# fi
+
+ if test -f "/lib/ld-uClibc.so.0" ; then
+ confvars="$confvars uClibc"
+ fi
+# gr: maybe for after the release:
+# tcc_elfinterp="$(ldd $CONFTEST | grep 'ld.*.so' | sed 's,\s*\(\S\+\).*,\1,')"
+ # echo "elfinterp $tcc_elfinterp"
+
+ fi
+ fi
+else
+ # if cross compiling, cannot launch a program, so make a static guess
+ case $cpu in
+ powerpc|mips|s390) bigendian=yes;;
+ esac
+fi
+
+cat <<EOF
+Binary directory $bindir
+TinyCC directory $tccdir
+Library directory $libdir
+Include directory $includedir
+Manual directory $mandir
+Info directory $infodir
+Doc directory $docdir
+Target root prefix $sysroot
+Source path $source_path
+C compiler $cc
+Target OS $targetos
+CPU $cpu
+Big Endian $bigendian
+gprof enabled $gprof
+cross compilers $build_cross
+use libgcc $use_libgcc
+EOF
echo "Creating config.mak and config.h"
-echo "# Automatically generated by configure - do not modify" > config.mak
-echo "/* Automatically generated by configure - do not modify */" > $TMPH
+cat >config.mak <<EOF
+# Automatically generated by configure - do not modify
+prefix=$prefix
+bindir=\$(DESTDIR)$bindir
+tccdir=\$(DESTDIR)$tccdir
+libdir=\$(DESTDIR)$libdir
+ln_libdir=$libdir
+includedir=\$(DESTDIR)$includedir
+mandir=\$(DESTDIR)$mandir
+infodir=\$(DESTDIR)$infodir
+docdir=\$(DESTDIR)$docdir
+CC=$cc
+GCC_MAJOR=$gcc_major
+GCC_MINOR=$gcc_minor
+HOST_CC=$host_cc
+AR=$ar
+STRIP=$strip -s -R .comment -R .note
+CFLAGS=$CFLAGS
+LDFLAGS=$LDFLAGS
+LIBSUF=$LIBSUF
+EXESUF=$EXESUF
+EOF
-echo "prefix=$prefix" >> config.mak
-echo "bindir=\$(DESTDIR)$bindir" >> config.mak
-echo "tccdir=\$(DESTDIR)$tccdir" >> config.mak
-echo "libdir=\$(DESTDIR)$libdir" >> config.mak
-echo "ln_libdir=$libdir" >> config.mak
-echo "includedir=\$(DESTDIR)$includedir" >> config.mak
-echo "mandir=\$(DESTDIR)$mandir" >> config.mak
-echo "infodir=\$(DESTDIR)$infodir" >> config.mak
-echo "docdir=\$(DESTDIR)$docdir" >> config.mak
-print_var1()
-{
- echo "#ifndef $1" >> $TMPH
- echo "# define $1 \"$2\"" >> $TMPH
- echo "#endif" >> $TMPH
+print_inc() {
+ if test -n "$2"; then
+ echo "#ifndef $1" >> $TMPH
+ echo "# define $1 \"$2\"" >> $TMPH
+ echo "#endif" >> $TMPH
+ fi
}
-print_var2()
-{
- if test -n "$2"; then print_var1 $1 "$2"; fi
+print_mak() {
+ if test -n "$2"; then
+ echo "NATIVE_DEFINES+=-D$1=\"\\\"$2\\\"\"" >> config.mak
+ fi
}
-print_var2 CONFIG_SYSROOT "$sysroot"
-print_var1 CONFIG_TCCDIR "$tccdir"
-print_var2 CONFIG_TCC_SYSINCLUDEPATHS "$tcc_sysincludepaths"
-print_var2 CONFIG_TCC_LIBPATHS "$tcc_libpaths"
-print_var2 CONFIG_TCC_CRTPREFIX "$tcc_crtprefix"
-print_var2 CONFIG_TCC_ELFINTERP "$tcc_elfinterp"
-
-echo "CC=$cc" >> config.mak
-echo "GCC_MAJOR=$gcc_major" >> config.mak
+
+echo "/* Automatically generated by configure - do not modify */" > $TMPH
+
+print_inc CONFIG_SYSROOT "$sysroot"
+print_inc CONFIG_TCCDIR "$tccdir"
+print_mak CONFIG_TCC_SYSINCLUDEPATHS "$tcc_sysincludepaths"
+print_mak CONFIG_TCC_LIBPATHS "$tcc_libpaths"
+print_mak CONFIG_TCC_CRTPREFIX "$tcc_crtprefix"
+print_mak CONFIG_TCC_ELFINTERP "$tcc_elfinterp"
+print_mak CONFIG_LDDIR "$tcc_lddir"
+print_mak CONFIG_MULTIARCHDIR "$multiarch_triplet"
+
echo "#define GCC_MAJOR $gcc_major" >> $TMPH
-echo "HOST_CC=$host_cc" >> config.mak
-echo "AR=$ar" >> config.mak
-echo "STRIP=$strip -s -R .comment -R .note" >> config.mak
-echo "CFLAGS=$CFLAGS" >> config.mak
-echo "LDFLAGS=$LDFLAGS" >> config.mak
-echo "LIBSUF=$LIBSUF" >> config.mak
-echo "EXESUF=$EXESUF" >> config.mak
+echo "#define GCC_MINOR $gcc_minor" >> $TMPH
if test "$cpu" = "x86" ; then
echo "ARCH=i386" >> config.mak
@@ -411,6 +419,7 @@ elif test "$cpu" = "x86-64" ; then
elif test "$cpu" = "armv4l" ; then
echo "ARCH=arm" >> config.mak
echo "#define HOST_ARM 1" >> $TMPH
+ echo "#define TCC_ARM_VERSION $cpuver" >> $TMPH
elif test "$cpu" = "powerpc" ; then
echo "ARCH=ppc" >> config.mak
echo "#define HOST_PPC 1" >> $TMPH
@@ -427,7 +436,12 @@ else
echo "Unsupported CPU"
exit 1
fi
+
echo "TARGETOS=$targetos" >> config.mak
+
+for v in $confvars ; do
+ echo "CONFIG_$v=yes" >> config.mak
+done
if test "$noldl" = "yes" ; then
echo "CONFIG_NOLDL=yes" >> config.mak
fi
@@ -437,7 +451,7 @@ if test "$mingw32" = "yes" ; then
fi
if test "$cygwin" = "yes" ; then
echo "#ifndef _WIN32" >> $TMPH
- echo "#define _WIN32" >> $TMPH
+ echo "# define _WIN32" >> $TMPH
echo "#endif" >> $TMPH
echo "AR=ar" >> config.mak
fi
@@ -469,23 +483,22 @@ if test "$have_selinux" = "yes" ; then
echo "#define HAVE_SELINUX" >> $TMPH
echo "HAVE_SELINUX=yes" >> config.mak
fi
+
version=`head $source_path/VERSION`
echo "VERSION=$version" >>config.mak
echo "#define TCC_VERSION \"$version\"" >> $TMPH
echo "@set VERSION $version" > config.texi
+echo "SRC_PATH=$source_path" >>config.mak
-# build tree in object directory if source path is different from current one
if test "$source_path_used" = "yes" ; then
- DIRS="tests"
- FILES="Makefile tests/Makefile"
- for dir in $DIRS ; do
- mkdir -p $dir
- done
- for f in $FILES ; do
- ln -sf $source_path/$f $f
- done
+ case $source_path in
+ /*) echo "top_srcdir=$source_path";;
+ *) echo "top_srcdir=\$(TOP)/$source_path";;
+ esac >>config.mak
+else
+ echo 'top_srcdir=$(TOP)' >>config.mak
fi
-echo "SRC_PATH=$source_path" >> config.mak
+echo 'top_builddir=$(TOP)' >>config.mak
diff $TMPH config.h >/dev/null 2>&1
if test $? -ne 0 ; then
@@ -494,4 +507,34 @@ else
echo "config.h is unchanged"
fi
-rm -f $TMPN*
+rm -f $TMPN* $CONFTEST
+
+# ---------------------------------------------------------------------------
+# build tree in object directory if source path is different from current one
+
+fn_makelink()
+{
+ tgt=$1/$2
+ case $2 in
+ */*) dn=${2%/*}
+ test -d $dn || mkdir -p $dn
+ case $1 in
+ /*) ;;
+ *) while test $dn ; do
+ tgt=../$tgt; dn=${dn#${dn%%/*}}; dn=${dn#/}
+ done
+ ;;
+ esac
+ ;;
+ esac
+ ln -sfn $tgt $2
+}
+
+if test "$source_path_used" = "yes" ; then
+ FILES="Makefile lib/Makefile tests/Makefile tests/tests2/Makefile"
+ for f in $FILES ; do
+ fn_makelink $source_path $f
+ done
+fi
+
+# ---------------------------------------------------------------------------
diff --git a/conftest.c b/conftest.c
new file mode 100644
index 0000000..53c181c
--- /dev/null
+++ b/conftest.c
@@ -0,0 +1,71 @@
+#include <stdio.h>
+
+/* Define architecture */
+#if defined(__i386__)
+# define TRIPLET_ARCH "i386"
+#elif defined(__x86_64__)
+# define TRIPLET_ARCH "x86_64"
+#elif defined(__arm__)
+# define TRIPLET_ARCH "arm"
+#else
+# define TRIPLET_ARCH "unknown"
+#endif
+
+/* Define OS */
+#if defined (__linux__)
+# define TRIPLET_OS "linux"
+#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
+# define TRIPLET_OS "kfreebsd"
+#elif !defined (__GNU__)
+# define TRIPLET_OS "unknown"
+#endif
+
+/* Define calling convention and ABI */
+#if defined (__ARM_EABI__)
+# if defined (__ARM_PCS_VFP)
+# define TRIPLET_ABI "gnueabihf"
+# else
+# define TRIPLET_ABI "gnueabi"
+# endif
+#else
+# define TRIPLET_ABI "gnu"
+#endif
+
+#ifdef __GNU__
+# define TRIPLET TRIPLET_ARCH "-" TRIPLET_ABI
+#else
+# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI
+#endif
+
+int main(int argc, char *argv[])
+{
+ switch(argc == 2 ? argv[1][0] : 0) {
+ case 'b':
+ {
+ volatile unsigned foo = 0x01234567;
+ puts(*(unsigned char*)&foo == 0x67 ? "no" : "yes");
+ break;
+ }
+#ifdef __GNUC__
+ case 'm':
+ printf("%d\n", __GNUC_MINOR__);
+ break;
+ case 'v':
+ printf("%d\n", __GNUC__);
+ break;
+#else
+ case 'm':
+ case 'v':
+ puts("0");
+ break;
+#endif
+ case 't':
+ puts(TRIPLET);
+ break;
+ case -1:
+ /* to test -Wno-unused-result */
+ fread(NULL, 1, 1, NULL);
+ break;
+ }
+ return 0;
+}
diff --git a/i386-gen.c b/i386-gen.c
index 6635559..c3f03c7 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -260,8 +260,13 @@ ST_FUNC void load(int r, SValue *sv)
o(0xb8 + r); /* mov $xx, r */
gen_addr32(fr, sv->sym, fc);
} else if (v == VT_LOCAL) {
- o(0x8d); /* lea xxx(%ebp), r */
- gen_modrm(r, VT_LOCAL, sv->sym, fc);
+ if (fc) {
+ o(0x8d); /* lea xxx(%ebp), r */
+ gen_modrm(r, VT_LOCAL, sv->sym, fc);
+ } else {
+ o(0x89);
+ o(0xe8 + r); /* mov %ebp, r */
+ }
} else if (v == VT_CMP) {
oad(0xb8 + r, 0); /* mov $0, r */
o(0x0f); /* setxx %br */
diff --git a/include/stddef.h b/include/stddef.h
index c5dd13c..fbc61fc 100644
--- a/include/stddef.h
+++ b/include/stddef.h
@@ -20,7 +20,7 @@ typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
#endif
-#define NULL ((void *)0)
+#define NULL ((void*)0)
#define offsetof(type, field) ((size_t)&((type *)0)->field)
void *alloca(size_t size);
diff --git a/lib/Makefile b/lib/Makefile
index d7d2c3f..dfac0f8 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -3,7 +3,8 @@
#
TOP = ..
-include $(TOP)/config.mak
+include $(TOP)/Makefile
+VPATH = $(top_srcdir)/lib $(top_srcdir)/win32/lib
ifndef TARGET
ifdef CONFIG_WIN64
@@ -14,19 +15,20 @@ ifndef TARGET
else
ifeq ($(ARCH),i386)
TARGET = i386
- ifneq ($(TARGETOS),Darwin)
- XCC = gcc -O2 -m32
- endif
+ ifneq ($(TARGETOS),Darwin)
+ XCC = $(CC)
+ endif
else
ifeq ($(ARCH),x86-64)
TARGET = x86_64
- ifneq ($(TARGETOS),Darwin)
- XCC = gcc -O2 -m64
- endif
+ ifneq ($(TARGETOS),Darwin)
+ XCC = $(CC)
+ endif
endif
endif
endif
endif
+ BCHECK_O = bcheck.o
endif
DIR = $(TARGET)
@@ -37,40 +39,32 @@ cross : $(DIR)/libtcc1.a
native : TCC = $(TOP)/tcc$(EXESUF)
cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)
-I386_O = libtcc1.o alloca86.o alloca86-bt.o
+I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)
X86_64_O = libtcc1.o alloca86_64.o
-WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o bcheck.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
-VPATH = $(TOP)/lib $(TOP)/win32/lib
-
ifeq "$(TARGET)" "i386-win32"
OBJ = $(addprefix $(DIR)/,$(WIN32_O))
TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE
- XCC = $(TCC) -B$(TOP)/win32 -I$(TOP)/include
+ XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include
XAR = $(DIR)/tiny_libmaker$(EXESUF)
else
ifeq "$(TARGET)" "x86_64-win32"
OBJ = $(addprefix $(DIR)/,$(WIN64_O))
TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE
- XCC = $(TCC) -B$(TOP)/win32 -I$(TOP)/include
+ XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include
XAR = $(DIR)/tiny_libmaker$(EXESUF)
else
ifeq "$(TARGET)" "i386"
OBJ = $(addprefix $(DIR)/,$(I386_O))
TGT = -DTCC_TARGET_I386
- XCC ?= $(TCC) -B$(TOP) -m32 -D_ANSI_SOURCE
- ifeq ($(TARGETOS),Darwin)
- XAR = $(DIR)/tiny_libmaker$(EXESUF)
- endif
+ XCC ?= $(TCC) -B$(TOP)
else
ifeq "$(TARGET)" "x86_64"
OBJ = $(addprefix $(DIR)/,$(X86_64_O))
TGT = -DTCC_TARGET_X86_64
- XCC ?= $(TCC) -B$(TOP) -m64 -D_ANSI_SOURCE
- ifeq ($(TARGETOS),Darwin)
- XAR = $(DIR)/tiny_libmaker$(EXESUF)
- endif
+ XCC ?= $(TCC) -B$(TOP)
else
$(error libtcc1.a not supported on target '$(TARGET)')
endif
@@ -78,6 +72,14 @@ endif
endif
endif
+XFLAGS = $(CPPFLAGS) $(CFLAGS) $(TGT)
+
+ifeq ($(TARGETOS),Darwin)
+ XAR = $(DIR)/tiny_libmaker$(EXESUF)
+ XFLAGS += -D_ANSI_SOURCE
+ BCHECK_O =
+endif
+
ifdef XAR
AR = $(XAR)
endif
@@ -85,11 +87,11 @@ endif
$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ) $(XAR)
$(AR) rcs $@ $(OBJ)
$(DIR)/%.o : %.c
- $(XCC) -c $< -o $@ $(TGT)
+ $(XCC) -c $< -o $@ $(XFLAGS)
$(DIR)/%.o : %.S
- $(XCC) -c $< -o $@ $(TGT)
+ $(XCC) -c $< -o $@ $(XFLAGS)
$(DIR)/%$(EXESUF) : $(TOP)/win32/tools/%.c
- $(CC) -Os -s -w -o $@ $< $(TGT)
+ $(CC) -o $@ $< $(XFLAGS) $(LDFLAGS)
$(OBJ) $(XAR) : $(DIR)/exists
$(DIR)/exists :
diff --git a/lib/bcheck.c b/lib/bcheck.c
index 48d7606..54124b9 100644
--- a/lib/bcheck.c
+++ b/lib/bcheck.c
@@ -25,6 +25,9 @@
&& !defined(__DragonFly__) && !defined(__OpenBSD__)
#include <malloc.h>
#endif
+#if !defined(_WIN32)
+#include <unistd.h>
+#endif
//#define BOUND_DEBUG
@@ -38,7 +41,8 @@
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
|| defined(__DragonFly__) || defined(__dietlibc__) \
- || defined(__UCLIBC__) || defined(__OpenBSD__) || defined(_WIN32)
+ || defined(__UCLIBC__) || defined(__OpenBSD__) \
+ || defined(_WIN32) || defined(TCC_UCLIBC)
#warning Bound checking does not support malloc (etc.) in this environment.
#undef CONFIG_TCC_MALLOC_HOOKS
#undef HAVE_MEMALIGN
@@ -94,9 +98,6 @@ static void *saved_realloc_hook;
static void *saved_memalign_hook;
#endif
-/* linker definitions */
-extern char _end;
-
/* TCC definitions */
extern char __bounds_start; /* start of static bounds table */
/* error message, just for TCC */
@@ -208,25 +209,11 @@ BOUND_PTR_INDIR(8)
BOUND_PTR_INDIR(12)
BOUND_PTR_INDIR(16)
-#ifdef __i386__
/* return the frame pointer of the caller */
#define GET_CALLER_FP(fp)\
{\
- unsigned long *fp1;\
- __asm__ __volatile__ ("movl %%ebp,%0" :"=g" (fp1));\
- fp = fp1[0];\
-}
-#elif defined(__x86_64__)
-/* TCC always creates %rbp frames also on x86_64, so use them. */
-#define GET_CALLER_FP(fp)\
-{\
- unsigned long *fp1;\
- __asm__ __volatile__ ("movq %%rbp,%0" :"=g" (fp1));\
- fp = fp1[0];\
+ fp = (unsigned long)__builtin_frame_address(1);\
}
-#else
-#error put code to extract the calling frame pointer
-#endif
/* called when entering a function to add all the local regions */
void FASTCALL __bound_local_new(void *p1)
@@ -391,11 +378,34 @@ void __bound_init(void)
size = BOUND_T23_SIZE;
mark_invalid(start, size);
-#if !defined(__TINYC__) && defined(CONFIG_TCC_MALLOC_HOOKS)
+#if defined(CONFIG_TCC_MALLOC_HOOKS)
/* malloc zone is also marked invalid. can only use that with
- hooks because all libs should use the same malloc. The solution
- would be to build a new malloc for tcc. */
- start = (unsigned long)&_end;
+ * hooks because all libs should use the same malloc. The solution
+ * would be to build a new malloc for tcc.
+ *
+ * usually heap (= malloc zone) comes right after bss, i.e. after _end, but
+ * not always - either if we are running from under `tcc -b -run`, or if
+ * address space randomization is turned on(a), heap start will be separated
+ * from bss end.
+ *
+ * So sbrk(0) will be a good approximation for start_brk:
+ *
+ * - if we are a separately compiled program, __bound_init() runs early,
+ * and sbrk(0) should be equal or very near to start_brk(b) (in case other
+ * constructors malloc something), or
+ *
+ * - if we are running from under `tcc -b -run`, sbrk(0) will return
+ * start of heap portion which is under this program control, and not
+ * mark as invalid earlier allocated memory.
+ *
+ *
+ * (a) /proc/sys/kernel/randomize_va_space = 2, on Linux;
+ * usually turned on by default.
+ *
+ * (b) on Linux >= v3.3, the alternative is to read
+ * start_brk from /proc/self/stat
+ */
+ start = (unsigned long)sbrk(0);
size = 128 * 0x100000;
mark_invalid(start, size);
#endif
@@ -606,7 +616,7 @@ int __bound_delete_region(void *p)
}
}
/* last page */
- page = get_page(t2_end);
+ page = get_page(t1_end);
e2 = (BoundEntry *)((char *)page + t2_end);
for(e=page;e<e2;e++) {
e->start = 0;
@@ -638,6 +648,9 @@ static unsigned long get_region_size(void *p)
/* patched memory functions */
+/* force compiler to perform stores coded up to this point */
+#define barrier() __asm__ __volatile__ ("": : : "memory")
+
static void install_malloc_hooks(void)
{
#ifdef CONFIG_TCC_MALLOC_HOOKS
@@ -649,6 +662,8 @@ static void install_malloc_hooks(void)
__free_hook = __bound_free;
__realloc_hook = __bound_realloc;
__memalign_hook = __bound_memalign;
+
+ barrier();
#endif
}
@@ -659,6 +674,8 @@ static void restore_malloc_hooks(void)
__free_hook = saved_free_hook;
__realloc_hook = saved_realloc_hook;
__memalign_hook = saved_memalign_hook;
+
+ barrier();
#endif
}
diff --git a/lib/libtcc1.c b/lib/libtcc1.c
index 946c6c8..dacee28 100644
--- a/lib/libtcc1.c
+++ b/lib/libtcc1.c
@@ -162,7 +162,7 @@ static UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
n0 = nn.s.low;
n1 = nn.s.high;
-#if !UDIV_NEEDS_NORMALIZATION
+#if !defined(UDIV_NEEDS_NORMALIZATION)
if (d1 == 0)
{
if (d0 > n1)
@@ -609,8 +609,11 @@ unsigned long long __fixunsxfdi (long double a1)
/* helper functions for stdarg.h */
-#include <stdio.h>
#include <stdlib.h>
+#ifndef __TINYC__
+/* gives "incompatible types for redefinition of __va_arg" below */
+#include <stdio.h>
+#endif
enum __va_arg_type {
__va_gen_reg, __va_float_reg, __va_stack
@@ -665,7 +668,9 @@ void *__va_arg(struct __va_list_struct *ap,
return ap->overflow_arg_area - size;
default:
+#ifndef __TINYC__
fprintf(stderr, "unknown ABI type for __va_arg\n");
+#endif
abort();
}
}
diff --git a/libtcc.c b/libtcc.c
index 6c04caa..af0fb7f 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -34,10 +34,6 @@ ST_DATA struct TCCState *tcc_state;
/********************************************************/
-#ifndef _WIN32
-#include <limits.h>
-#endif
-
#ifdef ONE_SOURCE
#include "tccpp.c"
#include "tccgen.c"
@@ -109,12 +105,14 @@ static void tcc_set_lib_path_w32(TCCState *s)
tcc_set_lib_path(s, path);
}
+#ifdef TCC_TARGET_PE
static void tcc_add_systemdir(TCCState *s)
{
char buf[1000];
GetSystemDirectory(buf, sizeof buf);
tcc_add_library_path(s, normalize_slashes(buf));
}
+#endif
#ifndef CONFIG_TCC_STATIC
void dlclose(void *p)
@@ -199,8 +197,8 @@ PUB_FUNC char *tcc_fileextension (const char *name)
#undef realloc
#ifdef MEM_DEBUG
-int mem_cur_size;
-int mem_max_size;
+ST_DATA int mem_cur_size;
+ST_DATA int mem_max_size;
unsigned malloc_usable_size(void*);
#endif
@@ -263,7 +261,7 @@ PUB_FUNC char *tcc_strdup(const char *str)
PUB_FUNC void tcc_memstats(void)
{
#ifdef MEM_DEBUG
- printf("memory in use: %d\n", mem_cur_size);
+ printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
#endif
}
@@ -274,7 +272,7 @@ PUB_FUNC void tcc_memstats(void)
/********************************************************/
/* dynarrays */
-PUB_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data)
+ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data)
{
int nb, nb_alloc;
void **pp;
@@ -294,7 +292,7 @@ PUB_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data)
*nb_ptr = nb;
}
-PUB_FUNC void dynarray_reset(void *pp, int *n)
+ST_FUNC void dynarray_reset(void *pp, int *n)
{
void **p;
for (p = *(void***)pp; *n; ++p, --*n)
@@ -322,30 +320,7 @@ static void tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char
}
}
cstr_ccat(&str, '\0');
-#ifndef _WIN32
- {
- int i, do_include;
- char tmp[PATH_MAX];
-
- if (realpath(str.data, tmp)) {
- str.size = 0;
- cstr_cat(&str, tmp);
- cstr_ccat(&str, '\0');
- }
-
- do_include = 1;
- for (i = 0; i < *p_nb_ary && do_include; i++) {
- do_include = do_include &&
- strcmp((char*)str.data, (char*)(*p_ary)[i]);
- }
-
- if (do_include) {
- dynarray_add(p_ary, p_nb_ary, str.data);
- }
- }
-#else
dynarray_add(p_ary, p_nb_ary, str.data);
-#endif
in = p+1;
} while (*p);
}
@@ -450,7 +425,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,
- uplong value, unsigned long size,
+ addr_t value, unsigned long size,
int can_add_underscore)
{
int sym_type, sym_bind, sh_num, info, other;
@@ -554,7 +529,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
}
ST_FUNC void put_extern_sym(Sym *sym, Section *section,
- uplong value, unsigned long size)
+ addr_t value, unsigned long size)
{
put_extern_sym2(sym, section, value, size, 1);
}
@@ -592,23 +567,24 @@ static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
{
char buf[2048];
- BufferedFile **f;
+ BufferedFile **pf, *f;
buf[0] = '\0';
- if (file) {
- for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
- strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
- (*f)->filename, (*f)->line_num);
- if (file->line_num > 0) {
- strcat_printf(buf, sizeof(buf),
- "%s:%d: ", file->filename, file->line_num);
+ /* use upper file if inline ":asm:" or token ":paste:" */
+ for (f = file; f && f->filename[0] == ':'; f = f->prev);
+ if (f) {
+ for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++)
+ strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
+ (*pf)->filename, (*pf)->line_num);
+ if (f->line_num > 0) {
+ strcat_printf(buf, sizeof(buf), "%s:%d: ",
+ f->filename, f->line_num);
} else {
- strcat_printf(buf, sizeof(buf),
- "%s: ", file->filename);
+ strcat_printf(buf, sizeof(buf), "%s: ",
+ f->filename);
}
} else {
- strcat_printf(buf, sizeof(buf),
- "tcc: ");
+ strcat_printf(buf, sizeof(buf), "tcc: ");
}
if (is_warning)
strcat_printf(buf, sizeof(buf), "warning: ");
@@ -780,15 +756,8 @@ 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);
-
-#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
- float_type.t = VT_FLOAT;
- double_type.t = VT_DOUBLE;
-
- func_float_type.t = VT_FUNC;
- func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
- func_double_type.t = VT_FUNC;
- func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
+#ifdef TCC_TARGET_ARM
+ arm_init_types();
#endif
#if 0
@@ -892,10 +861,10 @@ LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym)
define_undef(s);
}
+/* cleanup all static data used during compilation */
static void tcc_cleanup(void)
{
int i, n;
-
if (NULL == tcc_state)
return;
tcc_state = NULL;
@@ -947,18 +916,23 @@ LIBTCCAPI TCCState *tcc_new(void)
define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
+ /* define __TINYC__ 92X */
+ sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c);
+ sprintf(buffer, "%d", a*10000 + b*100 + c);
+ tcc_define_symbol(s, "__TINYC__", buffer);
+
/* standard defines */
tcc_define_symbol(s, "__STDC__", NULL);
tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
+
+ /* target defines */
#if defined(TCC_TARGET_I386)
tcc_define_symbol(s, "__i386__", NULL);
tcc_define_symbol(s, "__i386", NULL);
tcc_define_symbol(s, "i386", NULL);
-#endif
-#if defined(TCC_TARGET_X86_64)
+#elif defined(TCC_TARGET_X86_64)
tcc_define_symbol(s, "__x86_64__", NULL);
-#endif
-#if defined(TCC_TARGET_ARM)
+#elif defined(TCC_TARGET_ARM)
tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
tcc_define_symbol(s, "__arm_elf__", NULL);
tcc_define_symbol(s, "__arm_elf", NULL);
@@ -968,34 +942,31 @@ LIBTCCAPI TCCState *tcc_new(void)
tcc_define_symbol(s, "arm", NULL);
tcc_define_symbol(s, "__APCS_32__", NULL);
#endif
+
#ifdef TCC_TARGET_PE
tcc_define_symbol(s, "_WIN32", NULL);
-#ifdef TCC_TARGET_X86_64
+# ifdef TCC_TARGET_X86_64
tcc_define_symbol(s, "_WIN64", NULL);
-#endif
+# endif
#else
tcc_define_symbol(s, "__unix__", NULL);
tcc_define_symbol(s, "__unix", NULL);
tcc_define_symbol(s, "unix", NULL);
-#if defined(__FreeBSD__)
-#define str(s) #s
- tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));
-#undef str
-#endif
-#if defined(__FreeBSD_kernel__)
- tcc_define_symbol(s, "__FreeBSD_kernel__", NULL);
-#endif
-#if defined(__linux)
+# if defined(__linux)
tcc_define_symbol(s, "__linux__", NULL);
tcc_define_symbol(s, "__linux", NULL);
+# endif
+# if defined(__FreeBSD__)
+# define str(s) #s
+ tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));
+# undef str
+# endif
+# if defined(__FreeBSD_kernel__)
+ tcc_define_symbol(s, "__FreeBSD_kernel__", NULL);
+# endif
#endif
-#endif
- /* tiny C specific defines */
- sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c);
- sprintf(buffer, "%d", a*10000 + b*100 + c);
- tcc_define_symbol(s, "__TINYC__", buffer);
- /* tiny C & gcc defines */
+ /* TinyCC & gcc defines */
#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long long");
tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long long");
@@ -1010,11 +981,10 @@ LIBTCCAPI TCCState *tcc_new(void)
tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
#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");
-
-#ifndef TCC_TARGET_PE
/* default library paths */
tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
/* paths for crt objects */
@@ -1042,16 +1012,15 @@ LIBTCCAPI TCCState *tcc_new(void)
".dynhashtab", SHF_PRIVATE);
s->alacarte_link = 1;
s->nocommon = 1;
+ s->section_align = ELF_PAGE_SIZE;
#ifdef CHAR_IS_UNSIGNED
s->char_is_unsigned = 1;
#endif
/* enable this if you want symbols with leading underscore on windows: */
-#if defined(TCC_TARGET_PE) && 0
+#if 0 //def TCC_TARGET_PE
s->leading_underscore = 1;
#endif
- if (s->section_align == 0)
- s->section_align = ELF_PAGE_SIZE;
#ifdef TCC_TARGET_I386
s->seg_size = 32;
#endif
@@ -1092,16 +1061,25 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
- dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
-
tcc_free(s1->tcc_lib_path);
+ tcc_free(s1->soname);
+ tcc_free(s1->rpath);
+ tcc_free(s1->init_symbol);
+ tcc_free(s1->fini_symbol);
+ tcc_free(s1->outfile);
+ tcc_free(s1->deps_outfile);
+ dynarray_reset(&s1->files, &s1->nb_files);
+ dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
-#ifdef HAVE_SELINUX
+#ifdef TCC_IS_NATIVE
+# ifdef HAVE_SELINUX
munmap (s1->write_mem, s1->mem_size);
munmap (s1->runtime_mem, s1->mem_size);
-#else
+# else
tcc_free(s1->runtime_mem);
+# endif
#endif
+
tcc_free(s1);
}
@@ -1196,9 +1174,11 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
#ifndef TCC_TARGET_PE
if (ehdr.e_type == ET_DYN) {
if (s1->output_type == TCC_OUTPUT_MEMORY) {
+#ifdef TCC_IS_NATIVE
void *h;
h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
if (h)
+#endif
ret = 0;
} else {
ret = tcc_load_dll(s1, fd, filename,
@@ -1266,7 +1246,6 @@ static int tcc_add_library_internal(TCCState *s, const char *fmt,
return -1;
}
-#ifndef TCC_TARGET_PE
/* find and load a dll. Return non zero if not found */
/* XXX: add '-rpath' option support ? */
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
@@ -1274,7 +1253,6 @@ ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
return tcc_add_library_internal(s, "%s/%s", filename, flags,
s->library_paths, s->nb_library_paths);
}
-#endif
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename)
{
@@ -1306,11 +1284,15 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val)
{
#ifdef TCC_TARGET_PE
- pe_putimport(s, 0, name, val);
+ /* On x86_64 'val' might not be reachable with a 32bit offset.
+ So it is handled here as if it were in a DLL. */
+ pe_putimport(s, 0, name, (uintptr_t)val);
#else
- add_elf_sym(symtab_section, (uplong)val, 0,
- ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
- SHN_ABS, name);
+ /* 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);
#endif
return 0;
}
@@ -1371,6 +1353,12 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
return 0;
}
+LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path)
+{
+ tcc_free(s->tcc_lib_path);
+ s->tcc_lib_path = tcc_strdup(path);
+}
+
#define WD_ALL 0x0001 /* warning is activated when using -Wall */
#define FD_INVERT 0x0002 /* invert value before storing */
@@ -1412,14 +1400,8 @@ ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
return 0;
}
-/* enable debug */
-LIBTCCAPI void tcc_enable_debug(TCCState *s)
-{
- s->do_debug = 1;
-}
-
/* set/reset a warning */
-LIBTCCAPI int tcc_set_warning(TCCState *s, const char *warning_name, int value)
+static int tcc_set_warning(TCCState *s, const char *warning_name, int value)
{
int i;
const FlagDef *p;
@@ -1444,30 +1426,28 @@ static const FlagDef flag_defs[] = {
};
/* set/reset a flag */
-PUB_FUNC int tcc_set_flag(TCCState *s, const char *flag_name, int value)
+static int tcc_set_flag(TCCState *s, const char *flag_name, int value)
{
return set_flag(s, flag_defs, countof(flag_defs),
flag_name, value);
}
-static int strstart(const char *str, const char *val, char **ptr)
+static int strstart(const char *val, const char **str)
{
const char *p, *q;
- p = str;
+ p = *str;
q = val;
- while (*q != '\0') {
+ while (*q) {
if (*p != *q)
return 0;
p++;
q++;
}
- if (ptr)
- *ptr = (char *) p;
+ *str = p;
return 1;
}
-
/* Like strstart, but automatically takes into account that ld options can
*
* - start with double or single dash (e.g. '--soname' or '-soname')
@@ -1476,7 +1456,7 @@ static int strstart(const char *str, const char *val, char **ptr)
*
* you provide `val` always in 'option[=]' form (no leading -)
*/
-static int link_option(const char *str, const char *val, char **ptr)
+static int link_option(const char *str, const char *val, const char **ptr)
{
const char *p, *q;
@@ -1506,64 +1486,72 @@ static int link_option(const char *str, const char *val, char **ptr)
}
if (ptr)
- *ptr = (char *) p;
+ *ptr = p;
return 1;
}
+static const char *skip_linker_arg(const char **str)
+{
+ const char *s1 = *str;
+ const char *s2 = strchr(s1, ',');
+ *str = s2 ? s2++ : (s2 = s1 + strlen(s1));
+ return s2;
+}
-/* set linker options */
-PUB_FUNC const char * tcc_set_linker(TCCState *s, char *option, int multi)
+static char *copy_linker_arg(const char *p)
{
- char *p = option;
- char *end;
+ const char *q = p;
+ skip_linker_arg(&q);
+ return pstrncpy(tcc_malloc(q - p + 1), p, q - p);
+}
+/* set linker options */
+static int tcc_set_linker(TCCState *s, const char *option)
+{
while (option && *option) {
- end = NULL;
+
+ const char *p = option;
+ char *end = NULL;
+ int ignoring = 0;
+
if (link_option(option, "Bsymbolic", &p)) {
- s->symbolic = TRUE;
+ s->symbolic = 1;
} else if (link_option(option, "nostdlib", &p)) {
- s->nostdlib = TRUE;
+ s->nostdlib = 1;
} else if (link_option(option, "fini=", &p)) {
- s->fini_symbol = p;
- if (s->warn_unsupported)
- tcc_warning("ignoring -fini %s", p);
- } else if (link_option(option, "image-base=", &p)) {
+ s->fini_symbol = copy_linker_arg(p);
+ ignoring = 1;
+ } else if (link_option(option, "image-base=", &p)
+ || link_option(option, "Ttext=", &p)) {
s->text_addr = strtoull(p, &end, 16);
s->has_text_addr = 1;
} else if (link_option(option, "init=", &p)) {
- s->init_symbol = p;
- if (s->warn_unsupported)
- tcc_warning("ignoring -init %s", p);
+ s->init_symbol = copy_linker_arg(p);
+ ignoring = 1;
} else if (link_option(option, "oformat=", &p)) {
#if defined(TCC_TARGET_PE)
- if (strstart(p, "pe-", NULL)) {
-#else
-#if defined(TCC_TARGET_X86_64)
- if (strstart(p, "elf64-", NULL)) {
+ if (strstart("pe-", &p)) {
+#elif defined(TCC_TARGET_X86_64)
+ if (strstart("elf64-", &p)) {
#else
- if (strstart(p, "elf32-", NULL)) {
-#endif
+ if (strstart("elf32-", &p)) {
#endif
s->output_format = TCC_OUTPUT_FORMAT_ELF;
} else if (!strcmp(p, "binary")) {
s->output_format = TCC_OUTPUT_FORMAT_BINARY;
- } else
#ifdef TCC_TARGET_COFF
- if (!strcmp(p, "coff")) {
+ } else if (!strcmp(p, "coff")) {
s->output_format = TCC_OUTPUT_FORMAT_COFF;
- } else
#endif
- {
- return p;
- }
+ } else
+ goto err;
} else if (link_option(option, "rpath=", &p)) {
- s->rpath = p;
+ s->rpath = copy_linker_arg(p);
} else if (link_option(option, "section-alignment=", &p)) {
s->section_align = strtoul(p, &end, 16);
} else if (link_option(option, "soname=", &p)) {
- s->soname = p;
- multi = 0;
+ s->soname = copy_linker_arg(p);
#ifdef TCC_TARGET_PE
} else if (link_option(option, "file-alignment=", &p)) {
s->pe_file_align = strtoul(p, &end, 16);
@@ -1591,32 +1579,351 @@ PUB_FUNC const char * tcc_set_linker(TCCState *s, char *option, int multi)
if (!strcmp(p, "wince")) {
s->pe_subsystem = 9;
#endif
- } else {
- return p;
- }
+ } else
+ goto err;
#endif
+ } else
+ goto err;
+
+ if (ignoring && s->warn_unsupported) err: {
+ char buf[100], *e;
+ pstrcpy(buf, sizeof buf, e = copy_linker_arg(option)), tcc_free(e);
+ if (ignoring)
+ tcc_warning("unsupported linker option '%s'", buf);
+ else
+ tcc_error("unsupported linker option '%s'", buf);
+ }
+ option = skip_linker_arg(&p);
+ }
+ return 0;
+}
- } else if (link_option(option, "Ttext=", &p)) {
- s->text_addr = strtoull(p, &end, 16);
- s->has_text_addr = 1;
- } else {
- char *comma_ptr = strchr(option, ',');
- if (comma_ptr)
- *comma_ptr = '\0';
- return option;
+typedef struct TCCOption {
+ const char *name;
+ uint16_t index;
+ uint16_t flags;
+} TCCOption;
+
+enum {
+ TCC_OPTION_HELP,
+ TCC_OPTION_I,
+ TCC_OPTION_D,
+ TCC_OPTION_U,
+ TCC_OPTION_L,
+ TCC_OPTION_B,
+ TCC_OPTION_l,
+ TCC_OPTION_bench,
+ TCC_OPTION_bt,
+ TCC_OPTION_b,
+ TCC_OPTION_g,
+ TCC_OPTION_c,
+ TCC_OPTION_static,
+ TCC_OPTION_shared,
+ TCC_OPTION_soname,
+ TCC_OPTION_o,
+ TCC_OPTION_r,
+ TCC_OPTION_s,
+ TCC_OPTION_Wl,
+ TCC_OPTION_W,
+ TCC_OPTION_O,
+ TCC_OPTION_m,
+ TCC_OPTION_f,
+ TCC_OPTION_isystem,
+ TCC_OPTION_nostdinc,
+ TCC_OPTION_nostdlib,
+ TCC_OPTION_print_search_dirs,
+ TCC_OPTION_rdynamic,
+ TCC_OPTION_pedantic,
+ TCC_OPTION_pthread,
+ TCC_OPTION_run,
+ TCC_OPTION_v,
+ TCC_OPTION_w,
+ TCC_OPTION_pipe,
+ TCC_OPTION_E,
+ TCC_OPTION_MD,
+ TCC_OPTION_MF,
+ TCC_OPTION_x,
+ TCC_OPTION_dumpversion,
+};
+
+#define TCC_OPTION_HAS_ARG 0x0001
+#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
+
+static const TCCOption tcc_options[] = {
+ { "h", TCC_OPTION_HELP, 0 },
+ { "-help", TCC_OPTION_HELP, 0 },
+ { "?", TCC_OPTION_HELP, 0 },
+ { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
+ { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
+ { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
+ { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
+ { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
+ { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+ { "bench", TCC_OPTION_bench, 0 },
+#ifdef CONFIG_TCC_BACKTRACE
+ { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
+#endif
+#ifdef CONFIG_TCC_BCHECK
+ { "b", TCC_OPTION_b, 0 },
+#endif
+ { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+ { "c", TCC_OPTION_c, 0 },
+ { "static", TCC_OPTION_static, 0 },
+ { "shared", TCC_OPTION_shared, 0 },
+ { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
+ { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
+ { "pedantic", TCC_OPTION_pedantic, 0},
+ { "pthread", TCC_OPTION_pthread, 0},
+ { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+ { "rdynamic", TCC_OPTION_rdynamic, 0 },
+ { "r", TCC_OPTION_r, 0 },
+ { "s", TCC_OPTION_s, 0 },
+ { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+ { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+ { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+ { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
+ { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+ { "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 },
+ { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+ { "w", TCC_OPTION_w, 0 },
+ { "pipe", TCC_OPTION_pipe, 0},
+ { "E", TCC_OPTION_E, 0},
+ { "MD", TCC_OPTION_MD, 0},
+ { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
+ { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
+ { "dumpversion", TCC_OPTION_dumpversion, 0},
+ { NULL, 0, 0 },
+};
+
+static void parse_option_D(TCCState *s1, const char *optarg)
+{
+ char *sym = tcc_strdup(optarg);
+ char *value = strchr(sym, '=');
+ if (value)
+ *value++ = '\0';
+ tcc_define_symbol(s1, sym, value);
+ tcc_free(sym);
+}
+
+PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
+{
+ const TCCOption *popt;
+ const char *optarg, *r;
+ int run = 0;
+ int pthread = 0;
+ int optind = 0;
+
+ /* collect -Wl options for input such as "-Wl,-rpath -Wl,<path>" */
+ CString linker_arg;
+ cstr_new(&linker_arg);
+
+ while (optind < argc) {
+
+ r = argv[optind++];
+ if (r[0] != '-' || r[1] == '\0') {
+ /* add a new file */
+ dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));
+ if (run) {
+ optind--;
+ /* argv[0] will be this file */
+ break;
+ }
+ continue;
+ }
+
+ /* find option in table */
+ for(popt = tcc_options; ; ++popt) {
+ const char *p1 = popt->name;
+ const char *r1 = r + 1;
+ if (p1 == NULL)
+ tcc_error("invalid option -- '%s'", r);
+ if (!strstart(p1, &r1))
+ continue;
+ optarg = r1;
+ if (popt->flags & TCC_OPTION_HAS_ARG) {
+ if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP)) {
+ if (optind >= argc)
+ tcc_error("argument to '%s' is missing", r);
+ optarg = argv[optind++];
+ }
+ } else if (*r1 != '\0')
+ continue;
+ break;
}
- if (multi) {
- option = NULL;
- p = strchr( (end) ? end : p, ',');
- if (p) {
- *p = 0; /* terminate last option */
- option = ++p;
+ switch(popt->index) {
+ case TCC_OPTION_HELP:
+ return 0;
+ case TCC_OPTION_I:
+ if (tcc_add_include_path(s, optarg) < 0)
+ tcc_error("too many include paths");
+ break;
+ case TCC_OPTION_D:
+ parse_option_D(s, optarg);
+ break;
+ case TCC_OPTION_U:
+ tcc_undefine_symbol(s, optarg);
+ break;
+ case TCC_OPTION_L:
+ tcc_add_library_path(s, optarg);
+ break;
+ case TCC_OPTION_B:
+ /* set tcc utilities path (mainly for tcc development) */
+ tcc_set_lib_path(s, optarg);
+ break;
+ case TCC_OPTION_l:
+ dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));
+ s->nb_libraries++;
+ break;
+ case TCC_OPTION_pthread:
+ parse_option_D(s, "_REENTRANT");
+ pthread = 1;
+ break;
+ case TCC_OPTION_bench:
+ s->do_bench = 1;
+ break;
+#ifdef CONFIG_TCC_BACKTRACE
+ case TCC_OPTION_bt:
+ tcc_set_num_callers(atoi(optarg));
+ break;
+#endif
+#ifdef CONFIG_TCC_BCHECK
+ case TCC_OPTION_b:
+ s->do_bounds_check = 1;
+ s->do_debug = 1;
+ break;
+#endif
+ case TCC_OPTION_g:
+ s->do_debug = 1;
+ break;
+ case TCC_OPTION_c:
+ s->output_type = TCC_OUTPUT_OBJ;
+ break;
+ case TCC_OPTION_static:
+ s->static_link = 1;
+ break;
+ case TCC_OPTION_shared:
+ s->output_type = TCC_OUTPUT_DLL;
+ break;
+ case TCC_OPTION_soname:
+ s->soname = tcc_strdup(optarg);
+ break;
+ case TCC_OPTION_m:
+ s->option_m = tcc_strdup(optarg);
+ break;
+ case TCC_OPTION_o:
+ s->outfile = tcc_strdup(optarg);
+ break;
+ case TCC_OPTION_r:
+ /* generate a .o merging several output files */
+ s->option_r = 1;
+ s->output_type = TCC_OUTPUT_OBJ;
+ break;
+ case TCC_OPTION_isystem:
+ tcc_add_sysinclude_path(s, optarg);
+ break;
+ case TCC_OPTION_nostdinc:
+ s->nostdinc = 1;
+ break;
+ case TCC_OPTION_nostdlib:
+ s->nostdlib = 1;
+ break;
+ case TCC_OPTION_print_search_dirs:
+ s->print_search_dirs = 1;
+ break;
+ case TCC_OPTION_run:
+ s->output_type = TCC_OUTPUT_MEMORY;
+ tcc_set_options(s, optarg);
+ run = 1;
+ break;
+ case TCC_OPTION_v:
+ do ++s->verbose; while (*optarg++ == 'v');
+ break;
+ case TCC_OPTION_f:
+ if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
+ goto unsupported_option;
+ break;
+ case TCC_OPTION_W:
+ if (tcc_set_warning(s, optarg, 1) < 0 &&
+ s->warn_unsupported)
+ goto unsupported_option;
+ break;
+ case TCC_OPTION_w:
+ s->warn_none = 1;
+ break;
+ case TCC_OPTION_rdynamic:
+ s->rdynamic = 1;
+ break;
+ case TCC_OPTION_Wl:
+ if (linker_arg.size)
+ --linker_arg.size, cstr_ccat(&linker_arg, ',');
+ cstr_cat(&linker_arg, optarg);
+ cstr_ccat(&linker_arg, '\0');
+ break;
+ case TCC_OPTION_E:
+ s->output_type = TCC_OUTPUT_PREPROCESS;
+ break;
+ case TCC_OPTION_MD:
+ s->gen_deps = 1;
+ break;
+ case TCC_OPTION_MF:
+ s->deps_outfile = tcc_strdup(optarg);
+ break;
+ case TCC_OPTION_dumpversion:
+ printf ("%s\n", TCC_VERSION);
+ exit(0);
+ case TCC_OPTION_O:
+ case TCC_OPTION_pedantic:
+ case TCC_OPTION_pipe:
+ case TCC_OPTION_s:
+ case TCC_OPTION_x:
+ /* ignored */
+ break;
+ default:
+ if (s->warn_unsupported) {
+ unsupported_option:
+ tcc_warning("unsupported option '%s'", r);
}
- } else
- option = NULL;
+ break;
+ }
}
- return NULL;
+
+ if (pthread && s->output_type != TCC_OUTPUT_OBJ)
+ tcc_set_options(s, "-lpthread");
+
+ tcc_set_linker(s, (const char *)linker_arg.data);
+ cstr_free(&linker_arg);
+
+ return optind;
+}
+
+LIBTCCAPI int tcc_set_options(TCCState *s, const char *str)
+{
+ const char *s1;
+ char **argv, *arg;
+ int argc, len;
+ int ret;
+
+ argc = 0, argv = NULL;
+ for(;;) {
+ while (is_space(*str))
+ str++;
+ if (*str == '\0')
+ break;
+ s1 = str;
+ while (*str != '\0' && !is_space(*str))
+ str++;
+ len = str - s1;
+ arg = tcc_malloc(len + 1);
+ pstrncpy(arg, s1, len);
+ dynarray_add((void ***)&argv, &argc, arg);
+ }
+ ret = tcc_parse_args(s, argc, argv);
+ dynarray_reset(&argv, &argc);
+ return ret;
}
PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
@@ -1632,69 +1939,3 @@ PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
tt, (int)(total_lines / tt),
total_bytes / tt / 1000000.0);
}
-
-/* set CONFIG_TCCDIR at runtime */
-LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path)
-{
- tcc_free(s->tcc_lib_path);
- s->tcc_lib_path = tcc_strdup(path);
-}
-
-PUB_FUNC char *tcc_default_target(TCCState *s, const char *default_file)
-{
- char buf[1024];
- char *ext;
- const char *name = "a";
-
- if (default_file && strcmp(default_file, "-"))
- name = tcc_basename(default_file);
- pstrcpy(buf, sizeof(buf), name);
- ext = tcc_fileextension(buf);
-#ifdef TCC_TARGET_PE
- if (s->output_type == TCC_OUTPUT_DLL)
- strcpy(ext, ".dll");
- else
- if (s->output_type == TCC_OUTPUT_EXE)
- strcpy(ext, ".exe");
- else
-#endif
- if (( (s->output_type == TCC_OUTPUT_OBJ && !s->reloc_output) ||
- (s->output_type == TCC_OUTPUT_PREPROCESS) )
- && *ext)
- strcpy(ext, ".o");
- else
- pstrcpy(buf, sizeof(buf), "a.out");
-
- return tcc_strdup(buf);
-}
-
-
-PUB_FUNC void tcc_gen_makedeps(TCCState *s, const char *target, const char *filename)
-{
- FILE *depout;
- char buf[1024], *ext;
- int i;
-
- if (!filename) {
- /* compute filename automatically
- * dir/file.o -> dir/file.d */
- pstrcpy(buf, sizeof(buf), target);
- ext = tcc_fileextension(buf);
- pstrcpy(ext, sizeof(buf) - (ext-buf), ".d");
- filename = buf;
- }
-
- if (s->verbose)
- printf("<- %s\n", filename);
-
- /* XXX return err codes instead of error() ? */
- depout = fopen(filename, "w");
- if (!depout)
- tcc_error("could not open '%s'", filename);
-
- fprintf(depout, "%s : \\\n", target);
- for (i=0; i<s->nb_target_deps; ++i)
- fprintf(depout, " %s \\\n", s->target_deps[i]);
- fprintf(depout, "\n");
- fclose(depout);
-}
diff --git a/libtcc.h b/libtcc.h
index 278dca3..e69cc6b 100644
--- a/libtcc.h
+++ b/libtcc.h
@@ -19,18 +19,15 @@ LIBTCCAPI TCCState *tcc_new(void);
/* free a TCC compilation context */
LIBTCCAPI void tcc_delete(TCCState *s);
-/* add debug information in the generated code */
-LIBTCCAPI void tcc_enable_debug(TCCState *s);
+/* set CONFIG_TCCDIR at runtime */
+LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
/* set error/warning display callback */
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque,
- void (*error_func)(void *opaque, const char *msg));
-
-/* set/reset a warning */
-LIBTCCAPI int tcc_set_warning(TCCState *s, const char *warning_name, int value);
+ void (*error_func)(void *opaque, const char *msg));
-/* set linker option */
-LIBTCCAPI const char * tcc_set_linker(TCCState *s, char *option, int multi);
+/* set options as from command line (multiple supported) */
+LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
/*****************************/
/* preprocessor */
@@ -50,29 +47,22 @@ LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym);
/*****************************/
/* compiling */
-/* add a file (either a C file, dll, an object, a library or an ld
- script). Return -1 if error. */
+/* add a file (C file, dll, object, library, ld script). Return -1 if error. */
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
-/* compile a string containing a C source. Return non zero if
- error. */
+/* compile a string containing a C source. Return -1 if error. */
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
/*****************************/
/* linking commands */
/* set output type. MUST BE CALLED before any compilation */
-#define TCC_OUTPUT_MEMORY 0 /* output will be ran in memory (no
- output file) (default) */
+LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
+#define TCC_OUTPUT_MEMORY 0 /* output will be run in memory (default) */
#define TCC_OUTPUT_EXE 1 /* executable file */
#define TCC_OUTPUT_DLL 2 /* dynamic library */
#define TCC_OUTPUT_OBJ 3 /* object file */
-#define TCC_OUTPUT_PREPROCESS 4 /* preprocessed file (used internally) */
-LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
-
-#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
-#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
-#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
+#define TCC_OUTPUT_PREPROCESS 4 /* only preprocess (used internally) */
/* equivalent to -Lpath option */
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
@@ -91,21 +81,18 @@ LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
tcc_relocate() before. */
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
-/* do all relocations (needed before using tcc_get_symbol())
- possible values for 'ptr':
+/* do all relocations (needed before using tcc_get_symbol()) */
+LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
+/* possible values for 'ptr':
- TCC_RELOCATE_AUTO : Allocate and manage memory internally
- NULL : return required memory size for the step below
- memory address : copy code to memory passed by the caller
- returns -1 on error. */
-LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
+ returns -1 if error. */
#define TCC_RELOCATE_AUTO (void*)1
/* return symbol value or NULL if not found */
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
-/* set CONFIG_TCCDIR at runtime */
-LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
-
#ifdef __cplusplus
}
#endif
diff --git a/tcc-doc.html b/tcc-doc.html
new file mode 100644
index 0000000..727fa87
--- /dev/null
+++ b/tcc-doc.html
@@ -0,0 +1,2332 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html401/loose.dtd">
+<html>
+<!-- Created on February 15, 2013 by texi2html 1.82
+texi2html was written by:
+ Lionel Cons <Lionel.Cons@cern.ch> (original author)
+ Karl Berry <karl@freefriends.org>
+ Olaf Bachmann <obachman@mathematik.uni-kl.de>
+ and many others.
+Maintained by: Many creative people.
+Send bugs and suggestions to <texi2html-bug@nongnu.org>
+-->
+<head>
+<title>Tiny C Compiler Reference Documentation</title>
+
+<meta name="description" content="Tiny C Compiler Reference Documentation">
+<meta name="keywords" content="Tiny C Compiler Reference Documentation">
+<meta name="resource-type" content="document">
+<meta name="distribution" content="global">
+<meta name="Generator" content="texi2html 1.82">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<style type="text/css">
+<!--
+a.summary-letter {text-decoration: none}
+blockquote.smallquotation {font-size: smaller}
+pre.display {font-family: serif}
+pre.format {font-family: serif}
+pre.menu-comment {font-family: serif}
+pre.menu-preformatted {font-family: serif}
+pre.smalldisplay {font-family: serif; font-size: smaller}
+pre.smallexample {font-size: smaller}
+pre.smallformat {font-family: serif; font-size: smaller}
+pre.smalllisp {font-size: smaller}
+span.roman {font-family:serif; font-weight:normal;}
+span.sansserif {font-family:sans-serif; font-weight:normal;}
+ul.toc {list-style: none}
+-->
+</style>
+
+
+</head>
+
+<body lang="en" bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000">
+
+<a name="Top"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<a name="Tiny-C-Compiler-Reference-Documentation"></a>
+<h1 class="settitle">Tiny C Compiler Reference Documentation</h1>
+
+<p>This manual documents version 0.9.26 of the Tiny C Compiler.
+</p>
+<table class="menu" border="0" cellspacing="0">
+<tr><td align="left" valign="top"><a href="#Introduction">1. Introduction</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top"> Introduction to tcc.
+</td></tr>
+<tr><td align="left" valign="top"><a href="#Invoke">2. Command line invocation</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top"> Invocation of tcc (command line, options).
+</td></tr>
+<tr><td align="left" valign="top"><a href="#Clang">3. C language support</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top"> ANSI C and extensions.
+</td></tr>
+<tr><td align="left" valign="top"><a href="#asm">4. TinyCC Assembler</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top"> Assembler syntax.
+</td></tr>
+<tr><td align="left" valign="top"><a href="#linker">5. TinyCC Linker</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top"> Output file generation and supported targets.
+</td></tr>
+<tr><td align="left" valign="top"><a href="#Bounds">6. TinyCC Memory and Bound checks</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top"> Automatic bounds-checking of C code.
+</td></tr>
+<tr><td align="left" valign="top"><a href="#Libtcc">7. The <code>libtcc</code> library</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top"> The libtcc library.
+</td></tr>
+<tr><td align="left" valign="top"><a href="#devel">8. Developer&rsquo;s guide</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top"> Guide for Developers.
+</td></tr>
+</table>
+
+
+<hr size="1">
+<a name="Introduction"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Top" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Invoke" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Invoke" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<a name="Introduction-1"></a>
+<h1 class="chapter">1. Introduction</h1>
+
+<p>TinyCC (aka TCC) is a small but hyper fast C compiler. Unlike other C
+compilers, it is meant to be self-relying: you do not need an
+external assembler or linker because TCC does that for you.
+</p>
+<p>TCC compiles so <em>fast</em> that even for big projects <code>Makefile</code>s may
+not be necessary.
+</p>
+<p>TCC not only supports ANSI C, but also most of the new ISO C99
+standard and many GNUC extensions including inline assembly.
+</p>
+<p>TCC can also be used to make <em>C scripts</em>, i.e. pieces of C source
+that you run as a Perl or Python script. Compilation is so fast that
+your script will be as fast as if it was an executable.
+</p>
+<p>TCC can also automatically generate memory and bound checks
+(see section <a href="#Bounds">TinyCC Memory and Bound checks</a>) while allowing all C pointers operations. TCC can do
+these checks even if non patched libraries are used.
+</p>
+<p>With <code>libtcc</code>, you can use TCC as a backend for dynamic code
+generation (see section <a href="#Libtcc">The <code>libtcc</code> library</a>).
+</p>
+<p>TCC mainly supports the i386 target on Linux and Windows. There are alpha
+ports for the ARM (<code>arm-tcc</code>) and the TMS320C67xx targets
+(<code>c67-tcc</code>). More information about the ARM port is available at
+<a href="http://lists.gnu.org/archive/html/tinycc-devel/2003-10/msg00044.html">http://lists.gnu.org/archive/html/tinycc-devel/2003-10/msg00044.html</a>.
+</p>
+<p>For usage on Windows, see also <a href="tcc-win32.txt">tcc-win32.txt</a>.
+</p>
+<hr size="6">
+<a name="Invoke"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Introduction" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Quick-start" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Introduction" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Clang" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<a name="Command-line-invocation"></a>
+<h1 class="chapter">2. Command line invocation</h1>
+
+<hr size="6">
+<a name="Quick-start"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Invoke" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Option-summary" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Invoke" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Invoke" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Clang" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">2.1 Quick start</h2>
+
+<table><tr><td>&nbsp;</td><td><pre class="example">usage: tcc [options] [<var>infile1</var> <var>infile2</var>&hellip;] [&lsquo;<samp>-run</samp>&rsquo; <var>infile</var> <var>args</var>&hellip;]
+</pre></td></tr></table>
+
+<p>TCC options are a very much like gcc options. The main difference is that TCC
+can also execute directly the resulting program and give it runtime
+arguments.
+</p>
+<p>Here are some examples to understand the logic:
+</p>
+<dl compact="compact">
+<dt> <code>&lsquo;<samp>tcc -run a.c</samp>&rsquo;</code></dt>
+<dd><p>Compile &lsquo;<tt>a.c</tt>&rsquo; and execute it directly
+</p>
+</dd>
+<dt> <code>&lsquo;<samp>tcc -run a.c arg1</samp>&rsquo;</code></dt>
+<dd><p>Compile a.c and execute it directly. arg1 is given as first argument to
+the <code>main()</code> of a.c.
+</p>
+</dd>
+<dt> <code>&lsquo;<samp>tcc a.c -run b.c arg1</samp>&rsquo;</code></dt>
+<dd><p>Compile &lsquo;<tt>a.c</tt>&rsquo; and &lsquo;<tt>b.c</tt>&rsquo;, link them together and execute them. arg1 is given
+as first argument to the <code>main()</code> of the resulting program.
+</p>
+</dd>
+<dt> <code>&lsquo;<samp>tcc -o myprog a.c b.c</samp>&rsquo;</code></dt>
+<dd><p>Compile &lsquo;<tt>a.c</tt>&rsquo; and &lsquo;<tt>b.c</tt>&rsquo;, link them and generate the executable &lsquo;<tt>myprog</tt>&rsquo;.
+</p>
+</dd>
+<dt> <code>&lsquo;<samp>tcc -o myprog a.o b.o</samp>&rsquo;</code></dt>
+<dd><p>link &lsquo;<tt>a.o</tt>&rsquo; and &lsquo;<tt>b.o</tt>&rsquo; together and generate the executable &lsquo;<tt>myprog</tt>&rsquo;.
+</p>
+</dd>
+<dt> <code>&lsquo;<samp>tcc -c a.c</samp>&rsquo;</code></dt>
+<dd><p>Compile &lsquo;<tt>a.c</tt>&rsquo; and generate object file &lsquo;<tt>a.o</tt>&rsquo;.
+</p>
+</dd>
+<dt> <code>&lsquo;<samp>tcc -c asmfile.S</samp>&rsquo;</code></dt>
+<dd><p>Preprocess with C preprocess and assemble &lsquo;<tt>asmfile.S</tt>&rsquo; and generate
+object file &lsquo;<tt>asmfile.o</tt>&rsquo;.
+</p>
+</dd>
+<dt> <code>&lsquo;<samp>tcc -c asmfile.s</samp>&rsquo;</code></dt>
+<dd><p>Assemble (but not preprocess) &lsquo;<tt>asmfile.s</tt>&rsquo; and generate object file
+&lsquo;<tt>asmfile.o</tt>&rsquo;.
+</p>
+</dd>
+<dt> <code>&lsquo;<samp>tcc -r -o ab.o a.c b.c</samp>&rsquo;</code></dt>
+<dd><p>Compile &lsquo;<tt>a.c</tt>&rsquo; and &lsquo;<tt>b.c</tt>&rsquo;, link them together and generate the object file &lsquo;<tt>ab.o</tt>&rsquo;.
+</p>
+</dd>
+</dl>
+
+<p>Scripting:
+</p>
+<p>TCC can be invoked from <em>scripts</em>, just as shell scripts. You just
+need to add <code>#!/usr/local/bin/tcc -run</code> at the start of your C source:
+</p>
+<table><tr><td>&nbsp;</td><td><pre class="example">#!/usr/local/bin/tcc -run
+#include &lt;stdio.h&gt;
+
+int main()
+{
+ printf(&quot;Hello World\n&quot;);
+ return 0;
+}
+</pre></td></tr></table>
+
+<p>TCC can read C source code from <em>standard input</em> when &lsquo;<samp>-</samp>&rsquo; is used in
+place of &lsquo;<samp>infile</samp>&rsquo;. Example:
+</p>
+<table><tr><td>&nbsp;</td><td><pre class="example">echo 'main(){puts(&quot;hello&quot;);}' | tcc -run -
+</pre></td></tr></table>
+
+<hr size="6">
+<a name="Option-summary"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Quick-start" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Clang" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Invoke" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Invoke" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Clang" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">2.2 Option summary</h2>
+
+<p>General Options:
+</p>
+<dl compact="compact">
+<dt> &lsquo;<samp>-c</samp>&rsquo;</dt>
+<dd><p>Generate an object file.
+</p>
+</dd>
+<dt> &lsquo;<samp>-o outfile</samp>&rsquo;</dt>
+<dd><p>Put object file, executable, or dll into output file &lsquo;<tt>outfile</tt>&rsquo;.
+</p>
+</dd>
+<dt> &lsquo;<samp>-run source [args...]</samp>&rsquo;</dt>
+<dd><p>Compile file <var>source</var> and run it with the command line arguments
+<var>args</var>. In order to be able to give more than one argument to a
+script, several TCC options can be given <em>after</em> the
+&lsquo;<samp>-run</samp>&rsquo; option, separated by spaces:
+</p><table><tr><td>&nbsp;</td><td><pre class="example">tcc &quot;-run -L/usr/X11R6/lib -lX11&quot; ex4.c
+</pre></td></tr></table>
+<p>In a script, it gives the following header:
+</p><table><tr><td>&nbsp;</td><td><pre class="example">#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11
+</pre></td></tr></table>
+
+</dd>
+<dt> &lsquo;<samp>-dumpversion</samp>&rsquo;</dt>
+<dd><p>Print only the compiler version and nothing else.
+</p>
+</dd>
+<dt> &lsquo;<samp>-v</samp>&rsquo;</dt>
+<dd><p>Display TCC version.
+</p>
+</dd>
+<dt> &lsquo;<samp>-vv</samp>&rsquo;</dt>
+<dd><p>Show included files. As sole argument, print search dirs (as below).
+</p>
+</dd>
+<dt> &lsquo;<samp>-bench</samp>&rsquo;</dt>
+<dd><p>Display compilation statistics.
+</p>
+</dd>
+<dt> &lsquo;<samp>-print-search-dirs</samp>&rsquo;</dt>
+<dd><p>Print the configured installation directory and a list of library
+and include directories tcc will search.
+</p>
+</dd>
+</dl>
+
+<p>Preprocessor options:
+</p>
+<dl compact="compact">
+<dt> &lsquo;<samp>-Idir</samp>&rsquo;</dt>
+<dd><p>Specify an additional include path. Include paths are searched in the
+order they are specified.
+</p>
+<p>System include paths are always searched after. The default system
+include paths are: &lsquo;<tt>/usr/local/include</tt>&rsquo;, &lsquo;<tt>/usr/include</tt>&rsquo;
+and &lsquo;<tt>PREFIX/lib/tcc/include</tt>&rsquo;. (&lsquo;<tt>PREFIX</tt>&rsquo; is usually
+&lsquo;<tt>/usr</tt>&rsquo; or &lsquo;<tt>/usr/local</tt>&rsquo;).
+</p>
+</dd>
+<dt> &lsquo;<samp>-Dsym[=val]</samp>&rsquo;</dt>
+<dd><p>Define preprocessor symbol &lsquo;<samp>sym</samp>&rsquo; to
+val. If val is not present, its value is &lsquo;<samp>1</samp>&rsquo;. Function-like macros can
+also be defined: &lsquo;<samp>-DF(a)=a+1</samp>&rsquo;
+</p>
+</dd>
+<dt> &lsquo;<samp>-Usym</samp>&rsquo;</dt>
+<dd><p>Undefine preprocessor symbol &lsquo;<samp>sym</samp>&rsquo;.
+</p></dd>
+</dl>
+
+<p>Compilation flags:
+</p>
+<p>Note: each of the following warning options has a negative form beginning with
+&lsquo;<samp>-fno-</samp>&rsquo;.
+</p>
+<dl compact="compact">
+<dt> &lsquo;<samp>-funsigned-char</samp>&rsquo;</dt>
+<dd><p>Let the <code>char</code> type be unsigned.
+</p>
+</dd>
+<dt> &lsquo;<samp>-fsigned-char</samp>&rsquo;</dt>
+<dd><p>Let the <code>char</code> type be signed.
+</p>
+</dd>
+<dt> &lsquo;<samp>-fno-common</samp>&rsquo;</dt>
+<dd><p>Do not generate common symbols for uninitialized data.
+</p>
+</dd>
+<dt> &lsquo;<samp>-fleading-underscore</samp>&rsquo;</dt>
+<dd><p>Add a leading underscore at the beginning of each C symbol.
+</p>
+</dd>
+</dl>
+
+<p>Warning options:
+</p>
+<dl compact="compact">
+<dt> &lsquo;<samp>-w</samp>&rsquo;</dt>
+<dd><p>Disable all warnings.
+</p>
+</dd>
+</dl>
+
+<p>Note: each of the following warning options has a negative form beginning with
+&lsquo;<samp>-Wno-</samp>&rsquo;.
+</p>
+<dl compact="compact">
+<dt> &lsquo;<samp>-Wimplicit-function-declaration</samp>&rsquo;</dt>
+<dd><p>Warn about implicit function declaration.
+</p>
+</dd>
+<dt> &lsquo;<samp>-Wunsupported</samp>&rsquo;</dt>
+<dd><p>Warn about unsupported GCC features that are ignored by TCC.
+</p>
+</dd>
+<dt> &lsquo;<samp>-Wwrite-strings</samp>&rsquo;</dt>
+<dd><p>Make string constants be of type <code>const char *</code> instead of <code>char
+*</code>.
+</p>
+</dd>
+<dt> &lsquo;<samp>-Werror</samp>&rsquo;</dt>
+<dd><p>Abort compilation if warnings are issued.
+</p>
+</dd>
+<dt> &lsquo;<samp>-Wall</samp>&rsquo; </dt>
+<dd><p>Activate all warnings, except &lsquo;<samp>-Werror</samp>&rsquo;, &lsquo;<samp>-Wunusupported</samp>&rsquo; and
+&lsquo;<samp>-Wwrite-strings</samp>&rsquo;.
+</p>
+</dd>
+</dl>
+
+<p>Linker options:
+</p>
+<dl compact="compact">
+<dt> &lsquo;<samp>-Ldir</samp>&rsquo;</dt>
+<dd><p>Specify an additional static library path for the &lsquo;<samp>-l</samp>&rsquo; option. The
+default library paths are &lsquo;<tt>/usr/local/lib</tt>&rsquo;, &lsquo;<tt>/usr/lib</tt>&rsquo; and &lsquo;<tt>/lib</tt>&rsquo;.
+</p>
+</dd>
+<dt> &lsquo;<samp>-lxxx</samp>&rsquo;</dt>
+<dd><p>Link your program with dynamic library libxxx.so or static library
+libxxx.a. The library is searched in the paths specified by the
+&lsquo;<samp>-L</samp>&rsquo; option.
+</p>
+</dd>
+<dt> &lsquo;<samp>-Bdir</samp>&rsquo;</dt>
+<dd><p>Set the path where the tcc internal libraries (and include files) can be
+found (default is &lsquo;<tt>PREFIX/lib/tcc</tt>&rsquo;).
+</p>
+</dd>
+<dt> &lsquo;<samp>-shared</samp>&rsquo;</dt>
+<dd><p>Generate a shared library instead of an executable.
+</p>
+</dd>
+<dt> &lsquo;<samp>-soname name</samp>&rsquo;</dt>
+<dd><p>set name for shared library to be used at runtime
+</p>
+</dd>
+<dt> &lsquo;<samp>-static</samp>&rsquo;</dt>
+<dd><p>Generate a statically linked executable (default is a shared linked
+executable).
+</p>
+</dd>
+<dt> &lsquo;<samp>-rdynamic</samp>&rsquo;</dt>
+<dd><p>Export global symbols to the dynamic linker. It is useful when a library
+opened with <code>dlopen()</code> needs to access executable symbols.
+</p>
+</dd>
+<dt> &lsquo;<samp>-r</samp>&rsquo;</dt>
+<dd><p>Generate an object file combining all input files.
+</p>
+</dd>
+<dt> &lsquo;<samp>-Wl,-rpath=path</samp>&rsquo;</dt>
+<dd><p>Put custom seatch path for dynamic libraries into executable.
+</p>
+</dd>
+<dt> &lsquo;<samp>-Wl,--oformat=fmt</samp>&rsquo;</dt>
+<dd><p>Use <var>fmt</var> as output format. The supported output formats are:
+</p><dl compact="compact">
+<dt> <code>elf32-i386</code></dt>
+<dd><p>ELF output format (default)
+</p></dd>
+<dt> <code>binary</code></dt>
+<dd><p>Binary image (only for executable output)
+</p></dd>
+<dt> <code>coff</code></dt>
+<dd><p>COFF output format (only for executable output for TMS320C67xx target)
+</p></dd>
+</dl>
+
+</dd>
+<dt> &lsquo;<samp>-Wl,-subsystem=console/gui/wince/...</samp>&rsquo;</dt>
+<dd><p>Set type for PE (Windows) executables.
+</p>
+</dd>
+<dt> &lsquo;<samp>-Wl,-[Ttext=# | section-alignment=# | file-alignment=# | image-base=# | stack=#]</samp>&rsquo;</dt>
+<dd><p>Modify executable layout.
+</p>
+</dd>
+<dt> &lsquo;<samp>-Wl,-Bsymbolic</samp>&rsquo;</dt>
+<dd><p>Set DT_SYMBOLIC tag.
+</p>
+</dd>
+</dl>
+
+<p>Debugger options:
+</p>
+<dl compact="compact">
+<dt> &lsquo;<samp>-g</samp>&rsquo;</dt>
+<dd><p>Generate run time debug information so that you get clear run time
+error messages: <code> test.c:68: in function 'test5()': dereferencing
+invalid pointer</code> instead of the laconic <code>Segmentation
+fault</code>.
+</p>
+</dd>
+<dt> &lsquo;<samp>-b</samp>&rsquo;</dt>
+<dd><p>Generate additional support code to check
+memory allocations and array/pointer bounds. &lsquo;<samp>-g</samp>&rsquo; is implied. Note
+that the generated code is slower and bigger in this case.
+</p>
+<p>Note: &lsquo;<samp>-b</samp>&rsquo; is only available on i386 for the moment.
+</p>
+</dd>
+<dt> &lsquo;<samp>-bt N</samp>&rsquo;</dt>
+<dd><p>Display N callers in stack traces. This is useful with &lsquo;<samp>-g</samp>&rsquo; or
+&lsquo;<samp>-b</samp>&rsquo;.
+</p>
+</dd>
+</dl>
+
+<p>Misc options:
+</p>
+<dl compact="compact">
+<dt> &lsquo;<samp>-MD</samp>&rsquo;</dt>
+<dd><p>Generate makefile fragment with dependencies.
+</p>
+</dd>
+<dt> &lsquo;<samp>-MF depfile</samp>&rsquo;</dt>
+<dd><p>Use &lsquo;<tt>depfile</tt>&rsquo; as output for -MD.
+</p>
+</dd>
+</dl>
+
+<p>Note: GCC options &lsquo;<samp>-Ox</samp>&rsquo;, &lsquo;<samp>-fx</samp>&rsquo; and &lsquo;<samp>-mx</samp>&rsquo; are
+ignored.
+</p>
+
+<hr size="6">
+<a name="Clang"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Option-summary" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#ANSI-C" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Invoke" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#asm" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<a name="C-language-support"></a>
+<h1 class="chapter">3. C language support</h1>
+
+<hr size="6">
+<a name="ANSI-C"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Clang" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#ISOC99-extensions" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Clang" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Clang" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#asm" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">3.1 ANSI C</h2>
+
+<p>TCC implements all the ANSI C standard, including structure bit fields
+and floating point numbers (<code>long double</code>, <code>double</code>, and
+<code>float</code> fully supported).
+</p>
+<hr size="6">
+<a name="ISOC99-extensions"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#ANSI-C" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#GNU-C-extensions" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Clang" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Clang" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#asm" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">3.2 ISOC99 extensions</h2>
+
+<p>TCC implements many features of the new C standard: ISO C99. Currently
+missing items are: complex and imaginary numbers and variable length
+arrays.
+</p>
+<p>Currently implemented ISOC99 features:
+</p>
+<ul>
+<li> 64 bit <code>long long</code> types are fully supported.
+
+</li><li> The boolean type <code>_Bool</code> is supported.
+
+</li><li> <code>__func__</code> is a string variable containing the current
+function name.
+
+</li><li> Variadic macros: <code>__VA_ARGS__</code> can be used for
+ function-like macros:
+<table><tr><td>&nbsp;</td><td><pre class="example"> #define dprintf(level, __VA_ARGS__) printf(__VA_ARGS__)
+</pre></td></tr></table>
+
+<p><code>dprintf</code> can then be used with a variable number of parameters.
+</p>
+</li><li> Declarations can appear anywhere in a block (as in C++).
+
+</li><li> Array and struct/union elements can be initialized in any order by
+ using designators:
+<table><tr><td>&nbsp;</td><td><pre class="example"> struct { int x, y; } st[10] = { [0].x = 1, [0].y = 2 };
+
+ int tab[10] = { 1, 2, [5] = 5, [9] = 9};
+</pre></td></tr></table>
+
+</li><li> Compound initializers are supported:
+<table><tr><td>&nbsp;</td><td><pre class="example"> int *p = (int []){ 1, 2, 3 };
+</pre></td></tr></table>
+<p>to initialize a pointer pointing to an initialized array. The same
+works for structures and strings.
+</p>
+</li><li> Hexadecimal floating point constants are supported:
+<table><tr><td>&nbsp;</td><td><pre class="example"> double d = 0x1234p10;
+</pre></td></tr></table>
+
+<p>is the same as writing
+</p><table><tr><td>&nbsp;</td><td><pre class="example"> double d = 4771840.0;
+</pre></td></tr></table>
+
+</li><li> <code>inline</code> keyword is ignored.
+
+</li><li> <code>restrict</code> keyword is ignored.
+</li></ul>
+
+<hr size="6">
+<a name="GNU-C-extensions"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#ISOC99-extensions" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#TinyCC-extensions" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Clang" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Clang" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#asm" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">3.3 GNU C extensions</h2>
+
+<p>TCC implements some GNU C extensions:
+</p>
+<ul>
+<li> array designators can be used without &rsquo;=&rsquo;:
+<table><tr><td>&nbsp;</td><td><pre class="example"> int a[10] = { [0] 1, [5] 2, 3, 4 };
+</pre></td></tr></table>
+
+</li><li> Structure field designators can be a label:
+<table><tr><td>&nbsp;</td><td><pre class="example"> struct { int x, y; } st = { x: 1, y: 1};
+</pre></td></tr></table>
+<p>instead of
+</p><table><tr><td>&nbsp;</td><td><pre class="example"> struct { int x, y; } st = { .x = 1, .y = 1};
+</pre></td></tr></table>
+
+</li><li> <code>\e</code> is ASCII character 27.
+
+</li><li> case ranges : ranges can be used in <code>case</code>s:
+<table><tr><td>&nbsp;</td><td><pre class="example"> switch(a) {
+ case 1 &hellip; 9:
+ printf(&quot;range 1 to 9\n&quot;);
+ break;
+ default:
+ printf(&quot;unexpected\n&quot;);
+ break;
+ }
+</pre></td></tr></table>
+
+<a name="index-aligned-attribute"></a>
+<a name="index-packed-attribute"></a>
+<a name="index-section-attribute"></a>
+<a name="index-unused-attribute"></a>
+<a name="index-cdecl-attribute"></a>
+<a name="index-stdcall-attribute"></a>
+<a name="index-regparm-attribute"></a>
+<a name="index-dllexport-attribute"></a>
+
+</li><li> The keyword <code>__attribute__</code> is handled to specify variable or
+function attributes. The following attributes are supported:
+ <ul>
+<li> <code>aligned(n)</code>: align a variable or a structure field to n bytes
+(must be a power of two).
+
+ </li><li> <code>packed</code>: force alignment of a variable or a structure field to
+ 1.
+
+ </li><li> <code>section(name)</code>: generate function or data in assembly section
+name (name is a string containing the section name) instead of the default
+section.
+
+ </li><li> <code>unused</code>: specify that the variable or the function is unused.
+
+ </li><li> <code>cdecl</code>: use standard C calling convention (default).
+
+ </li><li> <code>stdcall</code>: use Pascal-like calling convention.
+
+ </li><li> <code>regparm(n)</code>: use fast i386 calling convention. <var>n</var> must be
+between 1 and 3. The first <var>n</var> function parameters are respectively put in
+registers <code>%eax</code>, <code>%edx</code> and <code>%ecx</code>.
+
+ </li><li> <code>dllexport</code>: export function from dll/executable (win32 only)
+
+</li></ul>
+
+<p>Here are some examples:
+</p><table><tr><td>&nbsp;</td><td><pre class="example"> int a __attribute__ ((aligned(8), section(&quot;.mysection&quot;)));
+</pre></td></tr></table>
+
+<p>align variable <code>a</code> to 8 bytes and put it in section <code>.mysection</code>.
+</p>
+<table><tr><td>&nbsp;</td><td><pre class="example"> int my_add(int a, int b) __attribute__ ((section(&quot;.mycodesection&quot;)))
+ {
+ return a + b;
+ }
+</pre></td></tr></table>
+
+<p>generate function <code>my_add</code> in section <code>.mycodesection</code>.
+</p>
+</li><li> GNU style variadic macros:
+<table><tr><td>&nbsp;</td><td><pre class="example"> #define dprintf(fmt, args&hellip;) printf(fmt, ## args)
+
+ dprintf(&quot;no arg\n&quot;);
+ dprintf(&quot;one arg %d\n&quot;, 1);
+</pre></td></tr></table>
+
+</li><li> <code>__FUNCTION__</code> is interpreted as C99 <code>__func__</code>
+(so it has not exactly the same semantics as string literal GNUC
+where it is a string literal).
+
+</li><li> The <code>__alignof__</code> keyword can be used as <code>sizeof</code>
+to get the alignment of a type or an expression.
+
+</li><li> The <code>typeof(x)</code> returns the type of <code>x</code>.
+<code>x</code> is an expression or a type.
+
+</li><li> Computed gotos: <code>&amp;&amp;label</code> returns a pointer of type
+<code>void *</code> on the goto label <code>label</code>. <code>goto *expr</code> can be
+used to jump on the pointer resulting from <code>expr</code>.
+
+</li><li> Inline assembly with asm instruction:
+<a name="index-inline-assembly"></a>
+<a name="index-assembly_002c-inline"></a>
+<a name="index-_005f_005fasm_005f_005f"></a>
+<table><tr><td>&nbsp;</td><td><pre class="example">static inline void * my_memcpy(void * to, const void * from, size_t n)
+{
+int d0, d1, d2;
+__asm__ __volatile__(
+ &quot;rep ; movsl\n\t&quot;
+ &quot;testb $2,%b4\n\t&quot;
+ &quot;je 1f\n\t&quot;
+ &quot;movsw\n&quot;
+ &quot;1:\ttestb $1,%b4\n\t&quot;
+ &quot;je 2f\n\t&quot;
+ &quot;movsb\n&quot;
+ &quot;2:&quot;
+ : &quot;=&amp;c&quot; (d0), &quot;=&amp;D&quot; (d1), &quot;=&amp;S&quot; (d2)
+ :&quot;0&quot; (n/4), &quot;q&quot; (n),&quot;1&quot; ((long) to),&quot;2&quot; ((long) from)
+ : &quot;memory&quot;);
+return (to);
+}
+</pre></td></tr></table>
+
+<a name="index-gas"></a>
+<p>TCC includes its own x86 inline assembler with a <code>gas</code>-like (GNU
+assembler) syntax. No intermediate files are generated. GCC 3.x named
+operands are supported.
+</p>
+</li><li> <code>__builtin_types_compatible_p()</code> and <code>__builtin_constant_p()</code>
+are supported.
+
+</li><li> <code>#pragma pack</code> is supported for win32 compatibility.
+
+</li></ul>
+
+<hr size="6">
+<a name="TinyCC-extensions"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#GNU-C-extensions" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#asm" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Clang" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Clang" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#asm" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">3.4 TinyCC extensions</h2>
+
+<ul>
+<li> <code>__TINYC__</code> is a predefined macro to <code>1</code> to
+indicate that you use TCC.
+
+</li><li> <code>#!</code> at the start of a line is ignored to allow scripting.
+
+</li><li> Binary digits can be entered (<code>0b101</code> instead of
+<code>5</code>).
+
+</li><li> <code>__BOUNDS_CHECKING_ON</code> is defined if bound checking is activated.
+
+</li></ul>
+
+<hr size="6">
+<a name="asm"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#TinyCC-extensions" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Syntax" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Clang" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#linker" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<a name="TinyCC-Assembler"></a>
+<h1 class="chapter">4. TinyCC Assembler</h1>
+
+<p>Since version 0.9.16, TinyCC integrates its own assembler. TinyCC
+assembler supports a gas-like syntax (GNU assembler). You can
+desactivate assembler support if you want a smaller TinyCC executable
+(the C compiler does not rely on the assembler).
+</p>
+<p>TinyCC Assembler is used to handle files with &lsquo;<tt>.S</tt>&rsquo; (C
+preprocessed assembler) and &lsquo;<tt>.s</tt>&rsquo; extensions. It is also used to
+handle the GNU inline assembler with the <code>asm</code> keyword.
+</p>
+<hr size="6">
+<a name="Syntax"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#asm" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Expressions" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#asm" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#asm" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#linker" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">4.1 Syntax</h2>
+
+<p>TinyCC Assembler supports most of the gas syntax. The tokens are the
+same as C.
+</p>
+<ul>
+<li> C and C++ comments are supported.
+
+</li><li> Identifiers are the same as C, so you cannot use &rsquo;.&rsquo; or &rsquo;$&rsquo;.
+
+</li><li> Only 32 bit integer numbers are supported.
+
+</li></ul>
+
+<hr size="6">
+<a name="Expressions"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Syntax" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Labels" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#asm" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#asm" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#linker" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">4.2 Expressions</h2>
+
+<ul>
+<li> Integers in decimal, octal and hexa are supported.
+
+</li><li> Unary operators: +, -, ~.
+
+</li><li> Binary operators in decreasing priority order:
+
+<ol>
+<li> *, /, %
+</li><li> &amp;, |, ^
+</li><li> +, -
+</li></ol>
+
+</li><li> A value is either an absolute number or a label plus an offset.
+All operators accept absolute values except &rsquo;+&rsquo; and &rsquo;-&rsquo;. &rsquo;+&rsquo; or &rsquo;-&rsquo; can be
+used to add an offset to a label. &rsquo;-&rsquo; supports two labels only if they
+are the same or if they are both defined and in the same section.
+
+</li></ul>
+
+<hr size="6">
+<a name="Labels"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Expressions" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Directives" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#asm" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#asm" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#linker" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">4.3 Labels</h2>
+
+<ul>
+<li> All labels are considered as local, except undefined ones.
+
+</li><li> Numeric labels can be used as local <code>gas</code>-like labels.
+They can be defined several times in the same source. Use &rsquo;b&rsquo;
+(backward) or &rsquo;f&rsquo; (forward) as suffix to reference them:
+
+<table><tr><td>&nbsp;</td><td><pre class="example"> 1:
+ jmp 1b /* jump to '1' label before */
+ jmp 1f /* jump to '1' label after */
+ 1:
+</pre></td></tr></table>
+
+</li></ul>
+
+<hr size="6">
+<a name="Directives"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Labels" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#X86-Assembler" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#asm" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#asm" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#linker" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">4.4 Directives</h2>
+<a name="index-assembler-directives"></a>
+<a name="index-directives_002c-assembler"></a>
+<a name="index-align-directive"></a>
+<a name="index-skip-directive"></a>
+<a name="index-space-directive"></a>
+<a name="index-byte-directive"></a>
+<a name="index-word-directive"></a>
+<a name="index-short-directive"></a>
+<a name="index-int-directive"></a>
+<a name="index-long-directive"></a>
+<a name="index-quad-directive"></a>
+<a name="index-globl-directive"></a>
+<a name="index-global-directive"></a>
+<a name="index-section-directive"></a>
+<a name="index-text-directive"></a>
+<a name="index-data-directive"></a>
+<a name="index-bss-directive"></a>
+<a name="index-fill-directive"></a>
+<a name="index-org-directive"></a>
+<a name="index-previous-directive"></a>
+<a name="index-string-directive"></a>
+<a name="index-asciz-directive"></a>
+<a name="index-ascii-directive"></a>
+
+<p>All directives are preceeded by a &rsquo;.&rsquo;. The following directives are
+supported:
+</p>
+<ul>
+<li> .align n[,value]
+</li><li> .skip n[,value]
+</li><li> .space n[,value]
+</li><li> .byte value1[,...]
+</li><li> .word value1[,...]
+</li><li> .short value1[,...]
+</li><li> .int value1[,...]
+</li><li> .long value1[,...]
+</li><li> .quad immediate_value1[,...]
+</li><li> .globl symbol
+</li><li> .global symbol
+</li><li> .section section
+</li><li> .text
+</li><li> .data
+</li><li> .bss
+</li><li> .fill repeat[,size[,value]]
+</li><li> .org n
+</li><li> .previous
+</li><li> .string string[,...]
+</li><li> .asciz string[,...]
+</li><li> .ascii string[,...]
+</li></ul>
+
+<hr size="6">
+<a name="X86-Assembler"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Directives" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#linker" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#asm" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#asm" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#linker" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">4.5 X86 Assembler</h2>
+<a name="index-assembler"></a>
+
+<p>All X86 opcodes are supported. Only ATT syntax is supported (source
+then destination operand order). If no size suffix is given, TinyCC
+tries to guess it from the operand sizes.
+</p>
+<p>Currently, MMX opcodes are supported but not SSE ones.
+</p>
+<hr size="6">
+<a name="linker"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#X86-Assembler" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#ELF-file-generation" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#asm" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Bounds" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<a name="TinyCC-Linker"></a>
+<h1 class="chapter">5. TinyCC Linker</h1>
+<a name="index-linker"></a>
+
+<hr size="6">
+<a name="ELF-file-generation"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#linker" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#ELF-file-loader" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#linker" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#linker" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Bounds" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">5.1 ELF file generation</h2>
+<a name="index-ELF"></a>
+
+<p>TCC can directly output relocatable ELF files (object files),
+executable ELF files and dynamic ELF libraries without relying on an
+external linker.
+</p>
+<p>Dynamic ELF libraries can be output but the C compiler does not generate
+position independent code (PIC). It means that the dynamic library
+code generated by TCC cannot be factorized among processes yet.
+</p>
+<p>TCC linker eliminates unreferenced object code in libraries. A single pass is
+done on the object and library list, so the order in which object files and
+libraries are specified is important (same constraint as GNU ld). No grouping
+options (&lsquo;<samp>--start-group</samp>&rsquo; and &lsquo;<samp>--end-group</samp>&rsquo;) are supported.
+</p>
+<hr size="6">
+<a name="ELF-file-loader"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#ELF-file-generation" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#PE_002di386-file-generation" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#linker" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#linker" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Bounds" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">5.2 ELF file loader</h2>
+
+<p>TCC can load ELF object files, archives (.a files) and dynamic
+libraries (.so).
+</p>
+<hr size="6">
+<a name="PE_002di386-file-generation"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#ELF-file-loader" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#GNU-Linker-Scripts" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#linker" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#linker" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Bounds" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">5.3 PE-i386 file generation</h2>
+<a name="index-PE_002di386"></a>
+
+<p>TCC for Windows supports the native Win32 executable file format (PE-i386). It
+generates EXE files (console and gui) and DLL files.
+</p>
+<p>For usage on Windows, see also tcc-win32.txt.
+</p>
+<hr size="6">
+<a name="GNU-Linker-Scripts"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#PE_002di386-file-generation" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Bounds" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#linker" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#linker" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Bounds" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">5.4 GNU Linker Scripts</h2>
+<a name="index-scripts_002c-linker"></a>
+<a name="index-linker-scripts"></a>
+<a name="index-GROUP_002c-linker-command"></a>
+<a name="index-FILE_002c-linker-command"></a>
+<a name="index-OUTPUT_005fFORMAT_002c-linker-command"></a>
+<a name="index-TARGET_002c-linker-command"></a>
+
+<p>Because on many Linux systems some dynamic libraries (such as
+&lsquo;<tt>/usr/lib/libc.so</tt>&rsquo;) are in fact GNU ld link scripts (horrible!),
+the TCC linker also supports a subset of GNU ld scripts.
+</p>
+<p>The <code>GROUP</code> and <code>FILE</code> commands are supported. <code>OUTPUT_FORMAT</code>
+and <code>TARGET</code> are ignored.
+</p>
+<p>Example from &lsquo;<tt>/usr/lib/libc.so</tt>&rsquo;:
+</p><table><tr><td>&nbsp;</td><td><pre class="example">/* GNU ld script
+ Use the shared library, but some functions are only in
+ the static library, so try that secondarily. */
+GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a )
+</pre></td></tr></table>
+
+<hr size="6">
+<a name="Bounds"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#GNU-Linker-Scripts" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Libtcc" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#linker" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Libtcc" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<a name="TinyCC-Memory-and-Bound-checks"></a>
+<h1 class="chapter">6. TinyCC Memory and Bound checks</h1>
+<a name="index-bound-checks"></a>
+<a name="index-memory-checks"></a>
+
+<p>This feature is activated with the &lsquo;<samp>-b</samp>&rsquo; (see section <a href="#Invoke">Command line invocation</a>).
+</p>
+<p>Note that pointer size is <em>unchanged</em> and that code generated
+with bound checks is <em>fully compatible</em> with unchecked
+code. When a pointer comes from unchecked code, it is assumed to be
+valid. Even very obscure C code with casts should work correctly.
+</p>
+<p>For more information about the ideas behind this method, see
+<a href="http://www.doc.ic.ac.uk/~phjk/BoundsChecking.html">http://www.doc.ic.ac.uk/~phjk/BoundsChecking.html</a>.
+</p>
+<p>Here are some examples of caught errors:
+</p>
+<dl compact="compact">
+<dt> Invalid range with standard string function:</dt>
+<dd><table><tr><td>&nbsp;</td><td><pre class="example">{
+ char tab[10];
+ memset(tab, 0, 11);
+}
+</pre></td></tr></table>
+
+</dd>
+<dt> Out of bounds-error in global or local arrays:</dt>
+<dd><table><tr><td>&nbsp;</td><td><pre class="example">{
+ int tab[10];
+ for(i=0;i&lt;11;i++) {
+ sum += tab[i];
+ }
+}
+</pre></td></tr></table>
+
+</dd>
+<dt> Out of bounds-error in malloc&rsquo;ed data:</dt>
+<dd><table><tr><td>&nbsp;</td><td><pre class="example">{
+ int *tab;
+ tab = malloc(20 * sizeof(int));
+ for(i=0;i&lt;21;i++) {
+ sum += tab4[i];
+ }
+ free(tab);
+}
+</pre></td></tr></table>
+
+</dd>
+<dt> Access of freed memory:</dt>
+<dd><table><tr><td>&nbsp;</td><td><pre class="example">{
+ int *tab;
+ tab = malloc(20 * sizeof(int));
+ free(tab);
+ for(i=0;i&lt;20;i++) {
+ sum += tab4[i];
+ }
+}
+</pre></td></tr></table>
+
+</dd>
+<dt> Double free:</dt>
+<dd><table><tr><td>&nbsp;</td><td><pre class="example">{
+ int *tab;
+ tab = malloc(20 * sizeof(int));
+ free(tab);
+ free(tab);
+}
+</pre></td></tr></table>
+
+</dd>
+</dl>
+
+<hr size="6">
+<a name="Libtcc"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Bounds" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#devel" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Bounds" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#devel" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<a name="The-libtcc-library"></a>
+<h1 class="chapter">7. The <code>libtcc</code> library</h1>
+
+<p>The <code>libtcc</code> library enables you to use TCC as a backend for
+dynamic code generation.
+</p>
+<p>Read the &lsquo;<tt>libtcc.h</tt>&rsquo; to have an overview of the API. Read
+&lsquo;<tt>libtcc_test.c</tt>&rsquo; to have a very simple example.
+</p>
+<p>The idea consists in giving a C string containing the program you want
+to compile directly to <code>libtcc</code>. Then you can access to any global
+symbol (function or variable) defined.
+</p>
+<hr size="6">
+<a name="devel"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Libtcc" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#File-reading" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Libtcc" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<a name="Developer_0027s-guide"></a>
+<h1 class="chapter">8. Developer&rsquo;s guide</h1>
+
+<p>This chapter gives some hints to understand how TCC works. You can skip
+it if you do not intend to modify the TCC code.
+</p>
+<hr size="6">
+<a name="File-reading"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#devel" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Lexer" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">8.1 File reading</h2>
+
+<p>The <code>BufferedFile</code> structure contains the context needed to read a
+file, including the current line number. <code>tcc_open()</code> opens a new
+file and <code>tcc_close()</code> closes it. <code>inp()</code> returns the next
+character.
+</p>
+<hr size="6">
+<a name="Lexer"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#File-reading" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Parser" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">8.2 Lexer</h2>
+
+<p><code>next()</code> reads the next token in the current
+file. <code>next_nomacro()</code> reads the next token without macro
+expansion.
+</p>
+<p><code>tok</code> contains the current token (see <code>TOK_xxx</code>)
+constants. Identifiers and keywords are also keywords. <code>tokc</code>
+contains additional infos about the token (for example a constant value
+if number or string token).
+</p>
+<hr size="6">
+<a name="Parser"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Lexer" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Types" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">8.3 Parser</h2>
+
+<p>The parser is hardcoded (yacc is not necessary). It does only one pass,
+except:
+</p>
+<ul>
+<li> For initialized arrays with unknown size, a first pass
+is done to count the number of elements.
+
+</li><li> For architectures where arguments are evaluated in
+reverse order, a first pass is done to reverse the argument order.
+
+</li></ul>
+
+<hr size="6">
+<a name="Types"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Parser" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Symbols" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">8.4 Types</h2>
+
+<p>The types are stored in a single &rsquo;int&rsquo; variable. It was choosen in the
+first stages of development when tcc was much simpler. Now, it may not
+be the best solution.
+</p>
+<table><tr><td>&nbsp;</td><td><pre class="example">#define VT_INT 0 /* integer type */
+#define VT_BYTE 1 /* signed byte type */
+#define VT_SHORT 2 /* short type */
+#define VT_VOID 3 /* void type */
+#define VT_PTR 4 /* pointer */
+#define VT_ENUM 5 /* enum definition */
+#define VT_FUNC 6 /* function type */
+#define VT_STRUCT 7 /* struct/union definition */
+#define VT_FLOAT 8 /* IEEE float */
+#define VT_DOUBLE 9 /* IEEE double */
+#define VT_LDOUBLE 10 /* IEEE long double */
+#define VT_BOOL 11 /* ISOC99 boolean type */
+#define VT_LLONG 12 /* 64 bit integer */
+#define VT_LONG 13 /* long integer (NEVER USED as type, only
+ during parsing) */
+#define VT_BTYPE 0x000f /* mask for basic type */
+#define VT_UNSIGNED 0x0010 /* unsigned type */
+#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
+#define VT_VLA 0x20000 /* VLA type (also has VT_PTR and VT_ARRAY) */
+#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_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */
+</pre></td></tr></table>
+
+<p>When a reference to another type is needed (for pointers, functions and
+structures), the <code>32 - VT_STRUCT_SHIFT</code> high order bits are used to
+store an identifier reference.
+</p>
+<p>The <code>VT_UNSIGNED</code> flag can be set for chars, shorts, ints and long
+longs.
+</p>
+<p>Arrays are considered as pointers <code>VT_PTR</code> with the flag
+<code>VT_ARRAY</code> set. Variable length arrays are considered as special
+arrays and have flag <code>VT_VLA</code> set instead of <code>VT_ARRAY</code>.
+</p>
+<p>The <code>VT_BITFIELD</code> flag can be set for chars, shorts, ints and long
+longs. If it is set, then the bitfield position is stored from bits
+VT_STRUCT_SHIFT to VT_STRUCT_SHIFT + 5 and the bit field size is stored
+from bits VT_STRUCT_SHIFT + 6 to VT_STRUCT_SHIFT + 11.
+</p>
+<p><code>VT_LONG</code> is never used except during parsing.
+</p>
+<p>During parsing, the storage of an object is also stored in the type
+integer:
+</p>
+<table><tr><td>&nbsp;</td><td><pre class="example">#define VT_EXTERN 0x00000080 /* extern definition */
+#define VT_STATIC 0x00000100 /* static variable */
+#define VT_TYPEDEF 0x00000200 /* typedef definition */
+#define VT_INLINE 0x00000400 /* inline definition */
+#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */
+#define VT_EXPORT 0x00008000 /* win32: data exported from dll */
+#define VT_WEAK 0x00010000 /* win32: data exported from dll */
+</pre></td></tr></table>
+
+<hr size="6">
+<a name="Symbols"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Types" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Sections" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">8.5 Symbols</h2>
+
+<p>All symbols are stored in hashed symbol stacks. Each symbol stack
+contains <code>Sym</code> structures.
+</p>
+<p><code>Sym.v</code> contains the symbol name (remember
+an idenfier is also a token, so a string is never necessary to store
+it). <code>Sym.t</code> gives the type of the symbol. <code>Sym.r</code> is usually
+the register in which the corresponding variable is stored. <code>Sym.c</code> is
+usually a constant associated to the symbol like its address for normal
+symbols, and the number of entries for symbols representing arrays.
+Variable length array types use <code>Sym.c</code> as a location on the stack
+which holds the runtime sizeof for the type.
+</p>
+<p>Four main symbol stacks are defined:
+</p>
+<dl compact="compact">
+<dt> <code>define_stack</code></dt>
+<dd><p>for the macros (<code>#define</code>s).
+</p>
+</dd>
+<dt> <code>global_stack</code></dt>
+<dd><p>for the global variables, functions and types.
+</p>
+</dd>
+<dt> <code>local_stack</code></dt>
+<dd><p>for the local variables, functions and types.
+</p>
+</dd>
+<dt> <code>global_label_stack</code></dt>
+<dd><p>for the local labels (for <code>goto</code>).
+</p>
+</dd>
+<dt> <code>label_stack</code></dt>
+<dd><p>for GCC block local labels (see the <code>__label__</code> keyword).
+</p>
+</dd>
+</dl>
+
+<p><code>sym_push()</code> is used to add a new symbol in the local symbol
+stack. If no local symbol stack is active, it is added in the global
+symbol stack.
+</p>
+<p><code>sym_pop(st,b)</code> pops symbols from the symbol stack <var>st</var> until
+the symbol <var>b</var> is on the top of stack. If <var>b</var> is NULL, the stack
+is emptied.
+</p>
+<p><code>sym_find(v)</code> return the symbol associated to the identifier
+<var>v</var>. The local stack is searched first from top to bottom, then the
+global stack.
+</p>
+<hr size="6">
+<a name="Sections"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Symbols" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Code-generation" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">8.6 Sections</h2>
+
+<p>The generated code and datas are written in sections. The structure
+<code>Section</code> contains all the necessary information for a given
+section. <code>new_section()</code> creates a new section. ELF file semantics
+is assumed for each section.
+</p>
+<p>The following sections are predefined:
+</p>
+<dl compact="compact">
+<dt> <code>text_section</code></dt>
+<dd><p>is the section containing the generated code. <var>ind</var> contains the
+current position in the code section.
+</p>
+</dd>
+<dt> <code>data_section</code></dt>
+<dd><p>contains initialized data
+</p>
+</dd>
+<dt> <code>bss_section</code></dt>
+<dd><p>contains uninitialized data
+</p>
+</dd>
+<dt> <code>bounds_section</code></dt>
+<dt> <code>lbounds_section</code></dt>
+<dd><p>are used when bound checking is activated
+</p>
+</dd>
+<dt> <code>stab_section</code></dt>
+<dt> <code>stabstr_section</code></dt>
+<dd><p>are used when debugging is actived to store debug information
+</p>
+</dd>
+<dt> <code>symtab_section</code></dt>
+<dt> <code>strtab_section</code></dt>
+<dd><p>contain the exported symbols (currently only used for debugging).
+</p>
+</dd>
+</dl>
+
+<hr size="6">
+<a name="Code-generation"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Sections" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Introduction-2" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">8.7 Code generation</h2>
+<a name="index-code-generation"></a>
+
+<hr size="6">
+<a name="Introduction-2"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Code-generation" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#The-value-stack" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Code-generation" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h3 class="subsection">8.7.1 Introduction</h3>
+
+<p>The TCC code generator directly generates linked binary code in one
+pass. It is rather unusual these days (see gcc for example which
+generates text assembly), but it can be very fast and surprisingly
+little complicated.
+</p>
+<p>The TCC code generator is register based. Optimization is only done at
+the expression level. No intermediate representation of expression is
+kept except the current values stored in the <em>value stack</em>.
+</p>
+<p>On x86, three temporary registers are used. When more registers are
+needed, one register is spilled into a new temporary variable on the stack.
+</p>
+<hr size="6">
+<a name="The-value-stack"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Introduction-2" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Manipulating-the-value-stack" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Code-generation" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h3 class="subsection">8.7.2 The value stack</h3>
+<a name="index-value-stack_002c-introduction"></a>
+
+<p>When an expression is parsed, its value is pushed on the value stack
+(<var>vstack</var>). The top of the value stack is <var>vtop</var>. Each value
+stack entry is the structure <code>SValue</code>.
+</p>
+<p><code>SValue.t</code> is the type. <code>SValue.r</code> indicates how the value is
+currently stored in the generated code. It is usually a CPU register
+index (<code>REG_xxx</code> constants), but additional values and flags are
+defined:
+</p>
+<table><tr><td>&nbsp;</td><td><pre class="example">#define VT_CONST 0x00f0
+#define VT_LLOCAL 0x00f1
+#define VT_LOCAL 0x00f2
+#define VT_CMP 0x00f3
+#define VT_JMP 0x00f4
+#define VT_JMPI 0x00f5
+#define VT_LVAL 0x0100
+#define VT_SYM 0x0200
+#define VT_MUSTCAST 0x0400
+#define VT_MUSTBOUND 0x0800
+#define VT_BOUNDED 0x8000
+#define VT_LVAL_BYTE 0x1000
+#define VT_LVAL_SHORT 0x2000
+#define VT_LVAL_UNSIGNED 0x4000
+#define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
+</pre></td></tr></table>
+
+<dl compact="compact">
+<dt> <code>VT_CONST</code></dt>
+<dd><p>indicates that the value is a constant. It is stored in the union
+<code>SValue.c</code>, depending on its type.
+</p>
+</dd>
+<dt> <code>VT_LOCAL</code></dt>
+<dd><p>indicates a local variable pointer at offset <code>SValue.c.i</code> in the
+stack.
+</p>
+</dd>
+<dt> <code>VT_CMP</code></dt>
+<dd><p>indicates that the value is actually stored in the CPU flags (i.e. the
+value is the consequence of a test). The value is either 0 or 1. The
+actual CPU flags used is indicated in <code>SValue.c.i</code>.
+</p>
+<p>If any code is generated which destroys the CPU flags, this value MUST be
+put in a normal register.
+</p>
+</dd>
+<dt> <code>VT_JMP</code></dt>
+<dt> <code>VT_JMPI</code></dt>
+<dd><p>indicates that the value is the consequence of a conditional jump. For VT_JMP,
+it is 1 if the jump is taken, 0 otherwise. For VT_JMPI it is inverted.
+</p>
+<p>These values are used to compile the <code>||</code> and <code>&amp;&amp;</code> logical
+operators.
+</p>
+<p>If any code is generated, this value MUST be put in a normal
+register. Otherwise, the generated code won&rsquo;t be executed if the jump is
+taken.
+</p>
+</dd>
+<dt> <code>VT_LVAL</code></dt>
+<dd><p>is a flag indicating that the value is actually an lvalue (left value of
+an assignment). It means that the value stored is actually a pointer to
+the wanted value.
+</p>
+<p>Understanding the use <code>VT_LVAL</code> is very important if you want to
+understand how TCC works.
+</p>
+</dd>
+<dt> <code>VT_LVAL_BYTE</code></dt>
+<dt> <code>VT_LVAL_SHORT</code></dt>
+<dt> <code>VT_LVAL_UNSIGNED</code></dt>
+<dd><p>if the lvalue has an integer type, then these flags give its real
+type. The type alone is not enough in case of cast optimisations.
+</p>
+</dd>
+<dt> <code>VT_LLOCAL</code></dt>
+<dd><p>is a saved lvalue on the stack. <code>VT_LLOCAL</code> should be eliminated
+ASAP because its semantics are rather complicated.
+</p>
+</dd>
+<dt> <code>VT_MUSTCAST</code></dt>
+<dd><p>indicates that a cast to the value type must be performed if the value
+is used (lazy casting).
+</p>
+</dd>
+<dt> <code>VT_SYM</code></dt>
+<dd><p>indicates that the symbol <code>SValue.sym</code> must be added to the constant.
+</p>
+</dd>
+<dt> <code>VT_MUSTBOUND</code></dt>
+<dt> <code>VT_BOUNDED</code></dt>
+<dd><p>are only used for optional bound checking.
+</p>
+</dd>
+</dl>
+
+<hr size="6">
+<a name="Manipulating-the-value-stack"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#The-value-stack" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#CPU-dependent-code-generation" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Code-generation" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h3 class="subsection">8.7.3 Manipulating the value stack</h3>
+<a name="index-value-stack"></a>
+
+<p><code>vsetc()</code> and <code>vset()</code> pushes a new value on the value
+stack. If the previous <var>vtop</var> was stored in a very unsafe place(for
+example in the CPU flags), then some code is generated to put the
+previous <var>vtop</var> in a safe storage.
+</p>
+<p><code>vpop()</code> pops <var>vtop</var>. In some cases, it also generates cleanup
+code (for example if stacked floating point registers are used as on
+x86).
+</p>
+<p>The <code>gv(rc)</code> function generates code to evaluate <var>vtop</var> (the
+top value of the stack) into registers. <var>rc</var> selects in which
+register class the value should be put. <code>gv()</code> is the <em>most
+important function</em> of the code generator.
+</p>
+<p><code>gv2()</code> is the same as <code>gv()</code> but for the top two stack
+entries.
+</p>
+<hr size="6">
+<a name="CPU-dependent-code-generation"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Manipulating-the-value-stack" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Optimizations-done" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Code-generation" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h3 class="subsection">8.7.4 CPU dependent code generation</h3>
+<a name="index-CPU-dependent"></a>
+<p>See the &lsquo;<tt>i386-gen.c</tt>&rsquo; file to have an example.
+</p>
+<dl compact="compact">
+<dt> <code>load()</code></dt>
+<dd><p>must generate the code needed to load a stack value into a register.
+</p>
+</dd>
+<dt> <code>store()</code></dt>
+<dd><p>must generate the code needed to store a register into a stack value
+lvalue.
+</p>
+</dd>
+<dt> <code>gfunc_start()</code></dt>
+<dt> <code>gfunc_param()</code></dt>
+<dt> <code>gfunc_call()</code></dt>
+<dd><p>should generate a function call
+</p>
+</dd>
+<dt> <code>gfunc_prolog()</code></dt>
+<dt> <code>gfunc_epilog()</code></dt>
+<dd><p>should generate a function prolog/epilog.
+</p>
+</dd>
+<dt> <code>gen_opi(op)</code></dt>
+<dd><p>must generate the binary integer operation <var>op</var> on the two top
+entries of the stack which are guaranted to contain integer types.
+</p>
+<p>The result value should be put on the stack.
+</p>
+</dd>
+<dt> <code>gen_opf(op)</code></dt>
+<dd><p>same as <code>gen_opi()</code> for floating point operations. The two top
+entries of the stack are guaranted to contain floating point values of
+same types.
+</p>
+</dd>
+<dt> <code>gen_cvt_itof()</code></dt>
+<dd><p>integer to floating point conversion.
+</p>
+</dd>
+<dt> <code>gen_cvt_ftoi()</code></dt>
+<dd><p>floating point to integer conversion.
+</p>
+</dd>
+<dt> <code>gen_cvt_ftof()</code></dt>
+<dd><p>floating point to floating point of different size conversion.
+</p>
+</dd>
+<dt> <code>gen_bounded_ptr_add()</code></dt>
+<dt> <code>gen_bounded_ptr_deref()</code></dt>
+<dd><p>are only used for bounds checking.
+</p>
+</dd>
+</dl>
+
+<hr size="6">
+<a name="Optimizations-done"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#CPU-dependent-code-generation" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h2 class="section">8.8 Optimizations done</h2>
+<a name="index-optimizations"></a>
+<a name="index-constant-propagation"></a>
+<a name="index-strength-reduction"></a>
+<a name="index-comparison-operators"></a>
+<a name="index-caching-processor-flags"></a>
+<a name="index-flags_002c-caching"></a>
+<a name="index-jump-optimization"></a>
+<p>Constant propagation is done for all operations. Multiplications and
+divisions are optimized to shifts when appropriate. Comparison
+operators are optimized by maintaining a special cache for the
+processor flags. &amp;&amp;, || and ! are optimized by maintaining a special
+&rsquo;jump target&rsquo; value. No other jump optimization is currently performed
+because it would require to store the code in a more abstract fashion.
+</p>
+<hr size="6">
+<a name="Concept-Index"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Optimizations-done" title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[ &gt; ]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td>
+<td valign="middle" align="left">[ &gt;&gt; ]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h1 class="unnumbered">Concept Index</h1>
+<table><tr><th valign="top">Jump to: &nbsp; </th><td><a href="#Concept-Index_cp_symbol-1" class="summary-letter"><b>_</b></a>
+ &nbsp;
+<br>
+<a href="#Concept-Index_cp_letter-A" class="summary-letter"><b>A</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-B" class="summary-letter"><b>B</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-C" class="summary-letter"><b>C</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-D" class="summary-letter"><b>D</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-E" class="summary-letter"><b>E</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-F" class="summary-letter"><b>F</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-G" class="summary-letter"><b>G</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-I" class="summary-letter"><b>I</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-J" class="summary-letter"><b>J</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-L" class="summary-letter"><b>L</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-M" class="summary-letter"><b>M</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-O" class="summary-letter"><b>O</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-P" class="summary-letter"><b>P</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-Q" class="summary-letter"><b>Q</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-R" class="summary-letter"><b>R</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-S" class="summary-letter"><b>S</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-T" class="summary-letter"><b>T</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-U" class="summary-letter"><b>U</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-V" class="summary-letter"><b>V</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-W" class="summary-letter"><b>W</b></a>
+ &nbsp;
+</td></tr></table>
+<table border="0" class="index-cp">
+<tr><td></td><th align="left">Index Entry</th><th align="left"> Section</th></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_symbol-1">_</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-_005f_005fasm_005f_005f">__asm__</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-A">A</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-align-directive">align directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-aligned-attribute">aligned attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-ascii-directive">ascii directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-asciz-directive">asciz directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-assembler">assembler</a></td><td valign="top"><a href="#X86-Assembler">4.5 X86 Assembler</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-assembler-directives">assembler directives</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-assembly_002c-inline">assembly, inline</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-B">B</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-bound-checks">bound checks</a></td><td valign="top"><a href="#Bounds">6. TinyCC Memory and Bound checks</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-bss-directive">bss directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-byte-directive">byte directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-C">C</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-caching-processor-flags">caching processor flags</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-cdecl-attribute">cdecl attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-code-generation">code generation</a></td><td valign="top"><a href="#Code-generation">8.7 Code generation</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-comparison-operators">comparison operators</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-constant-propagation">constant propagation</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-CPU-dependent">CPU dependent</a></td><td valign="top"><a href="#CPU-dependent-code-generation">8.7.4 CPU dependent code generation</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-D">D</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-data-directive">data directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-directives_002c-assembler">directives, assembler</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-dllexport-attribute">dllexport attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-E">E</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-ELF">ELF</a></td><td valign="top"><a href="#ELF-file-generation">5.1 ELF file generation</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-F">F</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-FILE_002c-linker-command">FILE, linker command</a></td><td valign="top"><a href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-fill-directive">fill directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-flags_002c-caching">flags, caching</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-G">G</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-gas">gas</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-global-directive">global directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-globl-directive">globl directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-GROUP_002c-linker-command">GROUP, linker command</a></td><td valign="top"><a href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-I">I</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-inline-assembly">inline assembly</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-int-directive">int directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-J">J</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-jump-optimization">jump optimization</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-L">L</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-linker">linker</a></td><td valign="top"><a href="#linker">5. TinyCC Linker</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-linker-scripts">linker scripts</a></td><td valign="top"><a href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-long-directive">long directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-M">M</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-memory-checks">memory checks</a></td><td valign="top"><a href="#Bounds">6. TinyCC Memory and Bound checks</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-O">O</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-optimizations">optimizations</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-org-directive">org directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-OUTPUT_005fFORMAT_002c-linker-command">OUTPUT_FORMAT, linker command</a></td><td valign="top"><a href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-P">P</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-packed-attribute">packed attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-PE_002di386">PE-i386</a></td><td valign="top"><a href="#PE_002di386-file-generation">5.3 PE-i386 file generation</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-previous-directive">previous directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-Q">Q</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-quad-directive">quad directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-R">R</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-regparm-attribute">regparm attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-S">S</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-scripts_002c-linker">scripts, linker</a></td><td valign="top"><a href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-section-attribute">section attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-section-directive">section directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-short-directive">short directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-skip-directive">skip directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-space-directive">space directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-stdcall-attribute">stdcall attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-strength-reduction">strength reduction</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-string-directive">string directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-T">T</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-TARGET_002c-linker-command">TARGET, linker command</a></td><td valign="top"><a href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-text-directive">text directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-U">U</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-unused-attribute">unused attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-V">V</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-value-stack">value stack</a></td><td valign="top"><a href="#Manipulating-the-value-stack">8.7.3 Manipulating the value stack</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-value-stack_002c-introduction">value stack, introduction</a></td><td valign="top"><a href="#The-value-stack">8.7.2 The value stack</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+<tr><th><a name="Concept-Index_cp_letter-W">W</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-word-directive">word directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr>
+<tr><td colspan="3"> <hr></td></tr>
+</table>
+<table><tr><th valign="top">Jump to: &nbsp; </th><td><a href="#Concept-Index_cp_symbol-1" class="summary-letter"><b>_</b></a>
+ &nbsp;
+<br>
+<a href="#Concept-Index_cp_letter-A" class="summary-letter"><b>A</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-B" class="summary-letter"><b>B</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-C" class="summary-letter"><b>C</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-D" class="summary-letter"><b>D</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-E" class="summary-letter"><b>E</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-F" class="summary-letter"><b>F</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-G" class="summary-letter"><b>G</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-I" class="summary-letter"><b>I</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-J" class="summary-letter"><b>J</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-L" class="summary-letter"><b>L</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-M" class="summary-letter"><b>M</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-O" class="summary-letter"><b>O</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-P" class="summary-letter"><b>P</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-Q" class="summary-letter"><b>Q</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-R" class="summary-letter"><b>R</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-S" class="summary-letter"><b>S</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-T" class="summary-letter"><b>T</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-U" class="summary-letter"><b>U</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-V" class="summary-letter"><b>V</b></a>
+ &nbsp;
+<a href="#Concept-Index_cp_letter-W" class="summary-letter"><b>W</b></a>
+ &nbsp;
+</td></tr></table>
+
+<hr size="6">
+<a name="SEC_Contents"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h1>Table of Contents</h1>
+<div class="contents">
+
+<ul class="toc">
+ <li><a name="toc-Introduction-1" href="#Introduction">1. Introduction</a></li>
+ <li><a name="toc-Command-line-invocation" href="#Invoke">2. Command line invocation</a>
+ <ul class="toc">
+ <li><a name="toc-Quick-start" href="#Quick-start">2.1 Quick start</a></li>
+ <li><a name="toc-Option-summary" href="#Option-summary">2.2 Option summary</a></li>
+ </ul></li>
+ <li><a name="toc-C-language-support" href="#Clang">3. C language support</a>
+ <ul class="toc">
+ <li><a name="toc-ANSI-C" href="#ANSI-C">3.1 ANSI C</a></li>
+ <li><a name="toc-ISOC99-extensions" href="#ISOC99-extensions">3.2 ISOC99 extensions</a></li>
+ <li><a name="toc-GNU-C-extensions" href="#GNU-C-extensions">3.3 GNU C extensions</a></li>
+ <li><a name="toc-TinyCC-extensions" href="#TinyCC-extensions">3.4 TinyCC extensions</a></li>
+ </ul></li>
+ <li><a name="toc-TinyCC-Assembler" href="#asm">4. TinyCC Assembler</a>
+ <ul class="toc">
+ <li><a name="toc-Syntax" href="#Syntax">4.1 Syntax</a></li>
+ <li><a name="toc-Expressions" href="#Expressions">4.2 Expressions</a></li>
+ <li><a name="toc-Labels" href="#Labels">4.3 Labels</a></li>
+ <li><a name="toc-Directives" href="#Directives">4.4 Directives</a></li>
+ <li><a name="toc-X86-Assembler" href="#X86-Assembler">4.5 X86 Assembler</a></li>
+ </ul></li>
+ <li><a name="toc-TinyCC-Linker" href="#linker">5. TinyCC Linker</a>
+ <ul class="toc">
+ <li><a name="toc-ELF-file-generation" href="#ELF-file-generation">5.1 ELF file generation</a></li>
+ <li><a name="toc-ELF-file-loader" href="#ELF-file-loader">5.2 ELF file loader</a></li>
+ <li><a name="toc-PE_002di386-file-generation" href="#PE_002di386-file-generation">5.3 PE-i386 file generation</a></li>
+ <li><a name="toc-GNU-Linker-Scripts" href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></li>
+ </ul></li>
+ <li><a name="toc-TinyCC-Memory-and-Bound-checks" href="#Bounds">6. TinyCC Memory and Bound checks</a></li>
+ <li><a name="toc-The-libtcc-library" href="#Libtcc">7. The <code>libtcc</code> library</a></li>
+ <li><a name="toc-Developer_0027s-guide" href="#devel">8. Developer&rsquo;s guide</a>
+ <ul class="toc">
+ <li><a name="toc-File-reading" href="#File-reading">8.1 File reading</a></li>
+ <li><a name="toc-Lexer" href="#Lexer">8.2 Lexer</a></li>
+ <li><a name="toc-Parser" href="#Parser">8.3 Parser</a></li>
+ <li><a name="toc-Types" href="#Types">8.4 Types</a></li>
+ <li><a name="toc-Symbols" href="#Symbols">8.5 Symbols</a></li>
+ <li><a name="toc-Sections" href="#Sections">8.6 Sections</a></li>
+ <li><a name="toc-Code-generation" href="#Code-generation">8.7 Code generation</a>
+ <ul class="toc">
+ <li><a name="toc-Introduction-2" href="#Introduction-2">8.7.1 Introduction</a></li>
+ <li><a name="toc-The-value-stack" href="#The-value-stack">8.7.2 The value stack</a></li>
+ <li><a name="toc-Manipulating-the-value-stack" href="#Manipulating-the-value-stack">8.7.3 Manipulating the value stack</a></li>
+ <li><a name="toc-CPU-dependent-code-generation" href="#CPU-dependent-code-generation">8.7.4 CPU dependent code generation</a></li>
+ </ul></li>
+ <li><a name="toc-Optimizations-done" href="#Optimizations-done">8.8 Optimizations done</a></li>
+ </ul></li>
+ <li><a name="toc-Concept-Index" href="#Concept-Index">Concept Index</a></li>
+</ul>
+</div>
+<hr size="1">
+<a name="SEC_About"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td>
+</tr></table>
+<h1>About This Document</h1>
+<p>
+ This document was generated by <em>Thomas Preud'homme</em> on <em>February 15, 2013</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html 1.82</em></a>.
+</p>
+<p>
+ The buttons in the navigation panels have the following meaning:
+</p>
+<table border="1">
+ <tr>
+ <th> Button </th>
+ <th> Name </th>
+ <th> Go to </th>
+ <th> From 1.2.3 go to</th>
+ </tr>
+ <tr>
+ <td align="center"> [ &lt; ] </td>
+ <td align="center">Back</td>
+ <td>Previous section in reading order</td>
+ <td>1.2.2</td>
+ </tr>
+ <tr>
+ <td align="center"> [ &gt; ] </td>
+ <td align="center">Forward</td>
+ <td>Next section in reading order</td>
+ <td>1.2.4</td>
+ </tr>
+ <tr>
+ <td align="center"> [ &lt;&lt; ] </td>
+ <td align="center">FastBack</td>
+ <td>Beginning of this chapter or previous chapter</td>
+ <td>1</td>
+ </tr>
+ <tr>
+ <td align="center"> [ Up ] </td>
+ <td align="center">Up</td>
+ <td>Up section</td>
+ <td>1.2</td>
+ </tr>
+ <tr>
+ <td align="center"> [ &gt;&gt; ] </td>
+ <td align="center">FastForward</td>
+ <td>Next chapter</td>
+ <td>2</td>
+ </tr>
+ <tr>
+ <td align="center"> [Top] </td>
+ <td align="center">Top</td>
+ <td>Cover (top) of document</td>
+ <td> &nbsp; </td>
+ </tr>
+ <tr>
+ <td align="center"> [Contents] </td>
+ <td align="center">Contents</td>
+ <td>Table of contents</td>
+ <td> &nbsp; </td>
+ </tr>
+ <tr>
+ <td align="center"> [Index] </td>
+ <td align="center">Index</td>
+ <td>Index</td>
+ <td> &nbsp; </td>
+ </tr>
+ <tr>
+ <td align="center"> [ ? ] </td>
+ <td align="center">About</td>
+ <td>About (help)</td>
+ <td> &nbsp; </td>
+ </tr>
+</table>
+
+<p>
+ where the <strong> Example </strong> assumes that the current position is at <strong> Subsubsection One-Two-Three </strong> of a document of the following structure:
+</p>
+
+<ul>
+ <li> 1. Section One
+ <ul>
+ <li>1.1 Subsection One-One
+ <ul>
+ <li>...</li>
+ </ul>
+ </li>
+ <li>1.2 Subsection One-Two
+ <ul>
+ <li>1.2.1 Subsubsection One-Two-One</li>
+ <li>1.2.2 Subsubsection One-Two-Two</li>
+ <li>1.2.3 Subsubsection One-Two-Three &nbsp; &nbsp;
+ <strong>&lt;== Current Position </strong></li>
+ <li>1.2.4 Subsubsection One-Two-Four</li>
+ </ul>
+ </li>
+ <li>1.3 Subsection One-Three
+ <ul>
+ <li>...</li>
+ </ul>
+ </li>
+ <li>1.4 Subsection One-Four</li>
+ </ul>
+ </li>
+</ul>
+
+<hr size="1">
+<p>
+ <font size="-1">
+ This document was generated by <em>Thomas Preud'homme</em> on <em>February 15, 2013</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html 1.82</em></a>.
+ </font>
+ <br>
+
+</p>
+</body>
+</html>
diff --git a/tcc-doc.texi b/tcc-doc.texi
index 4d4a029..42ca806 100644
--- a/tcc-doc.texi
+++ b/tcc-doc.texi
@@ -68,7 +68,7 @@ ports for the ARM (@code{arm-tcc}) and the TMS320C67xx targets
(@code{c67-tcc}). More information about the ARM port is available at
@url{http://lists.gnu.org/archive/html/tinycc-devel/2003-10/msg00044.html}.
-For usage on Windows, see also tcc-win32.txt.
+For usage on Windows, see also @url{tcc-win32.txt}.
@node Invoke
@chapter Command line invocation
@@ -157,47 +157,41 @@ General Options:
@c man begin OPTIONS
@table @option
-@item -v
-Display current TCC version, increase verbosity.
-
-@item -print-search-dirs
-Print the name of the configured installation directory and a list
-of program and library directories tcc will search.
-
@item -c
Generate an object file.
@item -o outfile
Put object file, executable, or dll into output file @file{outfile}.
-@item -Bdir
-Set the path where the tcc internal libraries can be found (default is
-@file{PREFIX/lib/tcc}).
-
-@item -bench
-Output compilation statistics.
-
@item -run source [args...]
Compile file @var{source} and run it with the command line arguments
@var{args}. In order to be able to give more than one argument to a
script, several TCC options can be given @emph{after} the
-@option{-run} option, separated by spaces. Example:
-
+@option{-run} option, separated by spaces:
@example
tcc "-run -L/usr/X11R6/lib -lX11" ex4.c
@end example
-
In a script, it gives the following header:
-
@example
#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11
-#include <stdlib.h>
-int main(int argc, char **argv)
-@{
- ...
-@}
@end example
+@item -dumpversion
+Print only the compiler version and nothing else.
+
+@item -v
+Display TCC version.
+
+@item -vv
+Show included files. As sole argument, print search dirs (as below).
+
+@item -bench
+Display compilation statistics.
+
+@item -print-search-dirs
+Print the configured installation directory and a list of library
+and include directories tcc will search.
+
@end table
Preprocessor options:
@@ -284,6 +278,10 @@ Link your program with dynamic library libxxx.so or static library
libxxx.a. The library is searched in the paths specified by the
@option{-L} option.
+@item -Bdir
+Set the path where the tcc internal libraries (and include files) can be
+found (default is @file{PREFIX/lib/tcc}).
+
@item -shared
Generate a shared library instead of an executable.
@@ -301,10 +299,10 @@ opened with @code{dlopen()} needs to access executable symbols.
@item -r
Generate an object file combining all input files.
-@item -Wl,-Ttext,address
-Set the start of the .text section to @var{address}.
+@item -Wl,-rpath=path
+Put custom seatch path for dynamic libraries into executable.
-@item -Wl,--oformat,fmt
+@item -Wl,--oformat=fmt
Use @var{fmt} as output format. The supported output formats are:
@table @code
@item elf32-i386
@@ -315,8 +313,14 @@ Binary image (only for executable output)
COFF output format (only for executable output for TMS320C67xx target)
@end table
-@item -Wl,-rpath=path
-Set custom library search path
+@item -Wl,-subsystem=console/gui/wince/...
+Set type for PE (Windows) executables.
+
+@item -Wl,-[Ttext=# | section-alignment=# | file-alignment=# | image-base=# | stack=#]
+Modify executable layout.
+
+@item -Wl,-Bsymbolic
+Set DT_SYMBOLIC tag.
@end table
@@ -342,6 +346,17 @@ Display N callers in stack traces. This is useful with @option{-g} or
@end table
+Misc options:
+
+@table @option
+@item -MD
+Generate makefile fragment with dependencies.
+
+@item -MF depfile
+Use @file{depfile} as output for -MD.
+
+@end table
+
Note: GCC options @option{-Ox}, @option{-fx} and @option{-mx} are
ignored.
@c man end
diff --git a/tcc.c b/tcc.c
index 5dd5725..cd306b0 100644
--- a/tcc.c
+++ b/tcc.c
@@ -24,37 +24,22 @@
#include "tcc.h"
#endif
-static char **files;
-static int nb_files, nb_libraries;
-static int multiple_files;
-static int print_search_dirs;
-static int output_type;
-static int reloc_output;
-static char *outfile;
-static int do_bench = 0;
-static int gen_deps;
-static const char *deps_outfile;
-static const char *m_option;
-static CString linker_arg;
-
-#define TCC_OPTION_HAS_ARG 0x0001
-#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
-
static void help(void)
{
printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
"Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
" tcc [options...] -run infile [arguments...]\n"
"General options:\n"
- " -v display current version, increase verbosity\n"
" -c compile only - generate an object file\n"
" -o outfile set output filename\n"
- " -Bdir set tcc internal library and include path\n"
- " -bench output compilation statistics\n"
" -run run compiled source\n"
" -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
" -w disable all warnings\n"
+ " -v show version\n"
+ " -vv show included files (as sole argument: show search paths)\n"
+ " -dumpversion\n"
+ " -bench show compilation statistics\n"
"Preprocessor options:\n"
" -E preprocess only\n"
" -Idir add include path 'dir'\n"
@@ -64,11 +49,12 @@ static void help(void)
" -Ldir add library path 'dir'\n"
" -llib link with dynamic or static library 'lib'\n"
" -pthread link with -lpthread and -D_REENTRANT (POSIX Linux)\n"
+ " -r generate (relocatable) object file\n"
+ " -rdynamic export all global symbols to dynamic linker\n"
" -shared generate a shared library\n"
" -soname set name for shared library to be used at runtime\n"
" -static static linking\n"
- " -rdynamic export all global symbols to dynamic linker\n"
- " -r generate (relocatable) object file\n"
+ " -Wl,-opt[=val] set linker option (see manual)\n"
"Debugger options:\n"
" -g generate runtime debug info\n"
#ifdef CONFIG_TCC_BCHECK
@@ -78,146 +64,14 @@ static void help(void)
" -bt N show N callers in stack traces\n"
#endif
"Misc options:\n"
+ " -nostdinc do not use standard system include paths\n"
+ " -nostdlib do not link with standard crt and libraries\n"
+ " -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"
);
}
-typedef struct TCCOption {
- const char *name;
- uint16_t index;
- uint16_t flags;
-} TCCOption;
-
-enum {
- TCC_OPTION_HELP,
- TCC_OPTION_I,
- TCC_OPTION_D,
- TCC_OPTION_U,
- TCC_OPTION_L,
- TCC_OPTION_B,
- TCC_OPTION_l,
- TCC_OPTION_bench,
- TCC_OPTION_bt,
- TCC_OPTION_b,
- TCC_OPTION_g,
- TCC_OPTION_c,
- TCC_OPTION_static,
- TCC_OPTION_shared,
- TCC_OPTION_soname,
- TCC_OPTION_o,
- TCC_OPTION_r,
- TCC_OPTION_s,
- TCC_OPTION_Wl,
- TCC_OPTION_W,
- TCC_OPTION_O,
- TCC_OPTION_m,
- TCC_OPTION_f,
- TCC_OPTION_isystem,
- TCC_OPTION_nostdinc,
- TCC_OPTION_nostdlib,
- TCC_OPTION_print_search_dirs,
- TCC_OPTION_rdynamic,
- TCC_OPTION_pedantic,
- TCC_OPTION_pthread,
- TCC_OPTION_run,
- TCC_OPTION_v,
- TCC_OPTION_w,
- TCC_OPTION_pipe,
- TCC_OPTION_E,
- TCC_OPTION_MD,
- TCC_OPTION_MF,
- TCC_OPTION_x,
-};
-
-static const TCCOption tcc_options[] = {
- { "h", TCC_OPTION_HELP, 0 },
- { "-help", TCC_OPTION_HELP, 0 },
- { "?", TCC_OPTION_HELP, 0 },
- { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
- { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
- { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
- { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
- { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
- { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "bench", TCC_OPTION_bench, 0 },
-#ifdef CONFIG_TCC_BACKTRACE
- { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
-#endif
-#ifdef CONFIG_TCC_BCHECK
- { "b", TCC_OPTION_b, 0 },
-#endif
- { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "c", TCC_OPTION_c, 0 },
- { "static", TCC_OPTION_static, 0 },
- { "shared", TCC_OPTION_shared, 0 },
- { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
- { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
- { "pedantic", TCC_OPTION_pedantic, 0},
- { "pthread", TCC_OPTION_pthread, 0},
- { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "rdynamic", TCC_OPTION_rdynamic, 0 },
- { "r", TCC_OPTION_r, 0 },
- { "s", TCC_OPTION_s, 0 },
- { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
- { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "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 },
- { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "w", TCC_OPTION_w, 0 },
- { "pipe", TCC_OPTION_pipe, 0},
- { "E", TCC_OPTION_E, 0},
- { "MD", TCC_OPTION_MD, 0},
- { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
- { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
- { NULL },
-};
-
-static int64_t getclock_us(void)
-{
-#ifdef _WIN32
- struct _timeb tb;
- _ftime(&tb);
- return (tb.time * 1000LL + tb.millitm) * 1000LL;
-#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec * 1000000LL + tv.tv_usec;
-#endif
-}
-
-/* convert 'str' into an array of space separated strings */
-static int expand_args(char ***pargv, const char *str)
-{
- const char *s1;
- char **argv, *arg;
- int argc, len;
-
- argc = 0;
- argv = NULL;
- for(;;) {
- while (is_space(*str))
- str++;
- if (*str == '\0')
- break;
- s1 = str;
- while (*str != '\0' && !is_space(*str))
- str++;
- len = str - s1;
- arg = tcc_malloc(len + 1);
- memcpy(arg, s1, len);
- arg[len] = '\0';
- dynarray_add((void ***)&argv, &argc, arg);
- }
- *pargv = argv;
- return argc;
-}
-
/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
#ifdef _WIN32
@@ -262,308 +116,199 @@ static void exec_other_tcc(TCCState *s, char **argv, const char *optarg)
tcc_warning("unsupported option \"-m%s\"", optarg);
}
}
+#else
+#define exec_other_tcc(s, argv, optarg)
#endif
-static void parse_option_D(TCCState *s1, const char *optarg)
+static void gen_makedeps(TCCState *s, const char *target, const char *filename)
{
- char *sym = tcc_strdup(optarg);
- char *value = strchr(sym, '=');
- if (value)
- *value++ = '\0';
- tcc_define_symbol(s1, sym, value);
- tcc_free(sym);
-}
+ FILE *depout;
+ char buf[1024], *ext;
+ int i;
-static int parse_args(TCCState *s, int argc, char **argv)
-{
- int optind;
- const TCCOption *popt;
- const char *optarg, *p1, *r1;
- char *r;
- int was_pthread;
+ if (!filename) {
+ /* compute filename automatically
+ * dir/file.o -> dir/file.d */
+ pstrcpy(buf, sizeof(buf), target);
+ ext = tcc_fileextension(buf);
+ pstrcpy(ext, sizeof(buf) - (ext-buf), ".d");
+ filename = buf;
+ }
- was_pthread = 0; /* is set if commandline contains -pthread key */
- optind = 0;
- cstr_new(&linker_arg);
+ if (s->verbose)
+ printf("<- %s\n", filename);
+
+ /* XXX return err codes instead of error() ? */
+ depout = fopen(filename, "w");
+ if (!depout)
+ tcc_error("could not open '%s'", filename);
+
+ fprintf(depout, "%s : \\\n", target);
+ for (i=0; i<s->nb_target_deps; ++i)
+ fprintf(depout, " %s \\\n", s->target_deps[i]);
+ fprintf(depout, "\n");
+ fclose(depout);
+}
- while (optind < argc) {
+static char *default_outputfile(TCCState *s, const char *first_file)
+{
+ char buf[1024];
+ char *ext;
+ const char *name = "a";
+
+ if (first_file && strcmp(first_file, "-"))
+ name = tcc_basename(first_file);
+ pstrcpy(buf, sizeof(buf), name);
+ ext = tcc_fileextension(buf);
+#ifdef TCC_TARGET_PE
+ if (s->output_type == TCC_OUTPUT_DLL)
+ strcpy(ext, ".dll");
+ else
+ if (s->output_type == TCC_OUTPUT_EXE)
+ strcpy(ext, ".exe");
+ else
+#endif
+ if (( (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) ||
+ (s->output_type == TCC_OUTPUT_PREPROCESS) )
+ && *ext)
+ strcpy(ext, ".o");
+ else
+ strcpy(buf, "a.out");
+
+ return tcc_strdup(buf);
+}
- r = argv[optind++];
- if (r[0] != '-' || r[1] == '\0') {
- /* add a new file */
- dynarray_add((void ***)&files, &nb_files, r);
- if (!multiple_files) {
- optind--;
- /* argv[0] will be this file */
- break;
- }
- } else {
- /* find option in table (match only the first chars */
- popt = tcc_options;
- for(;;) {
- p1 = popt->name;
- if (p1 == NULL)
- tcc_error("invalid option -- '%s'", r);
- r1 = r + 1;
- for(;;) {
- if (*p1 == '\0')
- goto option_found;
- if (*r1 != *p1)
- break;
- p1++;
- r1++;
- }
- popt++;
- }
- option_found:
- if (popt->flags & TCC_OPTION_HAS_ARG) {
- if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
- optarg = r1;
- } else {
- if (optind >= argc)
- tcc_error("argument to '%s' is missing", r);
- optarg = argv[optind++];
- }
- } else {
- if (*r1 != '\0')
- return 0;
- optarg = NULL;
- }
-
- switch(popt->index) {
- case TCC_OPTION_HELP:
- return 0;
+static void print_paths(const char *msg, char **paths, int nb_paths)
+{
+ int i;
+ printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
+ for(i = 0; i < nb_paths; i++)
+ printf(" %s\n", paths[i]);
+}
- case TCC_OPTION_I:
- if (tcc_add_include_path(s, optarg) < 0)
- tcc_error("too many include paths");
- break;
- case TCC_OPTION_D:
- parse_option_D(s, optarg);
- break;
- case TCC_OPTION_U:
- tcc_undefine_symbol(s, optarg);
- break;
- case TCC_OPTION_L:
- tcc_add_library_path(s, optarg);
- break;
- case TCC_OPTION_B:
- /* set tcc utilities path (mainly for tcc development) */
- tcc_set_lib_path(s, optarg);
- break;
- case TCC_OPTION_l:
- dynarray_add((void ***)&files, &nb_files, r);
- nb_libraries++;
- break;
- case TCC_OPTION_pthread:
- was_pthread = 1;
- parse_option_D(s, "_REENTRANT");
- break;
- case TCC_OPTION_bench:
- do_bench = 1;
- break;
-#ifdef CONFIG_TCC_BACKTRACE
- case TCC_OPTION_bt:
- tcc_set_num_callers(atoi(optarg));
- break;
+static void display_info(TCCState *s, int what)
+{
+ switch (what) {
+ case 0:
+ printf("tcc version %s ("
+#ifdef TCC_TARGET_I386
+ "i386"
+# ifdef TCC_TARGET_PE
+ " Win32"
+# endif
+#elif defined TCC_TARGET_X86_64
+ "x86-64"
+# ifdef TCC_TARGET_PE
+ " Win64"
+# endif
+#elif defined TCC_TARGET_ARM
+ "ARM"
+# ifdef TCC_ARM_HARDFLOAT
+ " Hard Float"
+# endif
+# ifdef TCC_TARGET_PE
+ " WinCE"
+# endif
#endif
-#ifdef CONFIG_TCC_BCHECK
- case TCC_OPTION_b:
- s->do_bounds_check = 1;
- s->do_debug = 1;
- break;
+#ifndef TCC_TARGET_PE
+# ifdef __linux
+ " Linux"
+# endif
#endif
- case TCC_OPTION_g:
- s->do_debug = 1;
- break;
- case TCC_OPTION_c:
- multiple_files = 1;
- output_type = TCC_OUTPUT_OBJ;
- break;
- case TCC_OPTION_static:
- s->static_link = 1;
- break;
- case TCC_OPTION_shared:
- output_type = TCC_OUTPUT_DLL;
- break;
- case TCC_OPTION_soname:
- s->soname = optarg;
- break;
- case TCC_OPTION_m:
- m_option = optarg;
- break;
- case TCC_OPTION_o:
- multiple_files = 1;
- outfile = tcc_strdup(optarg);
- break;
- case TCC_OPTION_r:
- /* generate a .o merging several output files */
- reloc_output = 1;
- output_type = TCC_OUTPUT_OBJ;
- break;
- case TCC_OPTION_isystem:
- tcc_add_sysinclude_path(s, optarg);
- break;
- case TCC_OPTION_nostdinc:
- s->nostdinc = 1;
- break;
- case TCC_OPTION_nostdlib:
- s->nostdlib = 1;
- break;
- case TCC_OPTION_print_search_dirs:
- print_search_dirs = 1;
- break;
- case TCC_OPTION_run:
- {
- int argc1;
- char **argv1;
- argc1 = expand_args(&argv1, optarg);
- if (argc1 > 0) {
- parse_args(s, argc1, argv1);
- }
- multiple_files = 0;
- output_type = TCC_OUTPUT_MEMORY;
- break;
- }
- case TCC_OPTION_v:
- do ++s->verbose; while (*optarg++ == 'v');
- break;
- case TCC_OPTION_f:
- if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
- goto unsupported_option;
- break;
- case TCC_OPTION_W:
- if (tcc_set_warning(s, optarg, 1) < 0 &&
- s->warn_unsupported)
- goto unsupported_option;
- break;
- case TCC_OPTION_w:
- s->warn_none = 1;
- break;
- case TCC_OPTION_rdynamic:
- s->rdynamic = 1;
- break;
- case TCC_OPTION_Wl:
- if (linker_arg.size)
- --linker_arg.size, cstr_ccat(&linker_arg, ',');
- cstr_cat(&linker_arg, optarg);
- cstr_ccat(&linker_arg, '\0');
- break;
- case TCC_OPTION_E:
- output_type = TCC_OUTPUT_PREPROCESS;
- break;
- case TCC_OPTION_MD:
- gen_deps = 1;
- break;
- case TCC_OPTION_MF:
- deps_outfile = optarg;
- break;
- case TCC_OPTION_x:
- break;
- default:
- if (s->warn_unsupported) {
- unsupported_option:
- tcc_warning("unsupported option '%s'", r);
- }
- break;
- }
- }
- }
- if (NULL != (r1 = tcc_set_linker(s, (char *) linker_arg.data, TRUE)))
- tcc_error("unsupported linker option '%s'", r1);
- /* fixme: these options could be different on your platform */
- if (was_pthread && output_type != TCC_OUTPUT_OBJ) {
- dynarray_add((void ***)&files, &nb_files, "-lpthread");
- nb_libraries++;
+ ")\n", TCC_VERSION);
+ break;
+ case 1:
+ printf("install: %s/\n", s->tcc_lib_path);
+ /* print_paths("programs", NULL, 0); */
+ 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);
+ break;
}
- return optind;
+}
+
+static int64_t getclock_us(void)
+{
+#ifdef _WIN32
+ struct _timeb tb;
+ _ftime(&tb);
+ return (tb.time * 1000LL + tb.millitm) * 1000LL;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec * 1000000LL + tv.tv_usec;
+#endif
}
int main(int argc, char **argv)
{
- int i;
TCCState *s;
- int nb_objfiles, ret, optind;
+ int ret, optind, i, bench;
int64_t start_time = 0;
- const char *default_file = NULL;
+ const char *first_file = NULL;
s = tcc_new();
+ s->output_type = TCC_OUTPUT_EXE;
- output_type = TCC_OUTPUT_EXE;
- outfile = NULL;
- multiple_files = 1;
- files = NULL;
- nb_files = 0;
- nb_libraries = 0;
- reloc_output = 0;
- print_search_dirs = 0;
- m_option = NULL;
- ret = 0;
-
- optind = parse_args(s, argc - 1, argv + 1);
+ optind = tcc_parse_args(s, argc - 1, argv + 1);
-#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386
- if (m_option)
- exec_other_tcc(s, argv, m_option);
-#endif
-
- if (print_search_dirs) {
- /* enough for Linux kernel */
- printf("install: %s/\n", s->tcc_lib_path);
- return 0;
+ if (optind == 0) {
+ help();
+ return 1;
}
+ if (s->option_m)
+ exec_other_tcc(s, argv, s->option_m);
+
if (s->verbose)
- printf("tcc version %s\n", TCC_VERSION);
+ display_info(s, 0);
- if (optind == 0 || nb_files == 0) {
- if (optind && s->verbose)
- return 0;
- help();
- return 1;
+ if (s->print_search_dirs || (s->verbose == 2 && optind == 1)) {
+ tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
+ display_info(s, 1);
+ return 0;
}
- nb_objfiles = nb_files - nb_libraries;
+ if (s->verbose && optind == 1)
+ return 0;
- /* if outfile provided without other options, we output an
- executable */
- if (outfile && output_type == TCC_OUTPUT_MEMORY)
- output_type = TCC_OUTPUT_EXE;
+ if (s->nb_files == 0)
+ tcc_error("no input files\n");
/* check -c consistency : only single file handled. XXX: checks file type */
- if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
+ if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
+ if (s->nb_libraries != 0)
+ tcc_error("cannot specify libraries with -c");
/* accepts only a single input file */
- if (nb_objfiles != 1)
+ if (s->nb_files != 1)
tcc_error("cannot specify multiple files with -c");
- if (nb_libraries != 0)
- tcc_error("cannot specify libraries with -c");
}
- if (output_type == TCC_OUTPUT_PREPROCESS) {
- if (!outfile) {
- s->outfile = stdout;
+ if (s->output_type == TCC_OUTPUT_PREPROCESS) {
+ if (!s->outfile) {
+ s->ppfp = stdout;
} else {
- s->outfile = fopen(outfile, "w");
- if (!s->outfile)
- tcc_error("could not open '%s'", outfile);
+ s->ppfp = fopen(s->outfile, "w");
+ if (!s->ppfp)
+ tcc_error("could not write '%s'", s->outfile);
}
}
- if (do_bench) {
+ bench = s->do_bench;
+ if (bench)
start_time = getclock_us();
- }
- tcc_set_output_type(s, output_type);
- s->reloc_output = reloc_output;
+ tcc_set_output_type(s, s->output_type);
/* compile or add each files or library */
- for(i = 0; i < nb_files && ret == 0; i++) {
+ for(i = ret = 0; i < s->nb_files && ret == 0; i++) {
const char *filename;
- filename = files[i];
+ filename = s->files[i];
if (filename[0] == '-' && filename[1] == 'l') {
if (tcc_add_library(s, filename + 2) < 0) {
- tcc_error_noabort("cannot find %s", filename);
+ tcc_error_noabort("cannot find '%s'", filename);
ret = 1;
}
} else {
@@ -571,16 +316,13 @@ int main(int argc, char **argv)
printf("-> %s\n", filename);
if (tcc_add_file(s, filename) < 0)
ret = 1;
- if (!default_file)
- default_file = filename;
+ if (!first_file)
+ first_file = filename;
}
}
- /* free all files */
- tcc_free(files);
-
if (0 == ret) {
- if (do_bench)
+ if (bench)
tcc_print_stats(s, getclock_us() - start_time);
if (s->output_type == TCC_OUTPUT_MEMORY) {
@@ -588,28 +330,23 @@ int main(int argc, char **argv)
ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind);
#else
tcc_error_noabort("-run is not available in a cross compiler");
+ ret = 1;
#endif
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
if (s->outfile)
- fclose(s->outfile);
+ fclose(s->ppfp);
} else {
- if (!outfile)
- outfile = tcc_default_target(s, default_file);
- ret = !!tcc_output_file(s, outfile);
+ if (!s->outfile)
+ s->outfile = default_outputfile(s, first_file);
+ ret = !!tcc_output_file(s, s->outfile);
/* dump collected dependencies */
- if (gen_deps && !ret)
- tcc_gen_makedeps(s, outfile, deps_outfile);
+ if (s->gen_deps && !ret)
+ gen_makedeps(s, s->outfile, s->deps_outfile);
}
}
tcc_delete(s);
- cstr_free(&linker_arg);
- tcc_free(outfile);
-
-#ifdef MEM_DEBUG
- if (do_bench) {
- printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
- }
-#endif
+ if (bench)
+ tcc_memstats();
return ret;
}
diff --git a/tcc.h b/tcc.h
index 4e88782..2c2936c 100644
--- a/tcc.h
+++ b/tcc.h
@@ -25,10 +25,8 @@
#include "config.h"
#ifdef CONFIG_TCCBOOT
-
#include "tccboot.h"
#define CONFIG_TCC_STATIC
-
#else
#include <stdlib.h>
@@ -42,42 +40,60 @@
#include <setjmp.h>
#include <time.h>
-#ifdef _WIN32
-#include <windows.h>
-#include <sys/timeb.h>
-#include <io.h> /* open, close etc. */
-#include <direct.h> /* getcwd */
-#define inline __inline
-#define inp next_inp
-#ifdef LIBTCC_AS_DLL
-# define LIBTCCAPI __declspec(dllexport)
-# define PUB_FUNC LIBTCCAPI
-#endif
-#endif
-
#ifndef _WIN32
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/ucontext.h>
-#include <sys/mman.h>
-#include <dlfcn.h>
+# include <unistd.h>
+# include <sys/time.h>
+# include <sys/ucontext.h>
+# include <sys/mman.h>
+# ifndef CONFIG_TCC_STATIC
+# include <dlfcn.h>
+# endif
+#else
+# 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
+# ifdef LIBTCC_AS_DLL
+# define LIBTCCAPI __declspec(dllexport)
+# define PUB_FUNC LIBTCCAPI
+# endif
#endif
#endif /* !CONFIG_TCCBOOT */
-#ifndef PAGESIZE
-#define PAGESIZE 4096
-#endif
-
#ifndef O_BINARY
-#define O_BINARY 0
+# define O_BINARY 0
#endif
-#ifndef SA_SIGINFO
-#define SA_SIGINFO 0x00000004u
+#include "elf.h"
+#ifdef TCC_TARGET_X86_64
+# define ELFCLASSW ELFCLASS64
+# define ElfW(type) Elf##64##_##type
+# define ELFW(type) ELF##64##_##type
+# define ElfW_Rel ElfW(Rela)
+# define SHT_RELX SHT_RELA
+# define REL_SECTION_FMT ".rela%s"
+/* XXX: DLL with PLT would only work with x86-64 for now */
+# define TCC_OUTPUT_DLL_WITH_PLT
+#else
+# define ELFCLASSW ELFCLASS32
+# define ElfW(type) Elf##32##_##type
+# define ELFW(type) ELF##32##_##type
+# define ElfW_Rel ElfW(Rel)
+# define SHT_RELX SHT_REL
+# define REL_SECTION_FMT ".rel%s"
#endif
-#include "elf.h"
+/* target address type */
+#define addr_t ElfW(Addr)
+
#include "stab.h"
#include "libtcc.h"
@@ -87,9 +103,8 @@
//#define PP_DEBUG
/* include file debug */
//#define INC_DEBUG
-
+/* memory leak debug */
//#define MEM_DEBUG
-
/* assembler debug */
//#define ASM_DEBUG
@@ -105,23 +120,11 @@
#define TCC_TARGET_I386
#endif
-#if defined (TCC_TARGET_ARM) && !defined(TCC_ARM_VERSION)
- #ifdef TCC_ARM_HARDFLOAT
- #define TCC_ARM_VERSION 7
- #else
- #define TCC_ARM_VERSION 4
- #endif
-#endif
-
#if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
!defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)
#define CONFIG_TCC_BCHECK /* enable bound checking code */
#endif
-#if defined(_WIN32) && !defined(TCC_TARGET_PE)
-#define CONFIG_TCC_STATIC
-#endif
-
/* define it to include assembler support */
#if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
#define CONFIG_TCC_ASM
@@ -147,23 +150,14 @@
# define CONFIG_TCC_BACKTRACE
#endif
-/* target address type */
-#if defined TCC_TARGET_X86_64 && (!defined __x86_64__ || defined _WIN32)
-# define uplong unsigned long long
-#else
-# define uplong unsigned long
-#endif
-
/* ------------ path configuration ------------ */
#ifndef CONFIG_SYSROOT
# define CONFIG_SYSROOT ""
#endif
-
-#ifdef CONFIG_MULTIARCHDIR
-# define CONFIG_LDDIR "lib/" CONFIG_MULTIARCHDIR
+#ifndef CONFIG_TCCDIR
+# define CONFIG_TCCDIR "."
#endif
-
#ifndef CONFIG_LDDIR
# define CONFIG_LDDIR "lib"
#endif
@@ -220,6 +214,8 @@
# 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
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2"
# endif
@@ -229,12 +225,25 @@
#define TCC_LIBGCC CONFIG_SYSROOT "/" CONFIG_LDDIR "/libgcc_s.so.1"
/* -------------------------------------------- */
+/* include the target specific definitions */
+
+#define TARGET_DEFS_ONLY
+#ifdef TCC_TARGET_I386
+# include "i386-gen.c"
+#endif
+#ifdef TCC_TARGET_X86_64
+# include "x86_64-gen.c"
+#endif
+#ifdef TCC_TARGET_ARM
+# include "arm-gen.c"
+#endif
+#ifdef TCC_TARGET_C67
+# include "coff.h"
+# include "c67-gen.c"
+#endif
+#undef TARGET_DEFS_ONLY
-#define FALSE 0
-#define false 0
-#define TRUE 1
-#define true 1
-typedef int BOOL;
+/* -------------------------------------------- */
#define INCLUDE_STACK_SIZE 32
#define IFDEF_STACK_SIZE 64
@@ -289,7 +298,7 @@ typedef union CValue {
unsigned long long ull;
struct CString *cstr;
void *ptr;
- int tab[2];
+ int tab[LDOUBLE_SIZE/4];
} CValue;
/* value on stack */
@@ -341,7 +350,7 @@ typedef struct Section {
int sh_addralign; /* elf section alignment */
int sh_entsize; /* elf entry size */
unsigned long sh_size; /* section size (only used during output) */
- uplong sh_addr; /* address at which the section is relocated */
+ addr_t sh_addr; /* address at which the section is relocated */
unsigned long sh_offset; /* file offset */
int nb_hashed_syms; /* used to resize the hash table */
struct Section *link; /* link to another section */
@@ -426,9 +435,7 @@ typedef struct BufferedFile {
int ifndef_macro; /* #ifndef macro / #endif search */
int ifndef_macro_saved; /* saved ifndef_macro */
int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
- char inc_type; /* type of include */
- char inc_filename[512]; /* filename specified by the user */
- char filename[1024]; /* current filename - here to simplify code */
+ char filename[1024]; /* filename */
unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
} BufferedFile;
@@ -464,7 +471,6 @@ typedef struct InlineFunc {
typedef struct CachedInclude {
int ifndef_macro;
int hash_next; /* -1 if none */
- char type; /* '"' or '>' to give include type */
char filename[1]; /* path specified in #include */
} CachedInclude;
@@ -492,83 +498,30 @@ typedef struct ASMOperand {
} ASMOperand;
#endif
-struct TCCState {
- unsigned output_type : 8;
- unsigned reloc_output : 1;
-
- BufferedFile **include_stack_ptr;
- int *ifdef_stack_ptr;
-
- /* include file handling */
- char **include_paths;
- int nb_include_paths;
- char **sysinclude_paths;
- int nb_sysinclude_paths;
- CachedInclude **cached_includes;
- int nb_cached_includes;
-
- char **library_paths;
- int nb_library_paths;
- char **crt_paths;
- int nb_crt_paths;
-
- /* array of all loaded dlls (including those referenced by loaded
- dlls) */
- DLLReference **loaded_dlls;
- int nb_loaded_dlls;
-
- /* sections */
- Section **sections;
- int nb_sections; /* number of sections, including first dummy section */
-
- Section **priv_sections;
- int nb_priv_sections; /* number of private sections */
-
- /* got handling */
- Section *got;
- Section *plt;
- unsigned long *got_offsets;
- int nb_got_offsets;
- /* give the correspondance from symtab indexes to dynsym indexes */
- int *symtab_to_dynsym;
-
- /* temporary dynamic symbol sections (for dll loading) */
- Section *dynsymtab_section;
- /* exported dynamic symbol section */
- Section *dynsym;
+struct sym_attr {
+ unsigned long got_offset;
+#ifdef TCC_TARGET_ARM
+ unsigned char plt_thumb_stub:1;
+#endif
+};
- /* copy of the gobal symtab_section variable */
- Section *symtab;
+struct TCCState {
+ int verbose; /* if true, display some information during compilation */
int nostdinc; /* if true, no standard headers are added */
int nostdlib; /* if true, no standard libraries are added */
int nocommon; /* if true, do not use common symbols for .bss data */
+ int static_link; /* if true, static linking is performed */
+ int rdynamic; /* if true, all symbols are exported */
+ int symbolic; /* if true, resolve symbols in the current module first */
+ int alacarte_link; /* if true, only link in referenced objects from archive */
- /* if true, static linking is performed */
- int static_link;
-
- /* soname as specified on the command line (-soname) */
- const char *soname;
- /* rpath as specified on the command line (-Wl,-rpath=) */
- const char *rpath;
-
- /* if true, all symbols are exported */
- int rdynamic;
-
- /* if true, resolve symbols in the current module first (-Wl,Bsymbolic) */
- int symbolic;
-
- /* if true, only link in referenced objects from archive */
- int alacarte_link;
-
- /* address of text section */
- uplong text_addr;
- int has_text_addr;
+ char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
+ char *soname; /* as specified on the command line (-soname) */
+ char *rpath; /* as specified on the command line (-Wl,-rpath=) */
- /* symbols to call at load-time / unload-time */
- const char *init_symbol;
- const char *fini_symbol;
-
+ /* output type, see TCC_OUTPUT_XXX */
+ int output_type;
/* output format, see TCC_OUTPUT_FORMAT_xxx */
int output_format;
@@ -583,16 +536,43 @@ struct TCCState {
int warn_none;
int warn_implicit_function_declaration;
- /* display some information during compilation */
- int verbose;
/* compile with debug symbol (and use them if error during execution) */
int do_debug;
#ifdef CONFIG_TCC_BCHECK
/* compile with built-in memory and bounds checker */
int do_bounds_check;
#endif
- /* give the path of the tcc libraries */
- char *tcc_lib_path;
+
+ addr_t text_addr; /* address of text section */
+ int has_text_addr;
+
+ unsigned long section_align; /* section alignment */
+
+ char *init_symbol; /* symbols to call at load-time (not used currently) */
+ char *fini_symbol; /* symbols to call at unload-time (not used currently) */
+
+#ifdef TCC_TARGET_I386
+ int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */
+#endif
+
+ /* array of all loaded dlls (including those referenced by loaded dlls) */
+ DLLReference **loaded_dlls;
+ int nb_loaded_dlls;
+
+ /* include paths */
+ char **include_paths;
+ int nb_include_paths;
+
+ char **sysinclude_paths;
+ int nb_sysinclude_paths;
+
+ /* library paths */
+ char **library_paths;
+ int nb_library_paths;
+
+ /* crt?.o object path */
+ char **crt_paths;
+ int nb_crt_paths;
/* error handling */
void *error_opaque;
@@ -601,72 +581,101 @@ struct TCCState {
jmp_buf error_jmp_buf;
int nb_errors;
- /* tiny assembler state */
- Sym *asm_labels;
+ /* output file for preprocessing (-E) */
+ FILE *ppfp;
+
+ /* for -MD/-MF: collected dependencies for this compilation */
+ char **target_deps;
+ int nb_target_deps;
- /* see include_stack_ptr */
+ /* compilation */
BufferedFile *include_stack[INCLUDE_STACK_SIZE];
+ BufferedFile **include_stack_ptr;
- /* see ifdef_stack_ptr */
int ifdef_stack[IFDEF_STACK_SIZE];
+ int *ifdef_stack_ptr;
- /* see cached_includes */
+ /* included files enclosed with #ifndef MACRO */
int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
+ CachedInclude **cached_includes;
+ int nb_cached_includes;
- /* pack stack */
+ /* #pragma pack stack */
int pack_stack[PACK_STACK_SIZE];
int *pack_stack_ptr;
- /* output file for preprocessing */
- FILE *outfile;
-
- /* automatically collected dependencies for this compilation */
- char **target_deps;
- int nb_target_deps;
-
- /* for tcc_relocate */
- int runtime_added;
- void *runtime_mem;
-#ifdef HAVE_SELINUX
- void *write_mem;
- unsigned long mem_size;
-#endif
-
+ /* inline functions are stored as token lists and compiled last
+ only if referenced */
struct InlineFunc **inline_fns;
int nb_inline_fns;
-#ifdef TCC_TARGET_I386
- int seg_size;
-#endif
+ /* sections */
+ Section **sections;
+ int nb_sections; /* number of sections, including first dummy section */
+
+ Section **priv_sections;
+ int nb_priv_sections; /* number of private sections */
+
+ /* got & plt handling */
+ Section *got;
+ Section *plt;
+ struct sym_attr *sym_attrs;
+ int nb_sym_attrs;
+ /* give the correspondance from symtab indexes to dynsym indexes */
+ int *symtab_to_dynsym;
- /* section alignment */
- unsigned long section_align;
+ /* temporary dynamic symbol sections (for dll loading) */
+ Section *dynsymtab_section;
+ /* exported dynamic symbol section */
+ Section *dynsym;
+ /* copy of the gobal symtab_section variable */
+ Section *symtab;
+ /* tiny assembler state */
+ Sym *asm_labels;
#ifdef TCC_TARGET_PE
/* PE info */
int pe_subsystem;
- unsigned long pe_file_align;
- unsigned long pe_stack_size;
-#ifdef TCC_TARGET_X86_64
+ unsigned pe_file_align;
+ unsigned pe_stack_size;
+# ifdef TCC_TARGET_X86_64
Section *uw_pdata;
int uw_sym;
unsigned uw_offs;
-#endif
+# endif
#endif
-#ifndef TCC_TARGET_PE
-#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM
+#ifdef TCC_IS_NATIVE
+ /* 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 int runtime_plt_and_got_offset;
-#endif
+ unsigned runtime_plt_and_got_offset;
+# define TCC_HAS_RUNTIME_PLTGOT
+# endif
#endif
+
+ /* used by main and tcc_parse_args only */
+ char **files; /* files seen on command line */
+ int nb_files; /* number thereof */
+ int nb_libraries; /* number of libs thereof */
+ char *outfile; /* output filename */
+ char *option_m; /* only -m32/-m64 handled */
+ int print_search_dirs; /* option */
+ int option_r; /* option -r */
+ int do_bench; /* option -bench */
+ int gen_deps; /* option -MD */
+ char *deps_outfile; /* option -MF */
};
/* The current value can be: */
-#define VT_VALMASK 0x003f
-#define VT_CONST 0x0030 /* constant in vc
- (must be first non register value) */
+#define VT_VALMASK 0x003f /* mask for value location, register or: */
+#define VT_CONST 0x0030 /* constant in vc (must be first non register value) */
#define VT_LLOCAL 0x0031 /* lvalue, offset on stack */
#define VT_LOCAL 0x0032 /* offset on stack */
#define VT_CMP 0x0033 /* the value is stored in processor flags (in vc) */
@@ -687,29 +696,29 @@ struct TCCState {
#define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
/* types */
-#define VT_INT 0 /* integer type */
-#define VT_BYTE 1 /* signed byte type */
-#define VT_SHORT 2 /* short type */
-#define VT_VOID 3 /* void type */
-#define VT_PTR 4 /* pointer */
-#define VT_ENUM 5 /* enum definition */
-#define VT_FUNC 6 /* function type */
-#define VT_STRUCT 7 /* struct/union definition */
-#define VT_FLOAT 8 /* IEEE float */
-#define VT_DOUBLE 9 /* IEEE double */
-#define VT_LDOUBLE 10 /* IEEE long double */
-#define VT_BOOL 11 /* ISOC99 boolean type */
-#define VT_LLONG 12 /* 64 bit integer */
-#define VT_LONG 13 /* long integer (NEVER USED as type, only
- during parsing) */
-#define VT_BTYPE 0x000f /* mask for basic type */
-#define VT_UNSIGNED 0x0010 /* unsigned type */
-#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
-#define VT_VLA 0x20000 /* VLA type (also has VT_PTR and VT_ARRAY) */
-#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_BTYPE 0x000f /* mask for basic type */
+#define VT_INT 0 /* integer type */
+#define VT_BYTE 1 /* signed byte type */
+#define VT_SHORT 2 /* short type */
+#define VT_VOID 3 /* void type */
+#define VT_PTR 4 /* pointer */
+#define VT_ENUM 5 /* enum definition */
+#define VT_FUNC 6 /* function type */
+#define VT_STRUCT 7 /* struct/union definition */
+#define VT_FLOAT 8 /* IEEE float */
+#define VT_DOUBLE 9 /* IEEE double */
+#define VT_LDOUBLE 10 /* IEEE long double */
+#define VT_BOOL 11 /* ISOC99 boolean type */
+#define VT_LLONG 12 /* 64 bit integer */
+#define VT_LONG 13 /* long integer (NEVER USED as type, only
+ during parsing) */
+#define VT_UNSIGNED 0x0010 /* unsigned type */
+#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
+#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_VLA 0x00020000 /* VLA type (also has VT_PTR and VT_ARRAY) */
/* storage */
#define VT_EXTERN 0x00000080 /* extern definition */
@@ -718,13 +727,13 @@ struct TCCState {
#define VT_INLINE 0x00000400 /* inline definition */
#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */
#define VT_EXPORT 0x00008000 /* win32: data exported from dll */
-#define VT_WEAK 0x00010000 /* win32: data exported from dll */
+#define VT_WEAK 0x00010000 /* weak symbol */
-#define VT_STRUCT_SHIFT 18 /* shift for bitfield shift values */
+#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_TYPE (~(VT_STORAGE))
+#define VT_TYPE (~(VT_STORAGE))
/* token values */
@@ -976,6 +985,11 @@ ST_DATA int tcc_ext;
/* XXX: get rid of this ASAP */
ST_DATA struct TCCState *tcc_state;
+#ifdef MEM_DEBUG
+ST_DATA int mem_cur_size;
+ST_DATA int mem_max_size;
+#endif
+
#define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
#define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
#define AFF_PREPROCESS 0x0004 /* preprocess file */
@@ -997,19 +1011,19 @@ PUB_FUNC char *tcc_strdup(const char *str);
#undef strdup
#define strdup(s) use_tcc_strdup(s)
PUB_FUNC void tcc_memstats(void);
-PUB_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data);
-PUB_FUNC void dynarray_reset(void *pp, int *n);
PUB_FUNC void tcc_error_noabort(const char *fmt, ...);
PUB_FUNC void tcc_error(const char *fmt, ...);
PUB_FUNC void tcc_warning(const char *fmt, ...);
/* other utilities */
-PUB_FUNC void cstr_ccat(CString *cstr, int ch);
-PUB_FUNC void cstr_cat(CString *cstr, const char *str);
-PUB_FUNC void cstr_wccat(CString *cstr, int ch);
-PUB_FUNC void cstr_new(CString *cstr);
-PUB_FUNC void cstr_free(CString *cstr);
-#define cstr_reset(cstr) cstr_free(cstr)
+ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data);
+ST_FUNC void dynarray_reset(void *pp, int *n);
+ST_FUNC void cstr_ccat(CString *cstr, int ch);
+ST_FUNC void cstr_cat(CString *cstr, const char *str);
+ST_FUNC void cstr_wccat(CString *cstr, int ch);
+ST_FUNC void cstr_new(CString *cstr);
+ST_FUNC void cstr_free(CString *cstr);
+ST_FUNC void cstr_reset(CString *cstr);
ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
@@ -1017,8 +1031,8 @@ ST_FUNC void *section_ptr_add(Section *sec, unsigned long size);
ST_FUNC void section_reserve(Section *sec, unsigned long size);
ST_FUNC Section *find_section(TCCState *s1, const char *name);
-ST_FUNC void put_extern_sym2(Sym *sym, Section *section, uplong value, unsigned long size, int can_add_underscore);
-ST_FUNC void put_extern_sym(Sym *sym, Section *section, uplong value, unsigned long size);
+ST_FUNC void put_extern_sym2(Sym *sym, Section *section, addr_t value, unsigned long size, int can_add_underscore);
+ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size);
ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type);
ST_INLN void sym_free(Sym *sym);
@@ -1036,14 +1050,10 @@ ST_FUNC void tcc_close(void);
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags);
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
-#ifndef TCC_TARGET_PE
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags);
-#endif
-PUB_FUNC int tcc_set_flag(TCCState *s, const char *flag_name, int value);
PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time);
-PUB_FUNC char *tcc_default_target(TCCState *s, const char *default_file);
-PUB_FUNC void tcc_gen_makedeps(TCCState *s, const char *target, const char *filename);
+PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv);
/* ------------ tccpp.c ------------ */
@@ -1095,7 +1105,7 @@ ST_FUNC void next_nomacro(void);
ST_FUNC void next(void);
ST_INLN void unget_tok(int last_tok);
ST_FUNC void preprocess_init(TCCState *s1);
-ST_FUNC void preprocess_new();
+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);
@@ -1128,7 +1138,8 @@ ST_DATA Sym *local_label_stack;
ST_DATA Sym *global_label_stack;
ST_DATA Sym *define_stack;
ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
-ST_DATA SValue vstack[VSTACK_SIZE], *vtop;
+ST_DATA SValue __vstack[1+/*to make bcheck happy*/ VSTACK_SIZE], *vtop;
+#define vstack (__vstack + 1)
ST_DATA int rsym, anon_sym, ind, loc;
ST_DATA int const_wanted; /* true if constant wanted */
@@ -1183,6 +1194,10 @@ ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsign
/* ------------ tccelf.c ------------ */
+#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
+#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
+#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
+
#define ARMAG "!<arch>\012" /* For COFF and a.out archives */
typedef struct {
@@ -1196,8 +1211,8 @@ typedef struct {
ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
ST_FUNC int put_elf_str(Section *s, const char *sym);
-ST_FUNC int put_elf_sym(Section *s, uplong value, unsigned long size, int info, int other, int shndx, const char *name);
-ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size, int info, int other, int sh_num, const char *name);
+ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
+ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int sh_num, const char *name);
ST_FUNC int find_elf_sym(Section *s, const char *name);
ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol);
@@ -1213,12 +1228,16 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s);
ST_FUNC void tcc_add_linker_symbols(TCCState *s1);
ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
ST_FUNC int tcc_load_archive(TCCState *s1, int fd);
-ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name);
ST_FUNC void tcc_add_bcheck(TCCState *s1);
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
+ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name);
+#endif
+
#ifndef TCC_TARGET_PE
ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level);
ST_FUNC int tcc_load_ldscript(TCCState *s1);
@@ -1228,26 +1247,14 @@ ST_INLN void inp(void);
ST_FUNC int handle_eob(void);
#endif
+/* ------------ xxx-gen.c ------------ */
+
#ifdef TCC_TARGET_X86_64
-# define ELFCLASSW ELFCLASS64
-# define ElfW(type) Elf##64##_##type
-# define ELFW(type) ELF##64##_##type
-# define ElfW_Rel ElfW(Rela)
-# define SHT_RELX SHT_RELA
-# define REL_SECTION_FMT ".rela%s"
-/* XXX: DLL with PLT would only work with x86-64 for now */
-# define TCC_OUTPUT_DLL_WITH_PLT
+ST_DATA const int reg_classes[NB_REGS+7];
#else
-# define ELFCLASSW ELFCLASS32
-# define ElfW(type) Elf##32##_##type
-# define ELFW(type) ELF##32##_##type
-# define ElfW_Rel ElfW(Rel)
-# define SHT_RELX SHT_REL
-# define REL_SECTION_FMT ".rel%s"
+ST_DATA const int reg_classes[NB_REGS];
#endif
-/* ------------ xxx-gen.c ------------ */
-
ST_FUNC void gsym_addr(int t, int a);
ST_FUNC void gsym(int t);
ST_FUNC void load(int r, SValue *sv);
@@ -1288,10 +1295,12 @@ ST_FUNC void gen_bounded_ptr_deref(void);
/* ------------ x86_64-gen.c ------------ */
#ifdef TCC_TARGET_X86_64
ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c);
+ST_FUNC void gen_opl(int op);
#endif
/* ------------ arm-gen.c ------------ */
#ifdef TCC_TARGET_ARM
+ST_FUNC void arm_init_types(void);
ST_FUNC uint32_t encbranch(int pos, int addr, int fail);
ST_FUNC void gen_cvt_itof1(int t);
#endif
@@ -1310,7 +1319,6 @@ ST_FUNC int tcc_load_coff(TCCState * s1, int fd);
/* ------------ tccasm.c ------------ */
ST_FUNC void asm_instr(void);
ST_FUNC void asm_global_instr(void);
-
#ifdef CONFIG_TCC_ASM
ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);
ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
@@ -1324,20 +1332,20 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier);
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str);
#endif
+
/* ------------ tccpe.c -------------- */
#ifdef TCC_TARGET_PE
ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd);
ST_FUNC int pe_output_file(TCCState * s1, const char *filename);
-ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, const void *value);
+ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value);
ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
-/* tiny_impdef.c */
-ST_FUNC char *get_export_names(FILE *fp);
#ifdef TCC_TARGET_X86_64
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
#endif
#endif
/* ------------ tccrun.c ----------------- */
+#ifdef TCC_IS_NATIVE
#ifdef CONFIG_TCC_STATIC
#define RTLD_LAZY 0x001
#define RTLD_NOW 0x002
@@ -1346,9 +1354,9 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
/* dummy function for profiling */
ST_FUNC void *dlopen(const char *filename, int flag);
ST_FUNC void dlclose(void *p);
-//ST_FUNC const char *dlerror(void);
+ST_FUNC const char *dlerror(void);
ST_FUNC void *resolve_sym(TCCState *s1, const char *symbol);
-#elif !defined TCC_TARGET_PE || !defined _WIN32
+#elif !defined _WIN32
ST_FUNC void *resolve_sym(TCCState *s1, const char *symbol);
#endif
@@ -1356,29 +1364,9 @@ ST_FUNC void *resolve_sym(TCCState *s1, const char *symbol);
ST_DATA int rt_num_callers;
ST_DATA const char **rt_bound_error_msg;
ST_DATA void *rt_prog_main;
-PUB_FUNC void tcc_set_num_callers(int n);
+ST_FUNC void tcc_set_num_callers(int n);
#endif
-
-/********************************************************/
-/* include the target specific definitions */
-
-#define TARGET_DEFS_ONLY
-#ifdef TCC_TARGET_I386
-#include "i386-gen.c"
-#endif
-#ifdef TCC_TARGET_X86_64
-#include "x86_64-gen.c"
-#endif
-#ifdef TCC_TARGET_ARM
-#include "arm-gen.c"
#endif
-#ifdef TCC_TARGET_C67
-#include "coff.h"
-#include "c67-gen.c"
-#endif
-#undef TARGET_DEFS_ONLY
-
-ST_DATA const int reg_classes[];
/********************************************************/
#undef ST_DATA
diff --git a/tccasm.c b/tccasm.c
index d1d2af1..9c77960 100644
--- a/tccasm.c
+++ b/tccasm.c
@@ -837,8 +837,7 @@ static void tcc_assemble_inline(TCCState *s1, char *str, int len)
saved_parse_flags = parse_flags;
saved_macro_ptr = macro_ptr;
- tcc_open_bf(s1, file->filename, len);
- file->line_num = file->prev->line_num;
+ tcc_open_bf(s1, ":asm:", len);
memcpy(file->buffer, str, len);
macro_ptr = NULL;
diff --git a/tcccoff.c b/tcccoff.c
index 2f52562..1421ca2 100644
--- a/tcccoff.c
+++ b/tcccoff.c
@@ -38,7 +38,7 @@ int EndAddress[MAX_FUNCS];
int LastLineNo[MAX_FUNCS];
int FuncEntries[MAX_FUNCS];
-BOOL OutputTheSection(Section * sect);
+int OutputTheSection(Section * sect);
short int GetCoffFlags(const char *s);
void SortSymbolTable(void);
Section *FindSection(TCCState * s1, const char *sname);
@@ -814,14 +814,14 @@ int FindCoffSymbolIndex(const char *func_name)
return n; // total number of symbols
}
-BOOL OutputTheSection(Section * sect)
+int OutputTheSection(Section * sect)
{
const char *s = sect->name;
if (!strcmp(s, ".text"))
- return true;
+ return 1;
else if (!strcmp(s, ".data"))
- return true;
+ return 1;
else
return 0;
}
@@ -933,7 +933,7 @@ ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
if (name[0] == '_' && strcmp(name, "_main") != 0)
name++;
- tcc_add_symbol(s1, name, (void*)(uplong)csym.n_value);
+ tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value);
}
// skip any aux records
diff --git a/tccelf.c b/tccelf.c
index e5bb1cb..500ea18 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -84,7 +84,7 @@ static void rebuild_hash(Section *s, unsigned int nb_buckets)
}
/* return the symbol number */
-ST_FUNC int put_elf_sym(Section *s, uplong value, unsigned long size,
+ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
int info, int other, int shndx, const char *name)
{
int name_offset, sym_index;
@@ -157,7 +157,7 @@ ST_FUNC int find_elf_sym(Section *s, const char *name)
}
/* return elf symbol value, signal error if 'err' is nonzero */
-static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
+ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)
{
int sym_index;
ElfW(Sym) *sym;
@@ -167,26 +167,28 @@ static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
if (!sym_index || sym->st_shndx == SHN_UNDEF) {
if (err)
tcc_error("%s not defined", name);
- return NULL;
+ return 0;
}
- return (void*)(uplong)sym->st_value;
+ return sym->st_value;
}
/* return elf symbol value */
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
{
- return get_elf_sym_addr(s, name, 0);
+ return (void*)(uintptr_t)get_elf_sym_addr(s, name, 0);
}
+#ifdef TCC_IS_NATIVE
/* return elf symbol value or error */
-ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name)
+ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)
{
- return get_elf_sym_addr(s, name, 1);
+ return (void*)get_elf_sym_addr(s, name, 1);
}
+#endif
/* add an elf symbol : check if it is already defined and patch
it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
-ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size,
+ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,
int info, int other, int sh_num, const char *name)
{
ElfW(Sym) *esym;
@@ -238,7 +240,7 @@ ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size,
} else if (s == tcc_state->dynsymtab_section) {
/* we accept that two DLL define the same symbol */
} else {
-#if 1
+#if 0
printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
#endif
@@ -431,12 +433,12 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
if (sh_num == SHN_UNDEF) {
name = strtab_section->data + sym->st_name;
if (do_resolve) {
-#if !defined TCC_TARGET_PE || !defined _WIN32
+#if defined TCC_IS_NATIVE && !defined _WIN32
void *addr;
name = symtab_section->link->data + sym->st_name;
addr = resolve_sym(s1, name);
if (addr) {
- sym->st_value = (uplong)addr;
+ sym->st_value = (addr_t)addr;
goto found;
}
#endif
@@ -469,10 +471,10 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
}
}
-#ifndef TCC_TARGET_PE
+#ifdef TCC_HAS_RUNTIME_PLTGOT
#ifdef TCC_TARGET_X86_64
#define JMP_TABLE_ENTRY_SIZE 14
-static uplong add_jmp_table(TCCState *s1, uplong val)
+static addr_t add_jmp_table(TCCState *s1, addr_t val)
{
char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
@@ -480,30 +482,30 @@ static uplong add_jmp_table(TCCState *s1, uplong val)
p[0] = 0xff;
p[1] = 0x25;
*(int *)(p + 2) = 0;
- *(uplong *)(p + 6) = val;
- return (uplong)p;
+ *(addr_t *)(p + 6) = val;
+ return (addr_t)p;
}
-static uplong add_got_table(TCCState *s1, uplong val)
+static addr_t add_got_table(TCCState *s1, addr_t val)
{
- uplong *p = (uplong *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
- s1->runtime_plt_and_got_offset += sizeof(uplong);
+ addr_t *p = (addr_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
+ s1->runtime_plt_and_got_offset += sizeof(addr_t);
*p = val;
- return (uplong)p;
+ return (addr_t)p;
}
#elif defined TCC_TARGET_ARM
#define JMP_TABLE_ENTRY_SIZE 8
-static uplong add_jmp_table(TCCState *s1, int val)
+static addr_t add_jmp_table(TCCState *s1, int val)
{
uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
/* ldr pc, [pc, #-4] */
p[0] = 0xE51FF004;
p[1] = val;
- return (uplong)p;
+ return (addr_t)p;
}
#endif
-#endif
+#endif /* def TCC_HAS_RUNTIME_PLTGOT */
/* relocate a given section (CPU dependent) */
ST_FUNC void relocate_section(TCCState *s1, Section *s)
@@ -513,7 +515,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
ElfW(Sym) *sym;
int type, sym_index;
unsigned char *ptr;
- uplong val, addr;
+ addr_t val, addr;
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
int esym_index;
#endif
@@ -581,7 +583,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
break;
case R_386_GOT32:
/* we load the got offset */
- *(int *)ptr += s1->got_offsets[sym_index];
+ *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
break;
case R_386_16:
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
@@ -612,13 +614,16 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
is_call = (type == R_ARM_CALL);
x += val - addr;
h = x & 2;
-#ifndef TCC_TARGET_PE
- if ((x & 3) || x >= 0x4000000 || x < -0x4000000)
- if (!(x & 3) || !blx_avail || !is_call)
- if (s1->output_type == TCC_OUTPUT_MEMORY)
+#ifdef TCC_HAS_RUNTIME_PLTGOT
+ if (s1->output_type == TCC_OUTPUT_MEMORY) {
+ if ((x & 3) || x >= 0x2000000 || x < -0x2000000)
+ if (!(x & 3) || !blx_avail || !is_call) {
x += add_jmp_table(s1, val) - val; /* add veneer */
+ is_thumb = 0; /* Veneer uses ARM instructions */
+ }
+ }
#endif
- if ((x & 3) || x >= 0x4000000 || x < -0x4000000)
+ if ((x & 3) || x >= 0x2000000 || x < -0x2000000)
if (!(x & 3) || !blx_avail || !is_call)
tcc_error("can't relocate value at %x",addr);
x >>= 2;
@@ -638,7 +643,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
case R_ARM_THM_JUMP24:
{
int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
- int to_thumb, is_call, blx_bit = 1 << 12;
+ int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
+ Section *plt;
/* weak reference */
if (sym->st_shndx == SHN_UNDEF &&
@@ -662,9 +668,14 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
/* Relocation infos */
to_thumb = val & 1;
+ plt = s1->plt;
+ to_plt = (val >= plt->sh_addr) &&
+ (val < plt->sh_addr + plt->data_offset);
is_call = (type == R_ARM_THM_CALL);
/* Compute final offset */
+ if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
+ x -= 4;
x += val - addr;
if (!to_thumb && is_call) {
blx_bit = 0; /* bl -> blx */
@@ -675,9 +686,9 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
* offset must not be out of range
* if target is to be entered in arm mode:
- bit 1 must not set
- - instruction must be a call (bl) */
+ - instruction must be a call (bl) or a jump to PLT */
if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
- if (to_thumb || (val & 2) || !is_call)
+ if (to_thumb || (val & 2) || (!is_call && !to_plt))
tcc_error("can't relocate value at %x",addr);
/* Compute and store final offset */
@@ -752,7 +763,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
break;
case R_ARM_GOT_BREL:
/* we load the got offset */
- *(int *)ptr += s1->got_offsets[sym_index];
+ *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
break;
case R_ARM_COPY:
break;
@@ -762,8 +773,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
*(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
break;
default:
- fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
- type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
+ fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
+ type, (unsigned)addr, ptr, (unsigned)val);
break;
#elif defined(TCC_TARGET_C67)
case R_C60_32:
@@ -788,8 +799,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
case R_C60HI16:
break;
default:
- fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
- type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
+ fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
+ type, (unsigned)addr, ptr, (unsigned)val);
break;
#elif defined(TCC_TARGET_X86_64)
case R_X86_64_64:
@@ -829,7 +840,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
long long diff;
diff = (long long)val - addr;
if (diff <= -2147483647 || diff > 2147483647) {
-#ifndef TCC_TARGET_PE
+#ifdef TCC_HAS_RUNTIME_PLTGOT
/* XXX: naive support for over 32bit jump */
if (s1->output_type == TCC_OUTPUT_MEMORY) {
val = (add_jmp_table(s1, val - rel->r_addend) +
@@ -850,7 +861,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
*(int *)ptr = val - rel->r_addend;
break;
case R_X86_64_GOTPCREL:
-#ifndef TCC_TARGET_PE
+#ifdef TCC_HAS_RUNTIME_PLTGOT
if (s1->output_type == TCC_OUTPUT_MEMORY) {
val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
*(int *)ptr += val - addr;
@@ -858,14 +869,14 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
}
#endif
*(int *)ptr += (s1->got->sh_addr - addr +
- s1->got_offsets[sym_index] - 4);
+ s1->sym_attrs[sym_index].got_offset - 4);
break;
case R_X86_64_GOTTPOFF:
*(int *)ptr += val - s1->got->sh_addr;
break;
case R_X86_64_GOT32:
/* we load the got offset */
- *(int *)ptr += s1->got_offsets[sym_index];
+ *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
break;
#else
#error unsupported processor
@@ -935,23 +946,23 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
return count;
}
-static void put_got_offset(TCCState *s1, int index, unsigned long val)
+static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
{
int n;
- unsigned long *tab;
+ struct sym_attr *tab;
- if (index >= s1->nb_got_offsets) {
+ if (index >= s1->nb_sym_attrs) {
/* find immediately bigger power of 2 and reallocate array */
n = 1;
while (index >= n)
n *= 2;
- tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
- s1->got_offsets = tab;
- memset(s1->got_offsets + s1->nb_got_offsets, 0,
- (n - s1->nb_got_offsets) * sizeof(unsigned long));
- s1->nb_got_offsets = n;
+ tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
+ s1->sym_attrs = tab;
+ memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
+ (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
+ s1->nb_sym_attrs = n;
}
- s1->got_offsets[index] = val;
+ return &s1->sym_attrs[index];
}
/* XXX: suppress that */
@@ -1015,11 +1026,11 @@ static void put_got_entry(TCCState *s1,
build_got(s1);
/* if a got entry already exists for that symbol, no need to add one */
- if (sym_index < s1->nb_got_offsets &&
- s1->got_offsets[sym_index] != 0)
+ if (sym_index < s1->nb_sym_attrs &&
+ s1->sym_attrs[sym_index].got_offset)
return;
-
- put_got_offset(s1, sym_index, s1->got->data_offset);
+
+ alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset;
if (s1->dynsym) {
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
@@ -1096,10 +1107,16 @@ static void put_got_entry(TCCState *s1,
put32(p + 12, 0xe5bef008);
}
- p = section_ptr_add(plt, 16);
- put32(p , 0xe59fc004);
- put32(p+4, 0xe08fc00c);
- put32(p+8, 0xe59cf000);
+ if (s1->sym_attrs[sym_index].plt_thumb_stub) {
+ p = section_ptr_add(plt, 20);
+ put32(p , 0x4778); // bx pc
+ put32(p+2, 0x46c0); // nop
+ p += 4;
+ } else
+ p = section_ptr_add(plt, 16);
+ put32(p , 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT
+ put32(p+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset
+ put32(p+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset
put32(p+12, s1->got->data_offset);
/* the symbol is modified so that it will be relocated to
@@ -1261,7 +1278,7 @@ ST_FUNC Section *new_symtab(TCCState *s1,
}
/* put dynamic tag */
-static void put_dt(Section *dynamic, int dt, uplong val)
+static void put_dt(Section *dynamic, int dt, addr_t val)
{
ElfW(Dyn) *dyn;
dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
@@ -1297,13 +1314,6 @@ static void add_init_array_defines(TCCState *s1, const char *section_name)
s->sh_num, sym_end);
}
-static int tcc_add_support(TCCState *s1, const char *filename)
-{
- char buf[1024];
- snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
- return tcc_add_file(s1, buf);
-}
-
ST_FUNC void tcc_add_bcheck(TCCState *s1)
{
#ifdef CONFIG_TCC_BCHECK
@@ -1321,10 +1331,6 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1)
add_elf_sym(symtab_section, 0, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
bounds_section->sh_num, "__bounds_start");
- /* add bound check code */
-#ifndef TCC_TARGET_PE
- tcc_add_support(s1, "bcheck.o");
-#endif
#ifdef TCC_TARGET_I386
if (s1->output_type != TCC_OUTPUT_MEMORY) {
/* add 'call __bound_init()' in .init section */
@@ -1340,6 +1346,13 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1)
#endif
}
+static inline int tcc_add_support(TCCState *s1, const char *filename)
+{
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
+ return tcc_add_file(s1, buf);
+}
+
/* add tcc runtime libraries */
ST_FUNC void tcc_add_runtime(TCCState *s1)
{
@@ -1483,9 +1496,9 @@ ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
unsigned long offset;
- if (sym_index >= s1->nb_got_offsets)
+ if (sym_index >= s1->nb_sym_attrs)
return;
- offset = s1->got_offsets[sym_index];
+ offset = s1->sym_attrs[sym_index].got_offset;
section_reserve(s1->got, offset + PTR_SIZE);
#ifdef TCC_TARGET_X86_64
/* only works for x86-64 */
@@ -1531,7 +1544,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
int *section_order;
int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
long long tmp;
- uplong addr;
+ addr_t addr;
Section *strsec, *s;
ElfW(Shdr) shdr, *sh;
ElfW(Phdr) *phdr, *ph;
@@ -1539,9 +1552,9 @@ static int elf_output_file(TCCState *s1, const char *filename)
unsigned long saved_dynamic_data_offset;
ElfW(Sym) *sym;
int type, file_type;
- uplong rel_addr, rel_size;
+ addr_t rel_addr, rel_size;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- uplong bss_addr, bss_size;
+ addr_t bss_addr, bss_size;
#endif
file_type = s1->output_type;
@@ -1618,8 +1631,16 @@ static int elf_output_file(TCCState *s1, const char *filename)
esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
type = ELFW(ST_TYPE)(esym->st_info);
if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
+ /* Indirect functions shall have STT_FUNC type
+ * in executable dynsym section. Indeed, a dlsym
+ * call following a lazy resolution would pick
+ * the symbol value from the executable dynsym
+ * entry which would contain the address of the
+ * function wanted by the caller of dlsym
+ * instead of the address of the function that
+ * would return that address */
put_got_entry(s1, R_JMP_SLOT, esym->st_size,
- ELFW(ST_INFO)(STB_GLOBAL,type),
+ ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
sym - (ElfW(Sym) *)symtab_section->data);
} else if (type == STT_OBJECT) {
unsigned long offset;
@@ -1719,8 +1740,9 @@ static int elf_output_file(TCCState *s1, const char *filename)
if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
&& sym->st_shndx == SHN_UNDEF) {
+ int visibility = ELFW(ST_BIND)(sym->st_info);
put_got_entry(s1, R_JMP_SLOT, sym->st_size,
- sym->st_info,
+ ELFW(ST_INFO)(visibility,STT_FUNC),
sym - (ElfW(Sym) *)symtab_section->data);
}
else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
@@ -2057,8 +2079,10 @@ static int elf_output_file(TCCState *s1, const char *filename)
#elif defined(TCC_TARGET_ARM)
int x;
x=s1->got->sh_addr - s1->plt->sh_addr - 12;
- p +=16;
+ p += 16;
while (p < p_end) {
+ if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
+ p += 4;
put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
p += 16;
}
@@ -2150,7 +2174,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
/* XXX: ignore sections with allocated relocations ? */
for(i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
- if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
+ if (s->reloc && s != s1->got)
relocate_section(s1, s);
}
@@ -2166,7 +2190,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
/* get entry point address */
if (file_type == TCC_OUTPUT_EXE)
- ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
+ ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
else
ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
}
@@ -2292,7 +2316,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
tcc_free(s1->symtab_to_dynsym);
tcc_free(section_order);
tcc_free(phdr);
- tcc_free(s1->got_offsets);
+ tcc_free(s1->sym_attrs);
return ret;
}
@@ -2587,6 +2611,18 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
rel->r_info = ELFW(R_INFO)(sym_index, type);
/* offset the relocation offset */
rel->r_offset += offseti;
+#ifdef TCC_TARGET_ARM
+ /* Jumps and branches from a Thumb code to a PLT entry need
+ special handling since PLT entries are ARM code.
+ Unconditional bl instructions referencing PLT entries are
+ handled by converting these instructions into blx
+ instructions. Other case of instructions referencing a PLT
+ entry require to add a Thumb stub before the PLT entry to
+ switch to ARM mode. We set bit 0 of the got offset of a
+ symbol to indicate such a case. */
+ if (type == R_ARM_THM_JUMP24)
+ alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
+#endif
}
break;
default:
@@ -2955,20 +2991,6 @@ static int ld_next(TCCState *s1, char *name, int name_size)
return c;
}
-/*
- * Extract the file name from the library name
- *
- * /!\ No test on filename capacity, be careful
- */
-static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
-{
- if (!s1->static_link) {
- sprintf(filename, "lib%s.so", libname);
- } else {
- sprintf(filename, "lib%s.a", libname);
- }
-}
-
static int ld_add_file(TCCState *s1, const char filename[])
{
int ret;
@@ -3015,8 +3037,12 @@ static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
ret = -1;
goto lib_parse_error;
}
- strcpy(libname, &filename[1]);
- libname_to_filename(s1, libname, filename);
+ pstrcpy(libname, sizeof libname, &filename[1]);
+ if (s1->static_link) {
+ snprintf(filename, sizeof filename, "lib%s.a", libname);
+ } else {
+ snprintf(filename, sizeof filename, "lib%s.so", libname);
+ }
} else if (t != LD_TOK_NAME) {
tcc_error_noabort("filename expected");
ret = -1;
diff --git a/tccgen.c b/tccgen.c
index 4e58ef0..0a6250c 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -55,7 +55,7 @@ ST_DATA Sym *define_stack;
ST_DATA Sym *global_label_stack;
ST_DATA Sym *local_label_stack;
-ST_DATA SValue vstack[VSTACK_SIZE], *vtop;
+ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop;
ST_DATA int const_wanted; /* true if constant wanted */
ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */
@@ -344,27 +344,23 @@ static void vpushs(long long v)
vsetc(&size_type, VT_CONST, &cval);
}
-/* push long long constant */
-static void vpushll(long long v)
-{
- CValue cval;
- CType ctype;
- ctype.t = VT_LLONG;
- ctype.ref = 0;
- cval.ull = v;
- vsetc(&ctype, VT_CONST, &cval);
-}
-
/* push arbitrary 64bit constant */
void vpush64(int ty, unsigned long long v)
{
CValue cval;
CType ctype;
ctype.t = ty;
+ ctype.ref = NULL;
cval.ull = v;
vsetc(&ctype, VT_CONST, &cval);
}
+/* push long long constant */
+static inline void vpushll(long long v)
+{
+ vpush64(VT_LLONG, v);
+}
+
/* Return a static symbol pointing to a section */
ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
{
@@ -459,7 +455,6 @@ static void vseti(int r, int v)
ST_FUNC void vswap(void)
{
SValue tmp;
-
/* cannot let cpu flags if other instruction are generated. Also
avoid leaving VT_JMP anywhere except on the top of the stack
because it would complicate the code generator. */
@@ -471,6 +466,11 @@ ST_FUNC void vswap(void)
tmp = vtop[0];
vtop[0] = vtop[-1];
vtop[-1] = tmp;
+
+/* XXX: +2% overall speed possible with optimized memswap
+ *
+ * memswap(&vtop[0], &vtop[1], sizeof *vtop);
+ */
}
ST_FUNC void vpushv(SValue *v)
@@ -1700,6 +1700,8 @@ ST_FUNC void gen_op(int op)
(t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
t |= VT_UNSIGNED;
goto std_op;
+ } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
+ tcc_error("comparison of struct");
} else {
/* integer operations */
t = VT_INT;
@@ -3258,8 +3260,8 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
{
Sym *s;
CType type1, *type2;
- int qualifiers, storage, saved_nocode_wanted;
-
+ int qualifiers, storage;
+
while (tok == '*') {
qualifiers = 0;
redo:
@@ -3313,12 +3315,12 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
storage = type->t & VT_STORAGE;
type->t &= ~VT_STORAGE;
if (storage & VT_STATIC) {
- saved_nocode_wanted = nocode_wanted;
+ int saved_nocode_wanted = nocode_wanted;
nocode_wanted = 1;
- }
- post_type(type, ad);
- if (storage & VT_STATIC)
+ post_type(type, ad);
nocode_wanted = saved_nocode_wanted;
+ } else
+ post_type(type, ad);
type->t |= storage;
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
parse_attribute(ad);
@@ -3663,20 +3665,23 @@ ST_FUNC void unary(void)
break;
case TOK_builtin_frame_address:
{
+ int level;
CType type;
next();
skip('(');
- if (tok != TOK_CINT) {
- tcc_error("__builtin_frame_address only takes integers");
- }
- if (tokc.i != 0) {
- tcc_error("TCC only supports __builtin_frame_address(0)");
+ if (tok != TOK_CINT || tokc.i < 0) {
+ tcc_error("__builtin_frame_address only takes positive integers");
}
+ level = tokc.i;
next();
skip(')');
type.t = VT_VOID;
mk_pointer(&type);
- vset(&type, VT_LOCAL, 0);
+ vset(&type, VT_LOCAL, 0); /* local frame */
+ while (level--) {
+ mk_pointer(&vtop->type);
+ indir(); /* -> parent frame */
+ }
}
break;
#ifdef TCC_TARGET_X86_64
@@ -5565,7 +5570,7 @@ ST_FUNC void gen_inline_functions(void)
str = fn->token_str;
fn->sym = NULL;
if (file)
- strcpy(file->filename, fn->filename);
+ pstrcpy(file->filename, sizeof file->filename, fn->filename);
sym->r = VT_SYM | VT_CONST;
sym->type.t &= ~VT_INLINE;
diff --git a/tccpe.c b/tccpe.c
index 4dec1d8..79be6f3 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -663,7 +663,7 @@ static int pe_write(struct pe_info *pe)
}
}
- strcpy((char*)psh->Name, sh_name);
+ pstrcpy((char*)psh->Name, sizeof psh->Name, sh_name);
psh->Characteristics = pe_sec_flags[si->cls];
psh->VirtualAddress = addr;
@@ -682,14 +682,11 @@ static int pe_write(struct pe_info *pe)
pe_header.filehdr.NumberOfSections = pe->sec_count;
pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
pe_header.opthdr.ImageBase = pe->imagebase;
+ pe_header.opthdr.Subsystem = pe->subsystem;
if (pe->s1->pe_stack_size)
pe_header.opthdr.SizeOfStackReserve = pe->s1->pe_stack_size;
if (PE_DLL == pe->type)
pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;
- else if (PE_GUI != pe->type)
- pe_header.opthdr.Subsystem = 3;
- if (pe->subsystem == 9) // WinCE
- pe_header.opthdr.Subsystem = 9;
sum = 0;
pe_fwrite(&pe_header, sizeof pe_header, op, &sum);
@@ -933,7 +930,7 @@ static void pe_build_exports(struct pe_info *pe)
#if 1
/* automatically write exports to <output-filename>.def */
- strcpy(buf, pe->filename);
+ pstrcpy(buf, sizeof buf, pe->filename);
strcpy(tcc_fileextension(buf), ".def");
op = fopen(buf, "w");
if (NULL == op) {
@@ -1100,6 +1097,9 @@ static int pe_assign_addresses (struct pe_info *pe)
continue;
}
#endif
+ if (c == sec_stab && 0 == pe->s1->do_debug)
+ continue;
+
strcpy(si->name, s->name);
si->cls = c;
si->ord = k;
@@ -1477,11 +1477,11 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2)
return v2;
}
-ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, const void *value)
+ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value)
{
return add_elf_sym(
s1->dynsymtab_section,
- (uplong)value,
+ value,
dllindex, /* st_size */
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
0,
@@ -1505,10 +1505,10 @@ static int add_dllref(TCCState *s1, const char *dllname)
/* ------------------------------------------------------------- */
-static int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
+static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
{
- fseek(fp, offset, 0);
- return len == fread(buffer, 1, len, fp);
+ lseek(fd, offset, SEEK_SET);
+ return len == read(fd, buffer, len);
}
/* -------------------------------------------------------------
@@ -1516,7 +1516,7 @@ static int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
* as generated by 'windres.exe -O coff ...'.
*/
-static int pe_load_res(TCCState *s1, FILE *fp)
+static int pe_load_res(TCCState *s1, int fd)
{
struct pe_rsrc_header hdr;
Section *rsrc_section;
@@ -1524,7 +1524,7 @@ static int pe_load_res(TCCState *s1, FILE *fp)
BYTE *ptr;
unsigned offs;
- if (!read_mem(fp, 0, &hdr, sizeof hdr))
+ if (!read_mem(fd, 0, &hdr, sizeof hdr))
goto quit;
if (hdr.filehdr.Machine != 0x014C
@@ -1535,13 +1535,13 @@ static int pe_load_res(TCCState *s1, FILE *fp)
rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData);
offs = hdr.sectionhdr.PointerToRawData;
- if (!read_mem(fp, offs, ptr, hdr.sectionhdr.SizeOfRawData))
+ if (!read_mem(fd, offs, ptr, hdr.sectionhdr.SizeOfRawData))
goto quit;
offs = hdr.sectionhdr.PointerToRelocations;
for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i)
{
struct pe_rsrc_reloc rel;
- if (!read_mem(fp, offs, &rel, sizeof rel))
+ if (!read_mem(fd, offs, &rel, sizeof rel))
goto quit;
// printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type);
if (rel.type != 7) /* DIR32NB */
@@ -1571,22 +1571,26 @@ static char *trimback(char *a, char *e)
return a;
}
-static char *get_line(char *line, int size, FILE *fp)
+static char *get_line(char *line, int size, int fd)
{
- if (NULL == fgets(line, size, fp))
+ 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, strchr(line, 0));
+ trimback(line, line + n);
return trimfront(line);
}
/* ------------------------------------------------------------- */
-static int pe_load_def(TCCState *s1, FILE *fp)
+static int pe_load_def(TCCState *s1, int fd)
{
int state = 0, ret = -1, dllindex = 0;
char line[400], dllname[80], *p;
for (;;) {
- p = get_line(line, sizeof line, fp);
+ p = get_line(line, sizeof line, fd);
if (NULL == p)
break;
if (0 == *p || ';' == *p)
@@ -1595,7 +1599,7 @@ static int pe_load_def(TCCState *s1, FILE *fp)
case 0:
if (0 != strnicmp(p, "LIBRARY", 7))
goto quit;
- strcpy(dllname, trimfront(p+7));
+ pstrcpy(dllname, sizeof dllname, trimfront(p+7));
++state;
continue;
@@ -1610,7 +1614,7 @@ static int pe_load_def(TCCState *s1, FILE *fp)
++state;
default:
- pe_putimport(s1, dllindex, p, NULL);
+ pe_putimport(s1, dllindex, p, 0);
continue;
}
}
@@ -1623,16 +1627,16 @@ quit:
#define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
#include "win32/tools/tiny_impdef.c"
-static int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp)
+static int pe_load_dll(TCCState *s1, const char *dllname, int fd)
{
char *p, *q;
int index;
- p = get_export_names(fp);
+ p = get_export_names(fd);
if (!p)
return -1;
index = add_dllref(s1, dllname);
for (q = p; *q; q += 1 + strlen(q))
- pe_putimport(s1, index, q, NULL);
+ pe_putimport(s1, index, q, 0);
tcc_free(p);
return 0;
}
@@ -1640,18 +1644,14 @@ static int pe_load_dll(TCCState *s1, const char *dllname, FILE *fp)
/* ------------------------------------------------------------- */
ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd)
{
- FILE *fp = fdopen(dup(fd), "rb");
int ret = -1;
char buf[10];
- if (fp) {
- if (0 == strcmp(tcc_fileextension(filename), ".def"))
- ret = pe_load_def(s1, fp);
- else if (pe_load_res(s1, fp) == 0)
- ret = 0;
- else if (read_mem(fp, 0, buf, sizeof buf) && 0 == strncmp(buf, "MZ", 2))
- ret = pe_load_dll(s1, tcc_basename(filename), fp);
- fclose(fp);
- }
+ if (0 == strcmp(tcc_fileextension(filename), ".def"))
+ ret = pe_load_def(s1, fd);
+ else if (pe_load_res(s1, fd) == 0)
+ ret = 0;
+ else if (read_mem(fd, 0, buf, sizeof buf) && 0 == strncmp(buf, "MZ", 2))
+ ret = pe_load_dll(s1, tcc_basename(filename), fd);
return ret;
}
@@ -1723,10 +1723,10 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
#define PE_STDSYM(n,s) "_" n s
#endif
-static void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
+static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
{
const char *start_symbol;
- unsigned long addr = 0;
+ ADDR3264 addr = 0;
int pe_type = 0;
if (find_elf_sym(symtab_section, PE_STDSYM("WinMain","@16")))
@@ -1762,15 +1762,17 @@ static void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
if (0 == s1->nostdlib) {
static const char *libs[] = {
- "tcc1", "msvcrt", "kernel32", "", "user32", "gdi32", NULL
+ "libtcc1.a", "msvcrt", "kernel32", "", "user32", "gdi32", NULL
};
const char **pp, *p;
for (pp = libs; 0 != (p = *pp); ++pp) {
if (0 == *p) {
if (PE_DLL != pe_type && PE_GUI != pe_type)
break;
- } else if (tcc_add_library(s1, p) < 0)
+ } else if (pp == libs ? tcc_add_dll(s1, p, 0) : tcc_add_library(s1, p)) {
tcc_error_noabort("cannot find library: %s", p);
+ break;
+ }
}
}
@@ -1778,7 +1780,7 @@ static void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe)
pe_type = PE_RUN;
if (start_symbol) {
- addr = (uplong)tcc_get_symbol_err(s1, 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,
@@ -1802,7 +1804,7 @@ ST_FUNC int pe_output_file(TCCState * s1, const char *filename)
pe.s1 = s1;
tcc_add_bcheck(s1);
- pe_add_runtime_ex(s1, &pe);
+ pe_add_runtime(s1, &pe);
relocate_common_syms(); /* assign bss adresses */
tcc_add_linker_symbols(s1);
@@ -1822,15 +1824,19 @@ ST_FUNC int pe_output_file(TCCState * s1, const char *filename)
#endif
}
- /* if no subsystem specified, we use "console" subsystem by default */
- if (s1->pe_subsystem != 0)
- pe.subsystem = s1->pe_subsystem;
- else
#if defined(TCC_TARGET_ARM)
- pe.subsystem = 9;
+ /* we use "console" subsystem by default */
+ pe.subsystem = 9;
#else
+ if (PE_DLL == pe.type || PE_GUI == pe.type)
+ pe.subsystem = 2;
+ else
pe.subsystem = 3;
#endif
+ /* Allow override via -Wl,-subsystem=... option */
+ if (s1->pe_subsystem != 0)
+ pe.subsystem = s1->pe_subsystem;
+
/* set default file/section alignment */
if (pe.subsystem == 1) {
pe.section_align = 0x20;
diff --git a/tccpp.c b/tccpp.c
index aff5a53..2d6e852 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -118,7 +118,7 @@ static void cstr_realloc(CString *cstr, int new_size)
}
/* add a byte */
-PUB_FUNC void cstr_ccat(CString *cstr, int ch)
+ST_FUNC void cstr_ccat(CString *cstr, int ch)
{
int size;
size = cstr->size + 1;
@@ -128,7 +128,7 @@ PUB_FUNC void cstr_ccat(CString *cstr, int ch)
cstr->size = size;
}
-PUB_FUNC void cstr_cat(CString *cstr, const char *str)
+ST_FUNC void cstr_cat(CString *cstr, const char *str)
{
int c;
for(;;) {
@@ -141,7 +141,7 @@ PUB_FUNC void cstr_cat(CString *cstr, const char *str)
}
/* add a wide char */
-PUB_FUNC void cstr_wccat(CString *cstr, int ch)
+ST_FUNC void cstr_wccat(CString *cstr, int ch)
{
int size;
size = cstr->size + sizeof(nwchar_t);
@@ -151,18 +151,24 @@ PUB_FUNC void cstr_wccat(CString *cstr, int ch)
cstr->size = size;
}
-PUB_FUNC void cstr_new(CString *cstr)
+ST_FUNC void cstr_new(CString *cstr)
{
memset(cstr, 0, sizeof(CString));
}
/* free string and reset it to NULL */
-PUB_FUNC void cstr_free(CString *cstr)
+ST_FUNC void cstr_free(CString *cstr)
{
tcc_free(cstr->data_allocated);
cstr_new(cstr);
}
+/* reset string to empty */
+ST_FUNC void cstr_reset(CString *cstr)
+{
+ cstr->size = 0;
+}
+
/* XXX: unicode ? */
static void add_char(CString *cstr, int c)
{
@@ -1236,13 +1242,12 @@ ST_FUNC void parse_define(void)
define_push(v, t, str.str, first);
}
-static inline int hash_cached_include(int type, const char *filename)
+static inline int hash_cached_include(const char *filename)
{
const unsigned char *s;
unsigned int h;
h = TOK_HASH_INIT;
- h = TOK_HASH_FUNC(h, type);
s = filename;
while (*s) {
h = TOK_HASH_FUNC(h, *s);
@@ -1252,45 +1257,39 @@ static inline int hash_cached_include(int type, const char *filename)
return h;
}
-/* XXX: use a token or a hash table to accelerate matching ? */
-static CachedInclude *search_cached_include(TCCState *s1,
- int type, const char *filename)
+static CachedInclude *search_cached_include(TCCState *s1, const char *filename)
{
CachedInclude *e;
int i, h;
- h = hash_cached_include(type, filename);
+ h = hash_cached_include(filename);
i = s1->cached_includes_hash[h];
for(;;) {
if (i == 0)
break;
e = s1->cached_includes[i - 1];
- if (e->type == type && !PATHCMP(e->filename, filename))
+ if (0 == PATHCMP(e->filename, filename))
return e;
i = e->hash_next;
}
return NULL;
}
-static inline void add_cached_include(TCCState *s1, int type,
- const char *filename, int ifndef_macro)
+static inline void add_cached_include(TCCState *s1, const char *filename, int ifndef_macro)
{
CachedInclude *e;
int h;
- if (search_cached_include(s1, type, filename))
+ if (search_cached_include(s1, filename))
return;
#ifdef INC_DEBUG
printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
#endif
e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
- if (!e)
- return;
- e->type = type;
strcpy(e->filename, filename);
e->ifndef_macro = ifndef_macro;
dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
/* add in hash table */
- h = hash_cached_include(type, filename);
+ h = hash_cached_include(filename);
e->hash_next = s1->cached_includes_hash[h];
s1->cached_includes_hash[h] = s1->nb_cached_includes;
}
@@ -1430,27 +1429,29 @@ ST_FUNC void preprocess(int is_bof)
if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
tcc_error("#include recursion too deep");
+ /* store current file in stack, but increment stack later below */
+ *s1->include_stack_ptr = file;
n = s1->nb_include_paths + s1->nb_sysinclude_paths;
for (i = -2; i < n; ++i) {
char buf1[sizeof file->filename];
CachedInclude *e;
+ BufferedFile **f;
const char *path;
- int size, fd;
if (i == -2) {
/* check absolute include path */
if (!IS_ABSPATH(buf))
continue;
buf1[0] = 0;
+ i = n; /* force end loop */
} else if (i == -1) {
/* search in current dir if "header.h" */
if (c != '\"')
continue;
- size = tcc_basename(file->filename) - file->filename;
- memcpy(buf1, file->filename, size);
- buf1[size] = '\0';
+ path = file->filename;
+ pstrncpy(buf1, path, tcc_basename(path) - path);
} else {
/* search in all the include paths */
@@ -1464,41 +1465,37 @@ ST_FUNC void preprocess(int is_bof)
pstrcat(buf1, sizeof(buf1), buf);
- e = search_cached_include(s1, c, buf1);
+ if (tok == TOK_INCLUDE_NEXT)
+ for (f = s1->include_stack_ptr; f >= s1->include_stack; --f)
+ if (0 == PATHCMP((*f)->filename, buf1)) {
+#ifdef INC_DEBUG
+ printf("%s: #include_next skipping %s\n", file->filename, buf1);
+#endif
+ goto include_trynext;
+ }
+
+ e = search_cached_include(s1, buf1);
if (e && define_find(e->ifndef_macro)) {
/* no need to parse the include because the 'ifndef macro'
is defined */
#ifdef INC_DEBUG
- printf("%s: skipping %s\n", file->filename, buf);
+ printf("%s: skipping cached %s\n", file->filename, buf1);
#endif
- fd = 0;
- } else {
- fd = tcc_open(s1, buf1);
- if (fd < 0)
- continue;
+ goto include_done;
}
- if (tok == TOK_INCLUDE_NEXT) {
- tok = TOK_INCLUDE;
- if (fd)
- tcc_close();
+ if (tcc_open(s1, buf1) < 0)
+include_trynext:
continue;
- }
-
- if (0 == fd)
- goto include_done;
#ifdef INC_DEBUG
- printf("%s: including %s\n", file->filename, buf1);
+ printf("%s: including %s\n", file->prev->filename, file->filename);
#endif
/* update target deps */
dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps,
tcc_strdup(buf1));
- /* XXX: fix current line init */
- /* push current file in stack */
- *s1->include_stack_ptr++ = file->prev;
- file->inc_type = c;
- pstrcpy(file->inc_filename, sizeof(file->inc_filename), buf1);
+ /* push current file in stack */
+ ++s1->include_stack_ptr;
/* add include file debug info */
if (s1->do_debug)
put_stabs(file->filename, N_BINCL, 0, 0, 0);
@@ -2131,8 +2128,8 @@ static inline void next_nomacro1(void)
#ifdef INC_DEBUG
printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
#endif
- add_cached_include(s1, file->inc_type, file->inc_filename,
- file->ifndef_macro_saved);
+ add_cached_include(s1, file->filename, file->ifndef_macro_saved);
+ tok_flags &= ~TOK_FLAG_ENDIF;
}
/* add end of include file debug info */
@@ -2803,13 +2800,13 @@ static inline int *macro_twosharps(const int *macro_str)
{
const int *ptr;
int t;
- CValue cval;
TokenString macro_str1;
CString cstr;
int n, start_of_nosubsts;
/* we search the first '##' */
for(ptr = macro_str;;) {
+ CValue cval;
TOK_GET(&t, &ptr, &cval);
if (t == TOK_TWOSHARPS)
break;
@@ -2838,10 +2835,9 @@ static inline int *macro_twosharps(const int *macro_str)
/* given 'a##b', remove nosubsts preceding 'b' */
while (t == TOK_NOSUBST)
t = *++ptr;
-
if (t && t != TOK_TWOSHARPS) {
+ CValue cval;
TOK_GET(&t, &ptr, &cval);
-
/* We concatenate the two tokens */
cstr_new(&cstr);
cstr_cat(&cstr, get_tok_str(tok, &tokc));
@@ -2849,7 +2845,7 @@ static inline int *macro_twosharps(const int *macro_str)
cstr_cat(&cstr, get_tok_str(t, &cval));
cstr_ccat(&cstr, '\0');
- tcc_open_bf(tcc_state, "<paste>", cstr.size);
+ tcc_open_bf(tcc_state, ":paste:", cstr.size);
memcpy(file->buffer, cstr.data, cstr.size);
for (;;) {
next_nomacro1();
@@ -2860,7 +2856,7 @@ static inline int *macro_twosharps(const int *macro_str)
n, cstr.data, (char*)cstr.data + n);
}
tcc_close();
- cstr_reset(&cstr);
+ cstr_free(&cstr);
}
}
if (tok != TOK_NOSUBST)
@@ -3041,13 +3037,12 @@ ST_FUNC void preprocess_init(TCCState *s1)
s1->ifdef_stack_ptr = s1->ifdef_stack;
file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
- /* XXX: not ANSI compliant: bound checking says error */
vtop = vstack - 1;
s1->pack_stack[0] = 0;
s1->pack_stack_ptr = s1->pack_stack;
}
-ST_FUNC void preprocess_new()
+ST_FUNC void preprocess_new(void)
{
int i, c;
const char *p, *r;
@@ -3116,17 +3111,17 @@ print_line:
: ""
;
iptr = iptr_new;
- fprintf(s1->outfile, "# %d \"%s\"%s\n", file->line_num, file->filename, s);
+ fprintf(s1->ppfp, "# %d \"%s\"%s\n", file->line_num, file->filename, s);
} else {
while (d)
- fputs("\n", s1->outfile), --d;
+ fputs("\n", s1->ppfp), --d;
}
line_ref = (file_ref = file)->line_num;
token_seen = tok != TOK_LINEFEED;
if (!token_seen)
continue;
}
- fputs(get_tok_str(tok, &tokc), s1->outfile);
+ fputs(get_tok_str(tok, &tokc), s1->ppfp);
}
free_defines(define_start);
return 0;
diff --git a/tccrun.c b/tccrun.c
index 531f46a..50178a8 100644
--- a/tccrun.c
+++ b/tccrun.c
@@ -35,7 +35,7 @@ ST_DATA void *rt_prog_main;
static void set_pages_executable(void *ptr, unsigned long length);
static void set_exception_handler(void);
-static int rt_get_caller_pc(uplong *paddr, ucontext_t *uc, int level);
+static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level);
static void rt_error(ucontext_t *uc, const char *fmt, ...);
static int tcc_relocate_ex(TCCState *s1, void *ptr);
@@ -54,33 +54,36 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
if (TCC_RELOCATE_AUTO != ptr)
return tcc_relocate_ex(s1, ptr);
+ ret = tcc_relocate_ex(s1, NULL);
+ if (ret < 0)
+ return ret;
+
#ifdef HAVE_SELINUX
- /* Use mmap instead of malloc for Selinux
- Ref http://www.gnu.org/s/libc/manual/html_node/File-Size.html */
- char tmpfname[] = "/tmp/.tccrunXXXXXX";
- int fd = mkstemp (tmpfname);
- if ((ret= tcc_relocate_ex(s1,NULL)) < 0)return -1;
- s1->mem_size=ret;
- unlink (tmpfname); ftruncate (fd, s1->mem_size);
- s1->write_mem = mmap (NULL, ret, PROT_READ|PROT_WRITE,
- MAP_SHARED, fd, 0);
- if(s1->write_mem == MAP_FAILED){
- tcc_error("/tmp not writeable");
- return -1;
- }
- s1->runtime_mem = mmap (NULL, ret, PROT_READ|PROT_EXEC,
- MAP_SHARED, fd, 0);
- if(s1->runtime_mem == MAP_FAILED){
- tcc_error("/tmp not executable");
- return -1;
+ { /* Use mmap instead of malloc for Selinux. Ref:
+ http://www.gnu.org/s/libc/manual/html_node/File-Size.html */
+
+ char tmpfname[] = "/tmp/.tccrunXXXXXX";
+ int fd = mkstemp (tmpfname);
+
+ s1->mem_size = ret;
+ unlink (tmpfname);
+ ftruncate (fd, s1->mem_size);
+
+ s1->write_mem = mmap (NULL, ret, PROT_READ|PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (s1->write_mem == MAP_FAILED)
+ tcc_error("/tmp not writeable");
+
+ s1->runtime_mem = mmap (NULL, ret, PROT_READ|PROT_EXEC,
+ MAP_SHARED, fd, 0);
+ if (s1->runtime_mem == MAP_FAILED)
+ tcc_error("/tmp not executable");
+
+ ret = tcc_relocate_ex(s1, s1->write_mem);
}
- ret = tcc_relocate_ex(s1, s1->write_mem);
#else
- ret = tcc_relocate_ex(s1, NULL);
- if (-1 != ret) {
- s1->runtime_mem = tcc_malloc(ret);
- ret = tcc_relocate_ex(s1, s1->runtime_mem);
- }
+ s1->runtime_mem = tcc_malloc(ret);
+ ret = tcc_relocate_ex(s1, s1->runtime_mem);
#endif
return ret;
}
@@ -127,11 +130,10 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
{
Section *s;
unsigned long offset, length;
- uplong mem;
+ addr_t mem;
int i;
- if (0 == s1->runtime_added) {
- s1->runtime_added = 1;
+ if (NULL == ptr) {
s1->nb_errors = 0;
#ifdef TCC_TARGET_PE
pe_output_file(s1, NULL);
@@ -145,7 +147,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
return -1;
}
- offset = 0, mem = (uplong)ptr;
+ offset = 0, mem = (addr_t)ptr;
for(i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
if (0 == (s->sh_flags & SHF_ALLOC))
@@ -161,7 +163,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
if (s1->nb_errors)
return -1;
-#if (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM) && !defined TCC_TARGET_PE
+#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
@@ -185,7 +187,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
continue;
length = s->data_offset;
// printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
- ptr = (void*)(uplong)s->sh_addr;
+ ptr = (void*)s->sh_addr;
if (NULL == s->data || s->sh_type == SHT_NOBITS)
memset(ptr, 0, length);
else
@@ -195,7 +197,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
set_pages_executable(ptr, length);
}
-#if (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM) && !defined TCC_TARGET_PE
+#ifdef TCC_HAS_RUNTIME_PLTGOT
set_pages_executable(s1->runtime_plt_and_got,
s1->runtime_plt_and_got_offset);
#endif
@@ -215,30 +217,31 @@ static void set_pages_executable(void *ptr, unsigned long length)
unsigned long old_protect;
VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
#else
- unsigned long start, end;
- start = (uplong)ptr & ~(PAGESIZE - 1);
- end = (uplong)ptr + length;
+#ifndef PAGESIZE
+# define PAGESIZE 4096
+#endif
+ addr_t start, end;
+ start = (addr_t)ptr & ~(PAGESIZE - 1);
+ end = (addr_t)ptr + length;
end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
#endif
}
/* ------------------------------------------------------------- */
-#endif /* TCC_IS_NATIVE */
-
#ifdef CONFIG_TCC_BACKTRACE
-PUB_FUNC void tcc_set_num_callers(int n)
+ST_FUNC void tcc_set_num_callers(int n)
{
rt_num_callers = n;
}
/* print the position in the source file of PC value 'pc' by reading
the stabs debug information */
-static uplong rt_printline(uplong wanted_pc, const char *msg)
+static addr_t rt_printline(addr_t wanted_pc, const char *msg)
{
char func_name[128], last_func_name[128];
- uplong func_addr, last_pc, pc;
+ addr_t func_addr, last_pc, pc;
const char *incl_files[INCLUDE_STACK_SIZE];
int incl_index, len, last_line_num, i;
const char *str, *p;
@@ -257,7 +260,7 @@ static uplong rt_printline(uplong wanted_pc, const char *msg)
func_addr = 0;
incl_index = 0;
last_func_name[0] = '\0';
- last_pc = (uplong)-1;
+ last_pc = (addr_t)-1;
last_line_num = 1;
if (!stab_sym)
@@ -380,7 +383,7 @@ no_stabs:
static void rt_error(ucontext_t *uc, const char *fmt, ...)
{
va_list ap;
- uplong pc;
+ addr_t pc;
int i;
fprintf(stderr, "Runtime error: ");
@@ -393,7 +396,7 @@ static void rt_error(ucontext_t *uc, const char *fmt, ...)
if (rt_get_caller_pc(&pc, uc, i) < 0)
break;
pc = rt_printline(pc, i ? "by" : "at");
- if (pc == (uplong)rt_prog_main && pc)
+ if (pc == (addr_t)rt_prog_main && pc)
break;
}
}
@@ -438,6 +441,10 @@ static void sig_error(int signum, siginfo_t *siginf, void *puc)
exit(255);
}
+#ifndef SA_SIGINFO
+# define SA_SIGINFO 0x00000004u
+#endif
+
/* Generate a stack backtrace when a CPU exception occurs. */
static void set_exception_handler(void)
{
@@ -463,10 +470,10 @@ static void set_exception_handler(void)
#define REG_EBP EBP
#endif
-/* return the PC at frame level 'level'. Return non zero if not found */
-static int rt_get_caller_pc(unsigned long *paddr, ucontext_t *uc, int level)
+/* return the PC at frame level 'level'. Return negative if not found */
+static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
{
- unsigned long fp;
+ addr_t fp;
int i;
if (level == 0) {
@@ -494,9 +501,9 @@ static int rt_get_caller_pc(unsigned long *paddr, ucontext_t *uc, int level)
/* XXX: check address validity with program info */
if (fp <= 0x1000 || fp >= 0xc0000000)
return -1;
- fp = ((unsigned long *)fp)[0];
+ fp = ((addr_t *)fp)[0];
}
- *paddr = ((unsigned long *)fp)[1];
+ *paddr = ((addr_t *)fp)[1];
return 0;
}
}
@@ -504,11 +511,10 @@ static int rt_get_caller_pc(unsigned long *paddr, ucontext_t *uc, int level)
/* ------------------------------------------------------------- */
#elif defined(__x86_64__)
-/* return the PC at frame level 'level'. Return non zero if not found */
-static int rt_get_caller_pc(unsigned long *paddr,
- ucontext_t *uc, int level)
+/* return the PC at frame level 'level'. Return negative if not found */
+static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
{
- unsigned long fp;
+ addr_t fp;
int i;
if (level == 0) {
@@ -533,9 +539,9 @@ static int rt_get_caller_pc(unsigned long *paddr,
/* XXX: check address validity with program info */
if (fp <= 0x1000)
return -1;
- fp = ((unsigned long *)fp)[0];
+ fp = ((addr_t *)fp)[0];
}
- *paddr = ((unsigned long *)fp)[1];
+ *paddr = ((addr_t *)fp)[1];
return 0;
}
}
@@ -544,10 +550,9 @@ static int rt_get_caller_pc(unsigned long *paddr,
#elif defined(__arm__)
/* return the PC at frame level 'level'. Return negative if not found */
-static int rt_get_caller_pc(unsigned long *paddr,
- ucontext_t *uc, int level)
+static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
{
- uint32_t fp, sp;
+ addr_t fp, sp;
int i;
if (level == 0) {
@@ -571,15 +576,15 @@ static int rt_get_caller_pc(unsigned long *paddr,
if (fp < sp + 12 || fp & 3)
return -1;
for(i = 1; i < level; i++) {
- sp = ((uint32_t *)fp)[-2];
+ sp = ((addr_t *)fp)[-2];
if (sp < fp || sp - fp > 16 || sp & 3)
return -1;
- fp = ((uint32_t *)fp)[-3];
+ fp = ((addr_t *)fp)[-3];
if (fp <= sp || fp - sp < 12 || fp & 3)
return -1;
}
/* XXX: check address validity with program info */
- *paddr = ((uint32_t *)fp)[-1];
+ *paddr = ((addr_t *)fp)[-1];
return 0;
}
}
@@ -588,8 +593,7 @@ static int rt_get_caller_pc(unsigned long *paddr,
#else
#warning add arch specific rt_get_caller_pc()
-static int rt_get_caller_pc(unsigned long *paddr,
- ucontext_t *uc, int level)
+static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
{
return -1;
}
@@ -620,8 +624,7 @@ static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info)
rt_error(uc, "exception caught");
break;
}
- exit(-1);
- return EXCEPTION_CONTINUE_SEARCH;
+ return EXCEPTION_EXECUTE_HANDLER;
}
/* Generate a stack backtrace when a CPU exception occurs. */
@@ -634,17 +637,17 @@ static void set_exception_handler(void)
static void win64_add_function_table(TCCState *s1)
{
RtlAddFunctionTable(
- (RUNTIME_FUNCTION*)(uplong)s1->uw_pdata->sh_addr,
+ (RUNTIME_FUNCTION*)s1->uw_pdata->sh_addr,
s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),
- (uplong)text_section->sh_addr
+ text_section->sh_addr
);
}
#endif
/* return the PC at frame level 'level'. Return non zero if not found */
-static int rt_get_caller_pc(uplong *paddr, CONTEXT *uc, int level)
+static int rt_get_caller_pc(addr_t *paddr, CONTEXT *uc, int level)
{
- uplong fp, pc;
+ addr_t fp, pc;
int i;
#ifdef _WIN64
pc = uc->Rip;
@@ -658,9 +661,9 @@ static int rt_get_caller_pc(uplong *paddr, CONTEXT *uc, int level)
/* XXX: check address validity with program info */
if (fp <= 0x1000 || fp >= 0xc0000000)
return -1;
- fp = ((uplong*)fp)[0];
+ fp = ((addr_t*)fp)[0];
}
- pc = ((uplong*)fp)[1];
+ pc = ((addr_t*)fp)[1];
}
*paddr = pc;
return 0;
@@ -669,14 +672,8 @@ static int rt_get_caller_pc(uplong *paddr, CONTEXT *uc, int level)
#endif /* _WIN32 */
#endif /* CONFIG_TCC_BACKTRACE */
/* ------------------------------------------------------------- */
-
#ifdef CONFIG_TCC_STATIC
-#define RTLD_LAZY 0x001
-#define RTLD_NOW 0x002
-#define RTLD_GLOBAL 0x100
-#define RTLD_DEFAULT NULL
-
/* dummy function for profiling */
ST_FUNC void *dlopen(const char *filename, int flag)
{
@@ -686,26 +683,27 @@ ST_FUNC void *dlopen(const char *filename, int flag)
ST_FUNC void dlclose(void *p)
{
}
-/*
-const char *dlerror(void)
+
+ST_FUNC const char *dlerror(void)
{
return "error";
}
-*/
+
typedef struct TCCSyms {
char *str;
void *ptr;
} TCCSyms;
-#define TCCSYM(a) { #a, &a, },
/* add the symbol you want here if no dynamic linking is done */
static TCCSyms tcc_syms[] = {
#if !defined(CONFIG_TCCBOOT)
+#define TCCSYM(a) { #a, &a, },
TCCSYM(printf)
TCCSYM(fprintf)
TCCSYM(fopen)
TCCSYM(fclose)
+#undef TCCSYM
#endif
{ NULL, NULL },
};
@@ -730,5 +728,5 @@ ST_FUNC void *resolve_sym(TCCState *s1, const char *sym)
}
#endif /* CONFIG_TCC_STATIC */
-
+#endif /* TCC_IS_NATIVE */
/* ------------------------------------------------------------- */
diff --git a/tests/Makefile b/tests/Makefile
index e5c3294..6e0f728 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -4,77 +4,84 @@
TOP = ..
include $(TOP)/Makefile
+VPATH = $(top_srcdir)/tests
# what tests to run
-TESTS = libtest \
- test1 \
- test2 \
- test3 \
- speedtest \
- btest \
- weaktest
-
- # test4 # this test does not seem to work on any platform
- # asmtest # this test does not seem to work on any platform
-
-# these should work too
-# TESTS += test1 test2 speedtest btest weaktest
-
-# some tests do not pass on all platforms, remove them for now
-ifeq ($(TARGETOS),Linux)
- TESTS := $(filter-out btest,$(TESTS))
- TESTS := $(filter-out weaktest,$(TESTS))
+TESTS = \
+ hello-exe \
+ hello-run \
+ libtest \
+ test3 \
+ moretests
+
+# 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))
+endif
+ifdef CONFIG_WIN32
+ TESTS := $(filter-out test3,$(TESTS))
endif
ifeq ($(TARGETOS),Darwin)
- TESTS := $(filter-out test1,$(TESTS))
- TESTS := $(filter-out test2,$(TESTS))
- TESTS := $(filter-out test3,$(TESTS))
- TESTS := $(filter-out btest,$(TESTS))
- TESTS := $(filter-out weaktest,$(TESTS))
+ TESTS := $(filter-out hello-exe test3 btest,$(TESTS))
endif
ifdef DISABLE_STATIC
-export LD_LIBRARY_PATH:=$(CURDIR)/..
+ export LD_LIBRARY_PATH:=$(CURDIR)/..
endif
ifeq ($(TARGETOS),Darwin)
-CFLAGS+=-Wl,-flat_namespace,-undefined,warning
-export MACOSX_DEPLOYMENT_TARGET:=10.2
-NATIVE_DEFINES+=-D_ANSI_SOURCE
+ CFLAGS+=-Wl,-flat_namespace,-undefined,warning
+ export MACOSX_DEPLOYMENT_TARGET:=10.2
+ NATIVE_DEFINES+=-D_ANSI_SOURCE
endif
# run local version of tcc with local libraries and includes
-TCC = ../tcc -B.. $(NATIVE_DEFINES)
+TCCFLAGS = -B$(TOP)
ifdef CONFIG_WIN32
- TCC := $(TCC) -I $(TOP)/win32/include -L$(TOP)
+ TCCFLAGS = -B$(top_srcdir)/win32 -I$(top_srcdir)/include -L$(TOP)
endif
-RUN_TCC = $(NATIVE_DEFINES) -run -DONE_SOURCE ../tcc.c -B..
-DISAS=objdump -d
-all test : $(TESTS)
+TCC = $(TOP)/tcc $(TCCFLAGS)
+RUN_TCC = $(NATIVE_DEFINES) -DONE_SOURCE -run $(TOP)/tcc.c $(TCCFLAGS)
-# make sure that tcc exists
-test1 test2 test3 test4 btest speedtest asmtest weaktest : ../tcc
-../%:
- $(MAKE) -C .. $*
+DISAS = objdump -d
# libtcc test
ifdef LIBTCC1
-LIBTCC1:=$(TOP)/$(LIBTCC1)
+ LIBTCC1:=$(TOP)/$(LIBTCC1)
endif
+all test : $(TESTS)
+
+hello-exe: ../examples/ex1.c
+ @echo ------------ $@ ------------
+ $(TCC) $< -o hello$(EXESUF) || ($(TOP)/tcc -vv; exit 1) && ./hello$(EXESUF)
+
+hello-run: ../examples/ex1.c
+ @echo ------------ $@ ------------
+ $(TCC) -run $<
+
libtest: libtcc_test$(EXESUF) $(LIBTCC1)
@echo ------------ $@ ------------
./libtcc_test$(EXESUF) lib_path=..
-libtcc_test$(EXESUF): libtcc_test.c ../$(LIBTCC)
- $(CC) -o $@ $^ -I.. $(CFLAGS) $(NATIVE_DEFINES) $(LIBS) $(LINK_LIBTCC)
+libtcc_test$(EXESUF): libtcc_test.c $(top_builddir)/$(LIBTCC)
+ $(CC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(NATIVE_DEFINES) $(LIBS) $(LINK_LIBTCC) $(LDFLAGS)
+
+moretests:
+ @echo ------------ $@ ------------
+ $(MAKE) -C tests2
# test.ref - generate using gcc
# copy only tcclib.h so GCC's stddef and stdarg will be used
test.ref: tcctest.c
cp ../include/tcclib.h .
- $(CC) -o tcctest.gcc $< -I. -w $(CFLAGS) $(NATIVE_DEFINES) -std=gnu99
+ gcc -o tcctest.gcc $< -I. $(CPPFLAGS) -w $(CFLAGS) $(NATIVE_DEFINES) -std=gnu99 -O0 -fno-omit-frame-pointer $(LDFLAGS)
./tcctest.gcc > $@
# auto test
@@ -98,29 +105,29 @@ test3: test.ref
# binary output test
test4: test.ref
@echo ------------ $@ ------------
-# dynamic output
- $(TCC) -o tcctest1 tcctest.c
- ./tcctest1 > test1.out
- @if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi
# object + link output
$(TCC) -c -o tcctest3.o tcctest.c
$(TCC) -o tcctest3 tcctest3.o
./tcctest3 > test3.out
@if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi
-# static output
- $(TCC) -static -o tcctest2 tcctest.c
- ./tcctest2 > test2.out
- @if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi
+# dynamic output
+ $(TCC) -o tcctest1 tcctest.c
+ ./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 tcctest.c
./tcctest4 > test4.out
@if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi
+# static output
+ $(TCC) -static -o tcctest2 tcctest.c
+ ./tcctest2 > test2.out
+ @if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi
# memory and bound check auto test
BOUNDS_OK = 1 4 8 10 14
BOUNDS_FAIL= 2 5 7 9 11 12 13 15
-btest: boundtest.c ../bcheck.o
+btest: boundtest.c
@echo ------------ $@ ------------
@for i in $(BOUNDS_OK); do \
echo ; echo --- boundtest $$i ---; \
@@ -144,19 +151,19 @@ btest: boundtest.c ../bcheck.o
speedtest: ex2 ex3
@echo ------------ $@ ------------
time ./ex2 1238 2 3 4 10 13 4
- time $(TCC) -run ../examples/ex2.c 1238 2 3 4 10 13 4
+ time $(TCC) -run $(top_srcdir)/examples/ex2.c 1238 2 3 4 10 13 4
time ./ex3 35
- time $(TCC) -run ../examples/ex3.c 35
+ time $(TCC) -run $(top_srcdir)/examples/ex3.c 35
weaktest: test.ref
- $(TCC) -c tcctest.c -o weaktest.tcc.o
- $(CC) -c tcctest.c -o weaktest.gcc.o -I. -w $(CFLAGS)
+ $(TCC) -c tcctest.c -o weaktest.tcc.o $(CPPFLAGS) $(CFLAGS)
+ $(CC) -c tcctest.c -o weaktest.gcc.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"
-ex%: ../examples/ex%.c
- $(CC) -o $@ $< $(CFLAGS)
+ex%: $(top_srcdir)/examples/ex%.c
+ $(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
# tiny assembler testing
asmtest.ref: asmtest.S
@@ -186,5 +193,7 @@ cache: tcc_g
# clean
clean:
- rm -vf *~ *.o *.a *.bin *.i *.ref *.out *.out? *.gcc \
- tcctest[1234] ex? libtcc_test$(EXESUF) tcc_g tcclib.h
+ $(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
+
diff --git a/tests/tcctest.c b/tests/tcctest.c
index 82762ea..8e295fd 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -89,6 +89,7 @@ void global_data_test(void);
void cmp_comparison_test(void);
void math_cmp_test(void);
void callsave_test(void);
+void builtin_frame_address_test(void);
int fib(int n);
void num(int n);
@@ -593,11 +594,14 @@ int main(int argc, char **argv)
local_label_test();
asm_test();
builtin_test();
+#ifndef _WIN32
weak_test();
+#endif
global_data_test();
cmp_comparison_test();
math_cmp_test();
callsave_test();
+ builtin_frame_address_test();
return 0;
}
@@ -2462,7 +2466,7 @@ void builtin_test(void)
printf("res = %d\n", __builtin_constant_p(constant_p_var));
}
-
+#ifndef _WIN32
extern int __attribute__((weak)) weak_f1(void);
extern int __attribute__((weak)) weak_f2(void);
extern int weak_f3(void);
@@ -2518,6 +2522,7 @@ int __attribute__((weak)) weak_f2() { return 222; }
int __attribute__((weak)) weak_f3() { return 333; }
int __attribute__((weak)) weak_v2 = 222;
int __attribute__((weak)) weak_v3 = 333;
+#endif
void const_func(const int a)
{
@@ -2594,7 +2599,6 @@ void cmp_comparison_test(void)
s.b2 = 0;
glob3 = 43;
compare_comparisons (&s);
- return 0;
}
int fcompare (double a, double b, int code)
@@ -2680,3 +2684,30 @@ void callsave_test(void)
printf ("%d\n", i);
#endif
}
+
+
+void bfa3(ptrdiff_t str_offset)
+{
+ printf("bfa3: %s\n", (char *)__builtin_frame_address(3) + str_offset);
+}
+void bfa2(ptrdiff_t str_offset)
+{
+ printf("bfa2: %s\n", (char *)__builtin_frame_address(2) + str_offset);
+ bfa3(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)
+{
+ char str[] = "__builtin_frame_address";
+ char *fp0 = __builtin_frame_address(0);
+
+ printf("str: %s\n", str);
+ bfa1(str-fp0);
+}
diff --git a/tests2/00_assignment.c b/tests/tests2/00_assignment.c
index c96109f..c96109f 100644
--- a/tests2/00_assignment.c
+++ b/tests/tests2/00_assignment.c
diff --git a/tests2/00_assignment.expect b/tests/tests2/00_assignment.expect
index d4407f3..d4407f3 100644
--- a/tests2/00_assignment.expect
+++ b/tests/tests2/00_assignment.expect
diff --git a/tests2/01_comment.c b/tests/tests2/01_comment.c
index a2e6bc6..a2e6bc6 100644
--- a/tests2/01_comment.c
+++ b/tests/tests2/01_comment.c
diff --git a/tests2/01_comment.expect b/tests/tests2/01_comment.expect
index b1387ad..b1387ad 100644
--- a/tests2/01_comment.expect
+++ b/tests/tests2/01_comment.expect
diff --git a/tests2/02_printf.c b/tests/tests2/02_printf.c
index 4c34dd8..4c34dd8 100644
--- a/tests2/02_printf.c
+++ b/tests/tests2/02_printf.c
diff --git a/tests2/02_printf.expect b/tests/tests2/02_printf.expect
index f67a0f6..f67a0f6 100644
--- a/tests2/02_printf.expect
+++ b/tests/tests2/02_printf.expect
diff --git a/tests2/03_struct.c b/tests/tests2/03_struct.c
index df0d3e7..df0d3e7 100644
--- a/tests2/03_struct.c
+++ b/tests/tests2/03_struct.c
diff --git a/tests2/03_struct.expect b/tests/tests2/03_struct.expect
index ecbf589..ecbf589 100644
--- a/tests2/03_struct.expect
+++ b/tests/tests2/03_struct.expect
diff --git a/tests2/04_for.c b/tests/tests2/04_for.c
index 312fed8..312fed8 100644
--- a/tests2/04_for.c
+++ b/tests/tests2/04_for.c
diff --git a/tests2/04_for.expect b/tests/tests2/04_for.expect
index f00c965..f00c965 100644
--- a/tests2/04_for.expect
+++ b/tests/tests2/04_for.expect
diff --git a/tests2/05_array.c b/tests/tests2/05_array.c
index c218f31..c218f31 100644
--- a/tests2/05_array.c
+++ b/tests/tests2/05_array.c
diff --git a/tests2/05_array.expect b/tests/tests2/05_array.expect
index bc7257c..bc7257c 100644
--- a/tests2/05_array.expect
+++ b/tests/tests2/05_array.expect
diff --git a/tests2/06_case.c b/tests/tests2/06_case.c
index c0191e2..c0191e2 100644
--- a/tests2/06_case.c
+++ b/tests/tests2/06_case.c
diff --git a/tests2/06_case.expect b/tests/tests2/06_case.expect
index fab2c20..fab2c20 100644
--- a/tests2/06_case.expect
+++ b/tests/tests2/06_case.expect
diff --git a/tests2/07_function.c b/tests/tests2/07_function.c
index 0477ce1..0477ce1 100644
--- a/tests2/07_function.c
+++ b/tests/tests2/07_function.c
diff --git a/tests2/07_function.expect b/tests/tests2/07_function.expect
index 8ffb0a7..8ffb0a7 100644
--- a/tests2/07_function.expect
+++ b/tests/tests2/07_function.expect
diff --git a/tests2/08_while.c b/tests/tests2/08_while.c
index 602ffc7..602ffc7 100644
--- a/tests2/08_while.c
+++ b/tests/tests2/08_while.c
diff --git a/tests2/08_while.expect b/tests/tests2/08_while.expect
index 702d4c0..702d4c0 100644
--- a/tests2/08_while.expect
+++ b/tests/tests2/08_while.expect
diff --git a/tests2/09_do_while.c b/tests/tests2/09_do_while.c
index 1d3315d..1d3315d 100644
--- a/tests2/09_do_while.c
+++ b/tests/tests2/09_do_while.c
diff --git a/tests2/09_do_while.expect b/tests/tests2/09_do_while.expect
index 702d4c0..702d4c0 100644
--- a/tests2/09_do_while.expect
+++ b/tests/tests2/09_do_while.expect
diff --git a/tests2/10_pointer.c b/tests/tests2/10_pointer.c
index 0177f4d..0177f4d 100644
--- a/tests2/10_pointer.c
+++ b/tests/tests2/10_pointer.c
diff --git a/tests2/10_pointer.expect b/tests/tests2/10_pointer.expect
index 1e3c473..1e3c473 100644
--- a/tests2/10_pointer.expect
+++ b/tests/tests2/10_pointer.expect
diff --git a/tests2/11_precedence.c b/tests/tests2/11_precedence.c
index db2049d..db2049d 100644
--- a/tests2/11_precedence.c
+++ b/tests/tests2/11_precedence.c
diff --git a/tests2/11_precedence.expect b/tests/tests2/11_precedence.expect
index b692396..b692396 100644
--- a/tests2/11_precedence.expect
+++ b/tests/tests2/11_precedence.expect
diff --git a/tests2/12_hashdefine.c b/tests/tests2/12_hashdefine.c
index 5c521e0..5c521e0 100644
--- a/tests2/12_hashdefine.c
+++ b/tests/tests2/12_hashdefine.c
diff --git a/tests2/12_hashdefine.expect b/tests/tests2/12_hashdefine.expect
index 99f2ed5..99f2ed5 100644
--- a/tests2/12_hashdefine.expect
+++ b/tests/tests2/12_hashdefine.expect
diff --git a/tests2/13_integer_literals.c b/tests/tests2/13_integer_literals.c
index 7cee98b..7cee98b 100644
--- a/tests2/13_integer_literals.c
+++ b/tests/tests2/13_integer_literals.c
diff --git a/tests2/13_integer_literals.expect b/tests/tests2/13_integer_literals.expect
index f5aca06..f5aca06 100644
--- a/tests2/13_integer_literals.expect
+++ b/tests/tests2/13_integer_literals.expect
diff --git a/tests2/14_if.c b/tests/tests2/14_if.c
index 2bd2550..2bd2550 100644
--- a/tests2/14_if.c
+++ b/tests/tests2/14_if.c
diff --git a/tests2/14_if.expect b/tests/tests2/14_if.expect
index c32c415..c32c415 100644
--- a/tests2/14_if.expect
+++ b/tests/tests2/14_if.expect
diff --git a/tests2/15_recursion.c b/tests/tests2/15_recursion.c
index f79a00d..f79a00d 100644
--- a/tests2/15_recursion.c
+++ b/tests/tests2/15_recursion.c
diff --git a/tests2/15_recursion.expect b/tests/tests2/15_recursion.expect
index db47b28..db47b28 100644
--- a/tests2/15_recursion.expect
+++ b/tests/tests2/15_recursion.expect
diff --git a/tests2/16_nesting.c b/tests/tests2/16_nesting.c
index 2b72cc0..2b72cc0 100644
--- a/tests2/16_nesting.c
+++ b/tests/tests2/16_nesting.c
diff --git a/tests2/16_nesting.expect b/tests/tests2/16_nesting.expect
index 625ee13..5a3431e 100644
--- a/tests2/16_nesting.expect
+++ b/tests/tests2/16_nesting.expect
@@ -1,18 +1,18 @@
-0 0 0
-0 0 1
-0 0 2
-0 1 0
-0 1 1
-0 1 2
-0 2 0
-0 2 1
-0 2 2
-1 0 0
-1 0 1
-1 0 2
-1 1 0
-1 1 1
-1 1 2
-1 2 0
-1 2 1
-1 2 2
+0 0 0
+0 0 1
+0 0 2
+0 1 0
+0 1 1
+0 1 2
+0 2 0
+0 2 1
+0 2 2
+1 0 0
+1 0 1
+1 0 2
+1 1 0
+1 1 1
+1 1 2
+1 2 0
+1 2 1
+1 2 2
diff --git a/tests2/17_enum.c b/tests/tests2/17_enum.c
index 0853c42..0853c42 100644
--- a/tests2/17_enum.c
+++ b/tests/tests2/17_enum.c
diff --git a/tests2/17_enum.expect b/tests/tests2/17_enum.expect
index bef4be6..0c4e153 100644
--- a/tests2/17_enum.expect
+++ b/tests/tests2/17_enum.expect
@@ -1,3 +1,3 @@
-0 1 2 3 54 73 74 75
-12
-54
+0 1 2 3 54 73 74 75
+12
+54
diff --git a/tests2/18_include.c b/tests/tests2/18_include.c
index dbae3aa..dbae3aa 100644
--- a/tests2/18_include.c
+++ b/tests/tests2/18_include.c
diff --git a/tests2/18_include.expect b/tests/tests2/18_include.expect
index 87729df..58c6d29 100644
--- a/tests2/18_include.expect
+++ b/tests/tests2/18_include.expect
@@ -1,3 +1,3 @@
-including
-included
-done
+including
+included
+done
diff --git a/tests2/18_include.h b/tests/tests2/18_include.h
index 01f894d..dc86080 100644
--- a/tests2/18_include.h
+++ b/tests/tests2/18_include.h
@@ -1 +1 @@
-printf("included\n");
+printf("included\n");
diff --git a/tests2/19_pointer_arithmetic.c b/tests/tests2/19_pointer_arithmetic.c
index aff65e5..aff65e5 100644
--- a/tests2/19_pointer_arithmetic.c
+++ b/tests/tests2/19_pointer_arithmetic.c
diff --git a/tests2/19_pointer_arithmetic.expect b/tests/tests2/19_pointer_arithmetic.expect
index 0cf781b..0cf781b 100644
--- a/tests2/19_pointer_arithmetic.expect
+++ b/tests/tests2/19_pointer_arithmetic.expect
diff --git a/tests2/20_pointer_comparison.c b/tests/tests2/20_pointer_comparison.c
index 825f778..825f778 100644
--- a/tests2/20_pointer_comparison.c
+++ b/tests/tests2/20_pointer_comparison.c
diff --git a/tests2/20_pointer_comparison.expect b/tests/tests2/20_pointer_comparison.expect
index 5d1e5f5..5d1e5f5 100644
--- a/tests2/20_pointer_comparison.expect
+++ b/tests/tests2/20_pointer_comparison.expect
diff --git a/tests2/21_char_array.c b/tests/tests2/21_char_array.c
index f22f527..f22f527 100644
--- a/tests2/21_char_array.c
+++ b/tests/tests2/21_char_array.c
diff --git a/tests2/21_char_array.expect b/tests/tests2/21_char_array.expect
index dbc6068..dbc6068 100644
--- a/tests2/21_char_array.expect
+++ b/tests/tests2/21_char_array.expect
diff --git a/tests2/22_floating_point.c b/tests/tests2/22_floating_point.c
index e3491f5..e3491f5 100644
--- a/tests2/22_floating_point.c
+++ b/tests/tests2/22_floating_point.c
diff --git a/tests2/22_floating_point.expect b/tests/tests2/22_floating_point.expect
index 75ea3a7..75ea3a7 100644
--- a/tests2/22_floating_point.expect
+++ b/tests/tests2/22_floating_point.expect
diff --git a/tests2/23_type_coercion.c b/tests/tests2/23_type_coercion.c
index 1fcc335..1fcc335 100644
--- a/tests2/23_type_coercion.c
+++ b/tests/tests2/23_type_coercion.c
diff --git a/tests2/23_type_coercion.expect b/tests/tests2/23_type_coercion.expect
index d9076f0..d9076f0 100644
--- a/tests2/23_type_coercion.expect
+++ b/tests/tests2/23_type_coercion.expect
diff --git a/tests2/24_math_library.c b/tests/tests2/24_math_library.c
index 4cc3d9e..4cc3d9e 100644
--- a/tests2/24_math_library.c
+++ b/tests/tests2/24_math_library.c
diff --git a/tests2/24_math_library.expect b/tests/tests2/24_math_library.expect
index 99f7299..99f7299 100644
--- a/tests2/24_math_library.expect
+++ b/tests/tests2/24_math_library.expect
diff --git a/tests2/25_quicksort.c b/tests/tests2/25_quicksort.c
index 5cc08bd..5cc08bd 100644
--- a/tests2/25_quicksort.c
+++ b/tests/tests2/25_quicksort.c
diff --git a/tests2/25_quicksort.expect b/tests/tests2/25_quicksort.expect
index 2d39cd3..2d39cd3 100644
--- a/tests2/25_quicksort.expect
+++ b/tests/tests2/25_quicksort.expect
diff --git a/tests2/26_character_constants.c b/tests/tests2/26_character_constants.c
index 95c4423..95c4423 100644
--- a/tests2/26_character_constants.c
+++ b/tests/tests2/26_character_constants.c
diff --git a/tests2/26_character_constants.expect b/tests/tests2/26_character_constants.expect
index 8f8bfa4..8f8bfa4 100644
--- a/tests2/26_character_constants.expect
+++ b/tests/tests2/26_character_constants.expect
diff --git a/tests2/27_sizeof.c b/tests/tests2/27_sizeof.c
index d1694b6..d1694b6 100644
--- a/tests2/27_sizeof.c
+++ b/tests/tests2/27_sizeof.c
diff --git a/tests2/27_sizeof.expect b/tests/tests2/27_sizeof.expect
index 7329e00..7329e00 100644
--- a/tests2/27_sizeof.expect
+++ b/tests/tests2/27_sizeof.expect
diff --git a/tests2/28_strings.c b/tests/tests2/28_strings.c
index 115fe09..115fe09 100644
--- a/tests2/28_strings.c
+++ b/tests/tests2/28_strings.c
diff --git a/tests2/28_strings.expect b/tests/tests2/28_strings.expect
index fd9217a..fd9217a 100644
--- a/tests2/28_strings.expect
+++ b/tests/tests2/28_strings.expect
diff --git a/tests2/29_array_address.c b/tests/tests2/29_array_address.c
index bda5ddd..bda5ddd 100644
--- a/tests2/29_array_address.c
+++ b/tests/tests2/29_array_address.c
diff --git a/tests2/29_array_address.expect b/tests/tests2/29_array_address.expect
index 9bc8683..9bc8683 100644
--- a/tests2/29_array_address.expect
+++ b/tests/tests2/29_array_address.expect
diff --git a/tests2/30_hanoi.c b/tests/tests2/30_hanoi.c
index b1a1181..b1a1181 100644
--- a/tests2/30_hanoi.c
+++ b/tests/tests2/30_hanoi.c
diff --git a/tests2/30_hanoi.expect b/tests/tests2/30_hanoi.expect
index 7798ee0..7798ee0 100644
--- a/tests2/30_hanoi.expect
+++ b/tests/tests2/30_hanoi.expect
diff --git a/tests2/31_args.c b/tests/tests2/31_args.c
index 275f8cf..275f8cf 100644
--- a/tests2/31_args.c
+++ b/tests/tests2/31_args.c
diff --git a/tests2/31_args.expect b/tests/tests2/31_args.expect
index c392b67..c392b67 100644
--- a/tests2/31_args.expect
+++ b/tests/tests2/31_args.expect
diff --git a/tests2/32_led.c b/tests/tests2/32_led.c
index 5596cbf..5596cbf 100644
--- a/tests2/32_led.c
+++ b/tests/tests2/32_led.c
diff --git a/tests2/32_led.expect b/tests/tests2/32_led.expect
index c53b58a..c53b58a 100644
--- a/tests2/32_led.expect
+++ b/tests/tests2/32_led.expect
diff --git a/tests2/33_ternary_op.c b/tests/tests2/33_ternary_op.c
index 8579b50..8579b50 100644
--- a/tests2/33_ternary_op.c
+++ b/tests/tests2/33_ternary_op.c
diff --git a/tests2/33_ternary_op.expect b/tests/tests2/33_ternary_op.expect
index 45ea507..45ea507 100644
--- a/tests2/33_ternary_op.expect
+++ b/tests/tests2/33_ternary_op.expect
diff --git a/tests2/34_array_assignment.c b/tests/tests2/34_array_assignment.c
index 5885c97..5885c97 100644
--- a/tests2/34_array_assignment.c
+++ b/tests/tests2/34_array_assignment.c
diff --git a/tests2/34_array_assignment.expect b/tests/tests2/34_array_assignment.expect
index 9736bf5..9736bf5 100644
--- a/tests2/34_array_assignment.expect
+++ b/tests/tests2/34_array_assignment.expect
diff --git a/tests2/35_sizeof.c b/tests/tests2/35_sizeof.c
index 672e87e..672e87e 100644
--- a/tests2/35_sizeof.c
+++ b/tests/tests2/35_sizeof.c
diff --git a/tests2/35_sizeof.expect b/tests/tests2/35_sizeof.expect
index 534fb83..534fb83 100644
--- a/tests2/35_sizeof.expect
+++ b/tests/tests2/35_sizeof.expect
diff --git a/tests2/36_array_initialisers.c b/tests/tests2/36_array_initialisers.c
index 1bc8ee0..1bc8ee0 100644
--- a/tests2/36_array_initialisers.c
+++ b/tests/tests2/36_array_initialisers.c
diff --git a/tests2/36_array_initialisers.expect b/tests/tests2/36_array_initialisers.expect
index 3ac6c77..3ac6c77 100644
--- a/tests2/36_array_initialisers.expect
+++ b/tests/tests2/36_array_initialisers.expect
diff --git a/tests2/37_sprintf.c b/tests/tests2/37_sprintf.c
index 1dd1dce..1dd1dce 100644
--- a/tests2/37_sprintf.c
+++ b/tests/tests2/37_sprintf.c
diff --git a/tests2/37_sprintf.expect b/tests/tests2/37_sprintf.expect
index a643da8..a643da8 100644
--- a/tests2/37_sprintf.expect
+++ b/tests/tests2/37_sprintf.expect
diff --git a/tests2/38_multiple_array_index.c b/tests/tests2/38_multiple_array_index.c
index 4e1868e..4e1868e 100644
--- a/tests2/38_multiple_array_index.c
+++ b/tests/tests2/38_multiple_array_index.c
diff --git a/tests2/38_multiple_array_index.expect b/tests/tests2/38_multiple_array_index.expect
index 747ad75..747ad75 100644
--- a/tests2/38_multiple_array_index.expect
+++ b/tests/tests2/38_multiple_array_index.expect
diff --git a/tests2/39_typedef.c b/tests/tests2/39_typedef.c
index 79ab58b..79ab58b 100644
--- a/tests2/39_typedef.c
+++ b/tests/tests2/39_typedef.c
diff --git a/tests2/39_typedef.expect b/tests/tests2/39_typedef.expect
index b9050a9..b9050a9 100644
--- a/tests2/39_typedef.expect
+++ b/tests/tests2/39_typedef.expect
diff --git a/tests2/40_stdio.c b/tests/tests2/40_stdio.c
index 575127a..b986093 100644
--- a/tests2/40_stdio.c
+++ b/tests/tests2/40_stdio.c
@@ -16,7 +16,7 @@ int main()
printf("%s", freddy);
- char InChar;
+ int InChar;
char ShowChar;
f = fopen("fred.txt", "r");
while ( (InChar = fgetc(f)) != EOF)
diff --git a/tests2/40_stdio.expect b/tests/tests2/40_stdio.expect
index e08167a..e08167a 100644
--- a/tests2/40_stdio.expect
+++ b/tests/tests2/40_stdio.expect
diff --git a/tests2/41_hashif.c b/tests/tests2/41_hashif.c
index cb37b9e..cb37b9e 100644
--- a/tests2/41_hashif.c
+++ b/tests/tests2/41_hashif.c
diff --git a/tests2/41_hashif.expect b/tests/tests2/41_hashif.expect
index 5fd414b..5fd414b 100644
--- a/tests2/41_hashif.expect
+++ b/tests/tests2/41_hashif.expect
diff --git a/tests2/42_function_pointer.c b/tests/tests2/42_function_pointer.c
index 49c331b..49c331b 100644
--- a/tests2/42_function_pointer.c
+++ b/tests/tests2/42_function_pointer.c
diff --git a/tests2/42_function_pointer.expect b/tests/tests2/42_function_pointer.expect
index 6c8b6ce..6c8b6ce 100644
--- a/tests2/42_function_pointer.expect
+++ b/tests/tests2/42_function_pointer.expect
diff --git a/tests2/43_void_param.c b/tests/tests2/43_void_param.c
index de17098..de17098 100644
--- a/tests2/43_void_param.c
+++ b/tests/tests2/43_void_param.c
diff --git a/tests2/43_void_param.expect b/tests/tests2/43_void_param.expect
index 092bfb9..092bfb9 100644
--- a/tests2/43_void_param.expect
+++ b/tests/tests2/43_void_param.expect
diff --git a/tests2/44_scoped_declarations.c b/tests/tests2/44_scoped_declarations.c
index 2febf98..f38664f 100644
--- a/tests2/44_scoped_declarations.c
+++ b/tests/tests2/44_scoped_declarations.c
@@ -1,17 +1,17 @@
-#include <stdio.h>
-
-int main()
-{
- int a;
-
- for (a = 0; a < 2; a++)
- {
- int b = a;
- }
-
- printf("it's all good\n");
-
- return 0;
-}
-
-/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
+#include <stdio.h>
+
+int main()
+{
+ int a;
+
+ for (a = 0; a < 2; a++)
+ {
+ int b = a;
+ }
+
+ printf("it's all good\n");
+
+ return 0;
+}
+
+/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
diff --git a/tests2/44_scoped_declarations.expect b/tests/tests2/44_scoped_declarations.expect
index 231ccc0..231ccc0 100644
--- a/tests2/44_scoped_declarations.expect
+++ b/tests/tests2/44_scoped_declarations.expect
diff --git a/tests2/45_empty_for.c b/tests/tests2/45_empty_for.c
index b14e9d4..7cef513 100644
--- a/tests2/45_empty_for.c
+++ b/tests/tests2/45_empty_for.c
@@ -1,18 +1,18 @@
-#include <stdio.h>
-
-int main()
-{
- int Count = 0;
-
- for (;;)
- {
- Count++;
- printf("%d\n", Count);
- if (Count >= 10)
- break;
- }
-
- return 0;
-}
-
-/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
+#include <stdio.h>
+
+int main()
+{
+ int Count = 0;
+
+ for (;;)
+ {
+ Count++;
+ printf("%d\n", Count);
+ if (Count >= 10)
+ break;
+ }
+
+ return 0;
+}
+
+/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
diff --git a/tests2/45_empty_for.expect b/tests/tests2/45_empty_for.expect
index f00c965..f00c965 100644
--- a/tests2/45_empty_for.expect
+++ b/tests/tests2/45_empty_for.expect
diff --git a/tests2/46_grep.c b/tests/tests2/46_grep.c
index 5f52220..5f52220 100644
--- a/tests2/46_grep.c
+++ b/tests/tests2/46_grep.c
diff --git a/tests2/47_switch_return.c b/tests/tests2/47_switch_return.c
index 1ec7924..1ec7924 100644
--- a/tests2/47_switch_return.c
+++ b/tests/tests2/47_switch_return.c
diff --git a/tests2/47_switch_return.expect b/tests/tests2/47_switch_return.expect
index b6deb7e..b6deb7e 100644
--- a/tests2/47_switch_return.expect
+++ b/tests/tests2/47_switch_return.expect
diff --git a/tests2/48_nested_break.c b/tests/tests2/48_nested_break.c
index 5bc5ba4..5bc5ba4 100644
--- a/tests2/48_nested_break.c
+++ b/tests/tests2/48_nested_break.c
diff --git a/tests2/48_nested_break.expect b/tests/tests2/48_nested_break.expect
index 573541a..573541a 100644
--- a/tests2/48_nested_break.expect
+++ b/tests/tests2/48_nested_break.expect
diff --git a/tests2/49_bracket_evaluation.c b/tests/tests2/49_bracket_evaluation.c
index 0cbe57d..0cbe57d 100644
--- a/tests2/49_bracket_evaluation.c
+++ b/tests/tests2/49_bracket_evaluation.c
diff --git a/tests2/49_bracket_evaluation.expect b/tests/tests2/49_bracket_evaluation.expect
index 1da66db..1da66db 100644
--- a/tests2/49_bracket_evaluation.expect
+++ b/tests/tests2/49_bracket_evaluation.expect
diff --git a/tests2/50_logical_second_arg.c b/tests/tests2/50_logical_second_arg.c
index 5fa0bb9..ddec08c 100644
--- a/tests2/50_logical_second_arg.c
+++ b/tests/tests2/50_logical_second_arg.c
@@ -1,29 +1,29 @@
-#include <stdio.h>
-
-int fred()
-{
- printf("fred\n");
- return 0;
-}
-
-int joe()
-{
- printf("joe\n");
- return 1;
-}
-
-int main()
-{
- printf("%d\n", fred() && joe());
- printf("%d\n", fred() || joe());
- printf("%d\n", joe() && fred());
- printf("%d\n", joe() || fred());
- printf("%d\n", fred() && (1 + joe()));
- printf("%d\n", fred() || (0 + joe()));
- printf("%d\n", joe() && (0 + fred()));
- printf("%d\n", joe() || (1 + fred()));
-
- return 0;
-}
-
-/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
+#include <stdio.h>
+
+int fred()
+{
+ printf("fred\n");
+ return 0;
+}
+
+int joe()
+{
+ printf("joe\n");
+ return 1;
+}
+
+int main()
+{
+ printf("%d\n", fred() && joe());
+ printf("%d\n", fred() || joe());
+ printf("%d\n", joe() && fred());
+ printf("%d\n", joe() || fred());
+ printf("%d\n", fred() && (1 + joe()));
+ printf("%d\n", fred() || (0 + joe()));
+ printf("%d\n", joe() && (0 + fred()));
+ printf("%d\n", joe() || (1 + fred()));
+
+ return 0;
+}
+
+/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
diff --git a/tests2/50_logical_second_arg.expect b/tests/tests2/50_logical_second_arg.expect
index d6174ae..d6174ae 100644
--- a/tests2/50_logical_second_arg.expect
+++ b/tests/tests2/50_logical_second_arg.expect
diff --git a/tests2/51_static.c b/tests/tests2/51_static.c
index d6c0917..d6c0917 100644
--- a/tests2/51_static.c
+++ b/tests/tests2/51_static.c
diff --git a/tests2/51_static.expect b/tests/tests2/51_static.expect
index 18224fa..18224fa 100644
--- a/tests2/51_static.expect
+++ b/tests/tests2/51_static.expect
diff --git a/tests2/52_unnamed_enum.c b/tests/tests2/52_unnamed_enum.c
index d0395b2..d0395b2 100644
--- a/tests2/52_unnamed_enum.c
+++ b/tests/tests2/52_unnamed_enum.c
diff --git a/tests2/52_unnamed_enum.expect b/tests/tests2/52_unnamed_enum.expect
index 84f2ac8..84f2ac8 100644
--- a/tests2/52_unnamed_enum.expect
+++ b/tests/tests2/52_unnamed_enum.expect
diff --git a/tests2/54_goto.c b/tests/tests2/54_goto.c
index 9509e83..2e151bb 100644
--- a/tests2/54_goto.c
+++ b/tests/tests2/54_goto.c
@@ -1,56 +1,56 @@
-#include <stdio.h>
-
-void fred()
-{
- printf("In fred()\n");
- goto done;
- printf("In middle\n");
-done:
- printf("At end\n");
-}
-
-void joe()
-{
- int b = 5678;
-
- printf("In joe()\n");
-
- {
- int c = 1234;
- printf("c = %d\n", c);
- goto outer;
- printf("uh-oh\n");
- }
-
-outer:
-
- printf("done\n");
-}
-
-void henry()
-{
- int a;
-
- printf("In henry()\n");
- goto inner;
-
- {
- int b;
-inner:
- b = 1234;
- printf("b = %d\n", b);
- }
-
- printf("done\n");
-}
-
-int main()
-{
- fred();
- joe();
- henry();
-
- return 0;
-}
-
-/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
+#include <stdio.h>
+
+void fred()
+{
+ printf("In fred()\n");
+ goto done;
+ printf("In middle\n");
+done:
+ printf("At end\n");
+}
+
+void joe()
+{
+ int b = 5678;
+
+ printf("In joe()\n");
+
+ {
+ int c = 1234;
+ printf("c = %d\n", c);
+ goto outer;
+ printf("uh-oh\n");
+ }
+
+outer:
+
+ printf("done\n");
+}
+
+void henry()
+{
+ int a;
+
+ printf("In henry()\n");
+ goto inner;
+
+ {
+ int b;
+inner:
+ b = 1234;
+ printf("b = %d\n", b);
+ }
+
+ printf("done\n");
+}
+
+int main()
+{
+ fred();
+ joe();
+ henry();
+
+ return 0;
+}
+
+/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
diff --git a/tests2/54_goto.expect b/tests/tests2/54_goto.expect
index 8e553fa..8e553fa 100644
--- a/tests2/54_goto.expect
+++ b/tests/tests2/54_goto.expect
diff --git a/tests2/55_lshift_type.c b/tests/tests2/55_lshift_type.c
index aa3e51a..aa3e51a 100644
--- a/tests2/55_lshift_type.c
+++ b/tests/tests2/55_lshift_type.c
diff --git a/tests2/55_lshift_type.expect b/tests/tests2/55_lshift_type.expect
index 8523767..8523767 100644
--- a/tests2/55_lshift_type.expect
+++ b/tests/tests2/55_lshift_type.expect
diff --git a/tests2/LICENSE b/tests/tests2/LICENSE
index b08a652..b08a652 100644
--- a/tests2/LICENSE
+++ b/tests/tests2/LICENSE
diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile
new file mode 100644
index 0000000..bf7511f
--- /dev/null
+++ b/tests/tests2/Makefile
@@ -0,0 +1,98 @@
+TOP = ../..
+include $(TOP)/Makefile
+VPATH = $(top_srcdir)/tests/tests2
+
+TCCFLAGS = -B$(TOP)
+ifdef CONFIG_WIN32
+ TCCFLAGS = -B$(top_srcdir)/win32 -I$(top_srcdir)/include -L$(TOP)
+endif
+
+ifeq ($(TARGETOS),Darwin)
+ CFLAGS += -Wl,-flat_namespace,-undefined,warning
+ TCCFLAGS += -D_ANSI_SOURCE
+ export MACOSX_DEPLOYMENT_TARGET:=10.2
+endif
+
+TCC_RUN = $(TOP)/tcc $(TCCFLAGS) -run
+
+TESTS = \
+ 00_assignment.test \
+ 01_comment.test \
+ 02_printf.test \
+ 03_struct.test \
+ 04_for.test \
+ 05_array.test \
+ 06_case.test \
+ 07_function.test \
+ 08_while.test \
+ 09_do_while.test \
+ 10_pointer.test \
+ 11_precedence.test \
+ 12_hashdefine.test \
+ 13_integer_literals.test \
+ 14_if.test \
+ 15_recursion.test \
+ 16_nesting.test \
+ 17_enum.test \
+ 18_include.test \
+ 19_pointer_arithmetic.test \
+ 20_pointer_comparison.test \
+ 21_char_array.test \
+ 22_floating_point.test \
+ 23_type_coercion.test \
+ 24_math_library.test \
+ 25_quicksort.test \
+ 26_character_constants.test \
+ 27_sizeof.test \
+ 28_strings.test \
+ 29_array_address.test \
+ 31_args.test \
+ 32_led.test \
+ 33_ternary_op.test \
+ 35_sizeof.test \
+ 36_array_initialisers.test \
+ 37_sprintf.test \
+ 38_multiple_array_index.test \
+ 39_typedef.test \
+ 40_stdio.test \
+ 41_hashif.test \
+ 42_function_pointer.test \
+ 43_void_param.test \
+ 44_scoped_declarations.test \
+ 45_empty_for.test \
+ 47_switch_return.test \
+ 48_nested_break.test \
+ 49_bracket_evaluation.test \
+ 50_logical_second_arg.test \
+ 51_static.test \
+ 52_unnamed_enum.test \
+ 54_goto.test \
+ 55_lshift_type.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
+
+# some tests do not pass on all platforms, remove them for now
+ifeq ($(TARGETOS),Darwin)
+ TESTS := $(filter-out 40_stdio.test,$(TESTS))
+endif
+ifdef CONFIG_WIN32
+ TESTS := $(filter-out 24_math_library.test 28_strings.test,$(TESTS))
+endif
+
+%.test: %.c %.expect
+ @echo Test: $*...
+ @if [ "x`echo $* | grep args`" != "x" ]; \
+ then $(TCC_RUN) $< - 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)
+
+clean:
+ rm -vf fred.txt *.output
diff --git a/tests2/Makefile b/tests2/Makefile
deleted file mode 100644
index bf4c2cd..0000000
--- a/tests2/Makefile
+++ /dev/null
@@ -1,99 +0,0 @@
-TOP = ..
-include $(TOP)/Makefile
-
-ifeq ($(TARGETOS),Darwin)
- CFLAGS+=-Wl,-flat_namespace,-undefined,warning
- TCCFLAGS=-D_ANSI_SOURCE
- export MACOSX_DEPLOYMENT_TARGET:=10.2
-endif
-
-ifdef CONFIG_WIN32
- TCCFLAGS=-I $(TOP)/win32/include -L$(TOP)
-endif
-
-TESTS= 00_assignment.test \
- 01_comment.test \
- 02_printf.test \
- 03_struct.test \
- 04_for.test \
- 05_array.test \
- 06_case.test \
- 07_function.test \
- 08_while.test \
- 09_do_while.test \
- 10_pointer.test \
- 11_precedence.test \
- 12_hashdefine.test \
- 13_integer_literals.test \
- 14_if.test \
- 15_recursion.test \
- 16_nesting.test \
- 17_enum.test \
- 18_include.test \
- 19_pointer_arithmetic.test \
- 20_pointer_comparison.test \
- 21_char_array.test \
- 22_floating_point.test \
- 23_type_coercion.test \
- 24_math_library.test \
- 25_quicksort.test \
- 26_character_constants.test \
- 27_sizeof.test \
- 28_strings.test \
- 29_array_address.test \
- 31_args.test \
- 32_led.test \
- 33_ternary_op.test \
- 35_sizeof.test \
- 36_array_initialisers.test \
- 37_sprintf.test \
- 38_multiple_array_index.test \
- 39_typedef.test \
- 40_stdio.test \
- 41_hashif.test \
- 42_function_pointer.test \
- 43_void_param.test \
- 44_scoped_declarations.test \
- 45_empty_for.test \
- 47_switch_return.test \
- 48_nested_break.test \
- 49_bracket_evaluation.test \
- 50_logical_second_arg.test \
- 51_static.test \
- 52_unnamed_enum.test \
- 54_goto.test \
- 55_lshift_type.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
-
-# some tests do not pass on all platforms, remove them for now
-ifeq ($(TARGETOS),Darwin)
- TESTS := $(filter-out 40_stdio.test,$(TESTS))
-endif
-ifdef CONFIG_WIN32
- TESTS := $(filter-out 24_math_library.test,$(TESTS))
- TESTS := $(filter-out 28_strings.test,$(TESTS))
-endif
-
-%.test: %.expect %.c
- @echo Test: $*...
- @if [ "x`echo $* | grep args`" != "x" ]; \
- then \
- ../tcc -B.. $(TCCFLAGS) -run $*.c - arg1 arg2 arg3 arg4 2>&1 >$*.output; \
- else \
- ../tcc -B.. $(TCCFLAGS) -run $*.c 2>&1 >$*.output; \
- fi
- @if diff -bu $*.expect $*.output ; \
- then \
- rm -f $*.output \
- else \
- echo "ERROR: test $*"; \
- fi
-
-all: test
-
-test: $(TESTS)
-
-# vim: set expandtab ts=4 sw=4 sts=4 tw=80 :
diff --git a/win32/build-tcc.bat b/win32/build-tcc.bat
index 9e7f8eb..5c1ee59 100644
--- a/win32/build-tcc.bat
+++ b/win32/build-tcc.bat
@@ -1,64 +1,60 @@
-@rem ----------------------------------------------------
-@rem batch file to build tcc using gcc and ar from mingw
-@rem ----------------------------------------------------
-
-echo>..\config.h #define TCC_VERSION "0.9.25"
-
-@if _%PROCESSOR_ARCHITEW6432%_==_AMD64_ goto x86_64
-@if _%PROCESSOR_ARCHITECTURE%_==_AMD64_ goto x86_64
-
-@set target=-DTCC_TARGET_PE -DTCC_TARGET_I386
-@set CC=gcc -Os -s -fno-strict-aliasing
-@set AR=ar
-@set P=32
-@goto tools
-
-:x86_64
-@set target=-DTCC_TARGET_PE -DTCC_TARGET_X86_64
-@rem mingw 64 has an ICE with -Os
-@set CC=x86_64-pc-mingw32-gcc -O0 -s -fno-strict-aliasing
-@set AR=x86_64-pc-mingw32-ar
-@set P=64
-
-:tools
-%CC% %target% tools/tiny_impdef.c -o tiny_impdef.exe
-%CC% %target% tools/tiny_libmaker.c -o tiny_libmaker.exe
-
-:libtcc
-if not exist libtcc\nul 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 lib/libtcc.def
-
-:tcc
-%CC% %target% ../tcc.c -o tcc.exe -ltcc -Llibtcc
-
-:copy_std_includes
-copy ..\include\*.h include
-
-:libtcc1.a
-.\tcc %target% -c ../lib/libtcc1.c
-.\tcc %target% -c lib/crt1.c
-.\tcc %target% -c lib/wincrt1.c
-.\tcc %target% -c lib/dllcrt1.c
-.\tcc %target% -c lib/dllmain.c
-.\tcc %target% -c lib/chkstk.S
-@if _%P%_==_64_ goto lib64
-
-:lib32
-.\tcc %target% -c ../lib/alloca86.S
-.\tcc %target% -c ../lib/alloca86-bt.S
-.\tcc %target% -c ../lib/bcheck.c
-tiny_libmaker lib/libtcc1.a libtcc1.o alloca86.o alloca86-bt.o crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o bcheck.o
-@goto the_end
-
-:lib64
-.\tcc %target% -c ../lib/alloca86_64.S
-tiny_libmaker lib/libtcc1.a libtcc1.o alloca86_64.o crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
-
-:the_end
-del *.o
-
-:libtcc_test
-.\tcc -v -I libtcc -ltcc ../tests/libtcc_test.c
-.\libtcc_test
+@rem ----------------------------------------------------
+@rem batch file to build tcc using mingw gcc
+@rem ----------------------------------------------------
+
+@set /p VERSION= < ..\VERSION
+echo>..\config.h #define TCC_VERSION "%VERSION%"
+
+@if _%PROCESSOR_ARCHITEW6432%_==_AMD64_ goto x86_64
+@if _%PROCESSOR_ARCHITECTURE%_==_AMD64_ goto x86_64
+
+@set target=-DTCC_TARGET_PE -DTCC_TARGET_I386
+@set CC=gcc -Os -s -fno-strict-aliasing
+@set P=32
+@goto tools
+
+:x86_64
+@set target=-DTCC_TARGET_PE -DTCC_TARGET_X86_64
+@rem mingw 64 has an ICE with -Os
+@set CC=x86_64-pc-mingw32-gcc -O0 -s -fno-strict-aliasing
+@set P=64
+@goto tools
+
+:tools
+%CC% %target% tools/tiny_impdef.c -o tiny_impdef.exe
+%CC% %target% tools/tiny_libmaker.c -o tiny_libmaker.exe
+
+:libtcc
+if not exist libtcc\nul 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
+
+:tcc
+%CC% %target% ../tcc.c -o tcc.exe -ltcc -Llibtcc
+
+:copy_std_includes
+copy ..\include\*.h include
+
+:libtcc1.a
+.\tcc %target% -c ../lib/libtcc1.c
+.\tcc %target% -c lib/crt1.c
+.\tcc %target% -c lib/wincrt1.c
+.\tcc %target% -c lib/dllcrt1.c
+.\tcc %target% -c lib/dllmain.c
+.\tcc %target% -c lib/chkstk.S
+goto lib%P%
+
+:lib32
+.\tcc %target% -c ../lib/alloca86.S
+.\tcc %target% -c ../lib/alloca86-bt.S
+.\tcc %target% -c ../lib/bcheck.c
+tiny_libmaker lib/libtcc1.a libtcc1.o alloca86.o alloca86-bt.o crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o bcheck.o
+@goto the_end
+
+:lib64
+.\tcc %target% -c ../lib/alloca86_64.S
+tiny_libmaker lib/libtcc1.a libtcc1.o alloca86_64.o crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
+
+:the_end
+del *.o
diff --git a/win32/include/_mingw.h b/win32/include/_mingw.h
index 00ff2fc..14cd718 100644
--- a/win32/include/_mingw.h
+++ b/win32/include/_mingw.h
@@ -19,7 +19,6 @@
#define __MINGW_H
/* some winapi files define these before including _mingw.h --> */
-#undef NULL
#undef __cdecl
#undef _X86_
#undef WIN32
@@ -38,8 +37,9 @@
#define __unaligned __attribute__((packed))
#define __fastcall __attribute__((fastcall))
-#define __MINGW_IMPORT extern __declspec(dllimport)
+#define __MSVCRT__ 1
#undef _MSVCRT_
+#define __MINGW_IMPORT extern __declspec(dllimport)
#define __MINGW_ATTRIB_NORETURN
#define __MINGW_ATTRIB_CONST
#define __MINGW_ATTRIB_DEPRECATED
diff --git a/win32/include/malloc.h b/win32/include/malloc.h
index 8426600..87f1868 100644
--- a/win32/include/malloc.h
+++ b/win32/include/malloc.h
@@ -25,7 +25,7 @@ extern "C" {
#endif
#ifndef _STATIC_ASSERT
-#define _STATIC_ASSERT(expr) typedef char __static_assert_t[(expr)]
+#define _STATIC_ASSERT(expr) extern void __static_assert_t(int [(expr)?1:-1])
#endif
/* Return codes for _heapwalk() */
diff --git a/win32/lib/wincrt1.c b/win32/lib/wincrt1.c
index 0466da9..77e74b8 100644
--- a/win32/lib/wincrt1.c
+++ b/win32/lib/wincrt1.c
@@ -1,6 +1,7 @@
//+---------------------------------------------------------------------------
#include <windows.h>
+#include <stdlib.h>
#define __UNKNOWN_APP 0
#define __CONSOLE_APP 1
diff --git a/win32/tcc-win32.txt b/win32/tcc-win32.txt
index 64ff885..ef784d0 100644
--- a/win32/tcc-win32.txt
+++ b/win32/tcc-win32.txt
@@ -1,157 +1,156 @@
-
- TinyCC
- ======
-
- This file contains specific information for usage of TinyCC
- under MS-Windows. See tcc-doc.html to have all the features.
-
-
-
- Compilation from source:
- ------------------------
- * You can use the MinGW and MSYS tools available at
-
- http://www.mingw.org
-
- Untar the TCC archive and type in the MSYS shell:
-
- ./configure
- make
- make install
-
- The default install location is c:\Program Files\tcc
-
-
- * Alternatively you can compile TCC with just GCC from MinGW using
-
- win32\build-tcc.bat
-
- To install, copy the entire contents of the win32 directory to
- where you want.
-
-
-
- Installation from the binary ZIP package:
- -----------------------------------------
- Unzip the package to a directory of your choice.
-
-
- Set the system PATH:
- --------------------
- To be able to invoke the compiler from everywhere on your computer by
- just typing "tcc", please add the directory containing tcc.exe to your
- system PATH.
-
-
-
- Examples:
- ---------
- Open a console window (DOS box) and 'cd' to the examples directory.
-
- For the 'Fibonacci' example type:
-
- tcc fib.c
-
- For the 'Hello Windows' GUI example type:
-
- tcc hello_win.c
-
- For the 'Hello DLL' example type
-
- tcc -shared dll.c
- tiny_impdef dll.dll (optional)
- tcc hello_dll.c dll.def
-
- For the 'libtcc_test' example type
-
- tcc examples/libtcc_test.c -I libtcc -ltcc
-
-
- Import Definition Files:
- ------------------------
- To link with Windows system DLLs, TCC uses import definition
- files (.def) instead of libraries.
-
- The included 'tiny_impdef' program may be used to make additional
- .def files for any DLL. For example:
-
- tiny_impdef.exe opengl32.dll
-
- Put opengl32.def into the tcc/lib directory. Specify -lopengl32 at
- the TCC commandline to link a program that uses opengl32.dll.
-
-
-
- Header Files:
- -------------
- The system header files (except _mingw.h) are from the MinGW
- distribution:
-
- http://www.mingw.org/
-
- From the windows headers, only a minimal set is included. If you need
- more, get MinGW's "w32api" package. Extract the files from "include"
- into your "tcc/include/winapi" directory.
-
-
-
- Resource Files:
- ---------------
- TCC can link windows resources in coff format as generated by MinGW's
- windres.exe. For example:
-
- windres -O coff app.rc -o appres.o
- tcc app.c appres.o -o app.exe
-
-
-
- Tiny Libmaker:
- --------------
- The included tiny_libmaker tool by Timovj Lahde can be used as
- 'ar' replacement to make a library from several object files:
-
- tiny_libmaker [rcs] library objectfiles ...
-
-
-
- Limitations:
- ------------
- - On the object file level, currently TCC supports only the ELF format,
- not COFF as used by MinGW and MSVC. It is not possible to exchange
- object files or libraries between TCC and these compilers. However
- libraries for TCC from objects by TCC can be made using tiny_libmaker
- or MinGW's ar.
-
- - No leading underscore is generated in the ELF symbols.
-
- - With DLLs, only functions (not data) can be im-/exported.
-
- - Bounds checking (option -b) is not supported currently.
-
- - 64-bit systems are not (yet) supported.
-
-
-
- Documentation and License:
- --------------------------
- TCC is distributed under the GNU Lesser General Public License. (See
- COPYING file or http://www.gnu.org/licenses/lgpl-2.1.html)
-
- TinyCC homepage is at:
-
- http://fabrice.bellard.free.fr/tcc/
-
-
-
- WinAPI Help and 3rd-party tools:
- --------------------------------
- The Windows API documentation (Win95) in a single .hlp file is
- available on the lcc-win32 site as "win32hlp.exe" or from other
- locations as "win32hlp_big.zip".
-
- A nice RAD tool to create windows resources (dialog boxes etc.) is
- "ResEd", available at the RadASM website.
-
-
-
- --- grischka
+
+ TinyCC
+ ======
+
+ This file contains specific information for usage of TinyCC
+ under MS-Windows. See tcc-doc.html to have all the features.
+
+
+ Installation from the binary ZIP package:
+ -----------------------------------------
+ Unzip the package to a directory of your choice.
+
+
+ Set the system PATH:
+ --------------------
+ To be able to invoke the compiler from everywhere on your computer by
+ just typing "tcc", please add the directory containing tcc.exe to your
+ system PATH.
+
+
+ Examples:
+ ---------
+ Open a console window (DOS box) and 'cd' to the examples directory.
+
+ For the 'Fibonacci' example type:
+
+ tcc fib.c
+
+ For the 'Hello Windows' GUI example type:
+
+ tcc hello_win.c
+
+ For the 'Hello DLL' example type
+
+ tcc -shared dll.c
+ tiny_impdef dll.dll (optional)
+ tcc hello_dll.c dll.def
+
+
+ Using libtcc as JIT compiler in your program
+ --------------------------------------------
+ Check out the 'libtcc_test' example:
+
+ - Running it from source:
+ tcc -I libtcc libtcc/libtcc.def -run examples/libtcc_test.c
+
+ - Compiling with TCC:
+ tcc examples/libtcc_test.c -I libtcc libtcc/libtcc.def
+
+ - Compiling with MinGW:
+ gcc examples/libtcc_test.c -I libtcc libtcc.dll
+
+ - Compiling with MSVC:
+ lib /def:libtcc\libtcc.def /out:libtcc.lib
+ cl /MD examples/libtcc_test.c -I libtcc libtcc.lib
+
+
+ Import Definition Files:
+ ------------------------
+ To link with Windows system DLLs, TCC uses import definition
+ files (.def) instead of libraries.
+
+ The included 'tiny_impdef' program may be used to make additional
+ .def files for any DLL. For example:
+
+ tiny_impdef.exe opengl32.dll
+
+ Put opengl32.def into the tcc/lib directory. Specify -lopengl32 at
+ the TCC commandline to link a program that uses opengl32.dll.
+
+
+ Header Files:
+ -------------
+ The system header files (except _mingw.h) are from the MinGW
+ distribution:
+
+ http://www.mingw.org/
+
+ From the windows headers, only a minimal set is included. If you need
+ more, get MinGW's "w32api" package. Extract the files from "include"
+ into your "tcc/include/winapi" directory.
+
+
+ Resource Files:
+ ---------------
+ TCC can link windows resources in coff format as generated by MinGW's
+ windres.exe. For example:
+
+ windres -O coff app.rc -o appres.o
+ tcc app.c appres.o -o app.exe
+
+
+ Tiny Libmaker:
+ --------------
+ The included tiny_libmaker tool by Timovj Lahde can be used as
+ 'ar' replacement to make a library from several object files:
+
+ tiny_libmaker [rcs] library objectfiles ...
+
+
+ Compilation from source:
+ ------------------------
+ * You can use the MinGW and MSYS tools available at
+
+ http://www.mingw.org
+
+ Untar the TCC archive and type in the MSYS shell:
+
+ ./configure [--prefix installpath]
+ make
+ make install
+
+ The default install location is c:\Program Files\tcc
+
+ * Alternatively you can compile TCC with just GCC from MinGW using
+
+ build-tcc.bat (from the win32 directory)
+
+ To install, copy the entire contents of the win32 directory to
+ where you want.
+
+
+ Limitations:
+ ------------
+ - On the object file level, currently TCC supports only the ELF format,
+ not COFF as used by MinGW and MSVC. It is not possible to exchange
+ object files or libraries between TCC and these compilers. However
+ libraries for TCC from objects by TCC can be made using tiny_libmaker
+ or MinGW's ar.
+
+ - No leading underscore is generated in the ELF symbols.
+
+ - Bounds checking (option -b) is not supported on 64-bit OS.
+
+
+ Documentation and License:
+ --------------------------
+ TCC is distributed under the GNU Lesser General Public License. (See
+ COPYING file or http://www.gnu.org/licenses/lgpl-2.1.html)
+
+ TinyCC homepage is at:
+
+ http://fabrice.bellard.free.fr/tcc/
+
+
+ WinAPI Help and 3rd-party tools:
+ --------------------------------
+ The Windows API documentation (Win95) in a single .hlp file is
+ available on the lcc-win32 site as "win32hlp.exe" or from other
+ locations as "win32hlp_big.zip".
+
+ A nice RAD tool to create windows resources (dialog boxes etc.) is
+ "ResEd", available at the RadASM website.
+
+
+ --- grischka
diff --git a/win32/tools/tiny_impdef.c b/win32/tools/tiny_impdef.c
index 586c49d..1739549 100644
--- a/win32/tools/tiny_impdef.c
+++ b/win32/tools/tiny_impdef.c
@@ -25,9 +25,10 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
+#include <io.h>
#include <malloc.h>
-char *get_export_names(FILE *fp);
+char *get_export_names(int fd);
#define tcc_free free
#define tcc_realloc realloc
@@ -114,7 +115,7 @@ usage:
if (v)
printf("--> %s\n", file);
- p = get_export_names(fp);
+ p = get_export_names(fileno(fp));
if (NULL == p) {
fprintf(stderr, "tiny_impdef: could not get exported function names.\n");
goto the_end;
@@ -149,18 +150,18 @@ the_end:
return ret;
}
-/* -------------------------------------------------------------- */
-
-int read_mem(FILE *fp, unsigned offset, void *buffer, unsigned len)
+int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
{
- fseek(fp, offset, 0);
- return len == fread(buffer, 1, len, fp);
+ lseek(fd, offset, SEEK_SET);
+ return len == read(fd, buffer, len);
}
/* -------------------------------------------------------------- */
+
+/* -------------------------------------------------------------- */
#endif
-char *get_export_names(FILE *fp)
+char *get_export_names(int fd)
{
int l, i, n, n0;
char *p;
@@ -182,20 +183,20 @@ char *get_export_names(FILE *fp)
n = n0 = 0;
p = NULL;
- if (!read_mem(fp, 0, &dh, sizeof dh))
+ if (!read_mem(fd, 0, &dh, sizeof dh))
goto the_end;
- if (!read_mem(fp, dh.e_lfanew, &sig, sizeof sig))
+ if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig))
goto the_end;
if (sig != 0x00004550)
goto the_end;
pef_hdroffset = dh.e_lfanew + sizeof sig;
- if (!read_mem(fp, pef_hdroffset, &ih, sizeof ih))
+ if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
goto the_end;
if (MACHINE != ih.Machine)
goto the_end;
opt_hdroffset = pef_hdroffset + sizeof ih;
sec_hdroffset = opt_hdroffset + sizeof oh;
- if (!read_mem(fp, opt_hdroffset, &oh, sizeof oh))
+ if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
goto the_end;
if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
@@ -204,7 +205,7 @@ char *get_export_names(FILE *fp)
addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
//printf("addr: %08x\n", addr);
for (i = 0; i < ih.NumberOfSections; ++i) {
- if (!read_mem(fp, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
+ if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
goto the_end;
//printf("vaddr: %08x\n", ish.VirtualAddress);
if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData)
@@ -214,18 +215,18 @@ char *get_export_names(FILE *fp)
found:
ref = ish.VirtualAddress - ish.PointerToRawData;
- if (!read_mem(fp, addr - ref, &ied, sizeof ied))
+ if (!read_mem(fd, addr - ref, &ied, sizeof ied))
goto the_end;
namep = ied.AddressOfNames - ref;
for (i = 0; i < ied.NumberOfNames; ++i) {
- if (!read_mem(fp, namep, &ptr, sizeof ptr))
+ if (!read_mem(fd, namep, &ptr, sizeof ptr))
goto the_end;
namep += sizeof ptr;
for (l = 0;;) {
if (n+1 >= n0)
p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
- if (!read_mem(fp, ptr - ref + l, p + n, 1) || ++l >= 80) {
+ if (!read_mem(fd, ptr - ref + l, p + n, 1) || ++l >= 80) {
tcc_free(p), p = NULL;
goto the_end;
}
diff --git a/win32/tools/tiny_libmaker.c b/win32/tools/tiny_libmaker.c
index 42373d8..62d2a2e 100644
--- a/win32/tools/tiny_libmaker.c
+++ b/win32/tools/tiny_libmaker.c
@@ -21,10 +21,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#ifdef _WIN32
-#include <io.h> /* for mktemp */
-#endif
-
#include "../../elf.h"
#ifdef TCC_TARGET_X86_64
@@ -77,18 +73,19 @@ ArHdr arhdro = {
int main(int argc, char **argv)
{
- FILE *fi, *fh, *fo;
+ FILE *fi, *fh = NULL, *fo = NULL;
ElfW(Ehdr) *ehdr;
ElfW(Shdr) *shdr;
ElfW(Sym) *sym;
int i, fsize, iarg;
char *buf, *shstr, *symtab = NULL, *strtab = NULL;
- int symtabsize = 0, strtabsize = 0;
+ int symtabsize = 0;//, strtabsize = 0;
char *anames = NULL;
int *afpos = NULL;
int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
char afile[260], tfile[260], stmp[20];
char *file, *name;
+ int ret = 2;
strcpy(afile, "ar_test.a");
@@ -111,19 +108,17 @@ int main(int argc, char **argv)
}
}
- strcpy(tfile, "./XXXXXX");
- if (!mktemp(tfile) || (fo = fopen(tfile, "wb+")) == NULL)
+ if ((fh = fopen(afile, "wb")) == NULL)
{
- fprintf(stderr, "Can't open temporary file %s\n", tfile);
- return 2;
+ fprintf(stderr, "Can't open file %s \n", afile);
+ goto the_end;
}
- if ((fh = fopen(afile, "wb")) == NULL)
+ sprintf(tfile, "%s.tmp", afile);
+ if ((fo = fopen(tfile, "wb+")) == NULL)
{
- fprintf(stderr, "Can't open file %s \n", afile);
- fclose(fo);
- remove(tfile);
- return 2;
+ fprintf(stderr, "Can't create temporary file %s\n", tfile);
+ goto the_end;
}
funcmax = 250;
@@ -140,9 +135,7 @@ int main(int argc, char **argv)
if ((fi = fopen(argv[iarg], "rb")) == NULL)
{
fprintf(stderr, "Can't open file %s \n", argv[iarg]);
- fclose(fo);
- remove(tfile);
- return 2;
+ goto the_end;
}
fseek(fi, 0, SEEK_END);
fsize = ftell(fi);
@@ -152,14 +145,13 @@ int main(int argc, char **argv)
fclose(fi);
//printf("%s:\n", argv[iarg]);
+
// elf header
ehdr = (ElfW(Ehdr) *)buf;
if (ehdr->e_ident[4] != ELFCLASSW)
{
fprintf(stderr, "Unsupported Elf Class: %s\n", argv[iarg]);
- fclose(fo);
- remove(tfile);
- return 2;
+ goto the_end;
}
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
@@ -167,7 +159,8 @@ int main(int argc, char **argv)
for (i = 0; i < ehdr->e_shnum; i++)
{
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
- if (!shdr->sh_offset) continue;
+ if (!shdr->sh_offset)
+ continue;
if (shdr->sh_type == SHT_SYMTAB)
{
symtab = (char *)(buf + shdr->sh_offset);
@@ -178,7 +171,7 @@ int main(int argc, char **argv)
if (!strcmp(shstr + shdr->sh_name, ".strtab"))
{
strtab = (char *)(buf + shdr->sh_offset);
- strtabsize = shdr->sh_size;
+ //strtabsize = shdr->sh_size;
}
}
}
@@ -210,7 +203,7 @@ int main(int argc, char **argv)
}
file = argv[iarg];
- for (name = strchr(file, 0);
+ for (name = strchr(file, 0);
name > file && name[-1] != '/' && name[-1] != '\\';
--name);
istrlen = strlen(name);
@@ -219,7 +212,6 @@ int main(int argc, char **argv)
memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name));
memcpy(arhdro.ar_name, name, istrlen);
arhdro.ar_name[istrlen] = '/';
-
sprintf(stmp, "%-10d", fsize);
memcpy(&arhdro.ar_size, stmp, 10);
fwrite(&arhdro, sizeof(arhdro), 1, fo);
@@ -229,36 +221,38 @@ int main(int argc, char **argv)
fpos += (fsize + sizeof(arhdro));
}
hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
- if ((hofs & 1)) { // align
- hofs++;
- fpos = 1;
- } else fpos = 0;
+ fpos = 0;
+ if ((hofs & 1)) // align
+ hofs++, fpos = 1;
// write header
fwrite("!<arch>\n", 8, 1, fh);
sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)));
memcpy(&arhdr.ar_size, stmp, 10);
fwrite(&arhdr, sizeof(arhdr), 1, fh);
afpos[0] = le2belong(funccnt);
- for (i=1; i<=funccnt; i++) {
+ for (i=1; i<=funccnt; i++)
afpos[i] = le2belong(afpos[i] + hofs);
- }
fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh);
fwrite(anames, strpos, 1, fh);
- if (fpos) fwrite("", 1, 1, fh);
+ if (fpos)
+ fwrite("", 1, 1, fh);
// write objects
fseek(fo, 0, SEEK_END);
fsize = ftell(fo);
fseek(fo, 0, SEEK_SET);
buf = malloc(fsize + 1);
fread(buf, fsize, 1, fo);
- fclose(fo);
fwrite(buf, fsize, 1, fh);
- fclose(fh);
free(buf);
+ ret = 0;
+the_end:
if (anames)
free(anames);
if (afpos)
free(afpos);
- remove(tfile);
- return 0;
+ if (fh)
+ fclose(fh);
+ if (fo)
+ fclose(fo), remove(tfile);
+ return ret;
}
diff --git a/x86_64-gen.c b/x86_64-gen.c
index 1fa8dd5..f85cd01 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
@@ -83,9 +83,6 @@ enum {
/* maximum alignment (for aligned attribute support) */
#define MAX_ALIGN 8
-ST_FUNC void gen_opl(int op);
-ST_FUNC void gen_le64(int64_t c);
-
/******************************************************/
/* ELF defines */
@@ -106,7 +103,7 @@ ST_FUNC void gen_le64(int64_t c);
#include "tcc.h"
#include <assert.h>
-ST_DATA const int reg_classes[] = {
+ST_DATA const int reg_classes[NB_REGS+7] = {
/* eax */ RC_INT | RC_RAX,
/* ecx */ RC_INT | RC_RCX,
/* edx */ RC_INT | RC_RDX,