mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-17 05:20:08 +08:00
So that the generated code, and more short
This commit is contained in:
commit
2a8905c93b
6
.gitignore
vendored
6
.gitignore
vendored
@ -36,10 +36,13 @@ p2.c
|
||||
tcctest[1234]
|
||||
test[1234].out
|
||||
tests/tcclib.h
|
||||
tests/tcctest.gcc
|
||||
tests/tcctest.cc
|
||||
tests/weaktest.*.o.txt
|
||||
tests/tests2/fred.txt
|
||||
tests/tests2/*.exe
|
||||
tests/hello
|
||||
tests/abitest-*cc
|
||||
tests/vla_test
|
||||
.gdb_history
|
||||
tcc.1
|
||||
tcc.pod
|
||||
@ -53,6 +56,7 @@ lib/x86_64
|
||||
lib/i386
|
||||
lib/x86_64-win32
|
||||
lib/i386-win32
|
||||
lib/arm
|
||||
tcc-doc.info
|
||||
conftest*
|
||||
tiny_libmaker
|
||||
|
@ -195,58 +195,53 @@ macro(make_tcc native_name cross_name cross_enabled definitions tcc_sources libt
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
make_tcc("Win32" i386-win32 TCC_BUILD_WIN32
|
||||
make_tcc("Win32" i386-w64-mingw32 TCC_BUILD_WIN32
|
||||
"TCC_TARGET_I386;TCC_TARGET_PE"
|
||||
"${I386_SOURCES};tccpe.c"
|
||||
tiny_libmaker_32 "${LIBTCC1_I386_SOURCES};${LIBTCC1_WIN_SOURCES}" "win32/include;win32/include/winapi"
|
||||
)
|
||||
make_tcc("Win64" x86_64-win32 TCC_BUILD_WIN64
|
||||
make_tcc("Win64" x86_64-w64-mingw32 TCC_BUILD_WIN64
|
||||
"TCC_TARGET_X86_64;TCC_TARGET_PE"
|
||||
"${X86_64_SOURCES};tccpe.c"
|
||||
tiny_libmaker_64 "lib/alloca86_64.S;${LIBTCC1_WIN_SOURCES}" "win32/include;win32/include/winapi"
|
||||
)
|
||||
make_tcc("WinCE" arm-win32 TCC_BUILD_WINCE
|
||||
make_tcc("WinCE" arm-wince-mingw32ce TCC_BUILD_WINCE
|
||||
"TCC_TARGET_ARM;TCC_ARM_VERSION=${TCC_ARM_VERSION};TCC_TARGET_PE"
|
||||
"${ARM_SOURCES};tccpe.c"
|
||||
"" "" ""
|
||||
)
|
||||
make_tcc("i386" i386 TCC_BUILD_I386
|
||||
make_tcc("i386" i386-linux-gnu TCC_BUILD_I386
|
||||
TCC_TARGET_I386
|
||||
"${I386_SOURCES}"
|
||||
tiny_libmaker_32 "${LIBTCC1_I386_SOURCES}" ""
|
||||
)
|
||||
make_tcc("x86_64" x86_64 TCC_BUILD_X64
|
||||
make_tcc("x86_64" x86_64-linux-gnu TCC_BUILD_X64
|
||||
TCC_TARGET_X86_64
|
||||
"${X86_64_SOURCES}"
|
||||
tiny_libmaker_64 "lib/alloca86_64.S" ""
|
||||
)
|
||||
set(ARM_DEFINITIONS TCC_TARGET_ARM TCC_ARM_VERSION=${TCC_ARM_VERSION})
|
||||
make_tcc("ARM" arm TCC_BUILD_ARM
|
||||
"${ARM_DEFINITIONS};WITHOUT_LIBTCC"
|
||||
"${ARM_SOURCES}"
|
||||
"" "" ""
|
||||
)
|
||||
make_tcc("" arm-eabihf TCC_BUILD_ARM_EABIHF
|
||||
make_tcc("" arm-linux-gnueabihf TCC_BUILD_ARM_EABIHF
|
||||
"${ARM_DEFINITIONS};TCC_ARM_EABI;TCC_ARM_HARDFLOAT"
|
||||
"${ARM_SOURCES}"
|
||||
"" "" ""
|
||||
)
|
||||
make_tcc("" arm-eabi TCC_BUILD_ARM_EABI
|
||||
make_tcc("" arm-linux-gnueabi TCC_BUILD_ARM_EABI
|
||||
"${ARM_DEFINITIONS};TCC_ARM_EABI"
|
||||
"${ARM_SOURCES}"
|
||||
"" "" ""
|
||||
)
|
||||
make_tcc("" arm-fpa TCC_BUILD_ARM_FPA
|
||||
make_tcc("" arm-linux-fpa TCC_BUILD_ARM_FPA
|
||||
"${ARM_DEFINITIONS}"
|
||||
"${ARM_SOURCES}"
|
||||
"" "" ""
|
||||
)
|
||||
make_tcc("" arm-fpa-ld TCC_BUILD_ARM_FPA_LD
|
||||
make_tcc("" arm-linux-fpa-ld TCC_BUILD_ARM_FPA_LD
|
||||
"${ARM_DEFINITIONS};LDOUBLE_SIZE=12"
|
||||
"${ARM_SOURCES}"
|
||||
"" "" ""
|
||||
)
|
||||
make_tcc("" arm-vfp TCC_BUILD_ARM_VFP
|
||||
make_tcc("" arm-linux-gnu TCC_BUILD_ARM_VFP
|
||||
"${ARM_DEFINITIONS};TCC_ARM_VFP"
|
||||
"${ARM_SOURCES}"
|
||||
"" "" ""
|
||||
|
121
Changelog
121
Changelog
@ -1,7 +1,126 @@
|
||||
Version 0.9.27:
|
||||
|
||||
Licensing:
|
||||
|
||||
- TinyCC partly relicensed to MIT license
|
||||
|
||||
User interface:
|
||||
|
||||
- define __STDC_HOSTED__ (Michael Matz, Urs Janssen)
|
||||
- added support for CPATH, C_INCLUDE_PATH and LD_LIBRARY_PATH (Andrew Aladjev
|
||||
and Urs Janssen)
|
||||
- added option -norunsrc to control argv[0] with tcc -run (James Lyon)
|
||||
- improve --with-libgcc configure help (grischka)
|
||||
- improve error message when memory is full (grischka)
|
||||
- improve wording about compiler switches in documentation (Thomas Preud'homme)
|
||||
- use GNU triplet prefix for cross compiler names (Thomas Preud'homme)
|
||||
- ignore unknown linker optimization and as-needed option (Austin English)
|
||||
|
||||
Features:
|
||||
|
||||
- added ABI tests with native compiler using libtcc (James Lyon)
|
||||
- added CMake build system with support for cross-compilation (James Lyon)
|
||||
- improved variable length array support (James Lyon)
|
||||
- add the possibility to use noname functions by ordinal (YX Hao)
|
||||
- add a install-strip target to install tcc (Thomas Preud'homme)
|
||||
- add runtime selection of float ABI on ARM (Thomas Preud'homme)
|
||||
- add shared lib support on x86-64 (Michael Matz)
|
||||
|
||||
Platforms:
|
||||
- Support Debian GNU/kfreeBSD 64bit userspace (Thomas Preud'homme)
|
||||
- support Debian GNU/kfreeBSD 64bit userspace (Thomas Preud'homme)
|
||||
- fix GNU/Hurd interpreter path (Thomas Preud'homme)
|
||||
- fix configure script for FreeBSD host (Thomas Preud'homme)
|
||||
- make tcc -run work reliably on ARM by flushing caches (Thomas Preud'homme)
|
||||
- many x86-64 ABI fixes incl. XMM register passing (James Lyon)
|
||||
- improve compatibility with mingw's long double (James Lyon)
|
||||
- avoid .stabstr section name to be truncated on win32 (Roy)
|
||||
- add support for load/store of _Bool value (Thomas Preud'homme)
|
||||
- detect instruction with incorrect operands on x86-64 (Thomas Preud'homme)
|
||||
- improved relocations on ARM (Thomas Preud'homme)
|
||||
- add va_* macro implementation for ARM (Thomas Preud'homme)
|
||||
- define __ARM_EABI__, __ARMEL__ and __ARM_PCS_VFP (Thomas Preud'homme)
|
||||
- provide a runtime library for ARM (Thomas Preud'homme)
|
||||
- vastly improved support for ARM hard float calling convention
|
||||
(Thomas Preud'homme, Daniel Glöckner)
|
||||
- tcc can uses libtcc1 on ARM (Thomas Preud'homme)
|
||||
- use __fixdfdi for all float to integer conversion (grischka)
|
||||
- simplify startup code for unix platforms (grischka)
|
||||
- improve ELF generated on ARM (Thomas Preud'homme)
|
||||
- add support for thumb to ARM relocation (Thomas Preud'homme)
|
||||
- fix globbing to match MSVC on Windows (Thomas Preud'homme)
|
||||
- deprecate FPA and OABI support for ARM (Thomas Preud'homme)
|
||||
- warn about softfloat not being supported on ARM (Thomas Preud'homme)
|
||||
|
||||
Bug fixes:
|
||||
- many code clean up (Urs Janssen, grischka)
|
||||
- fixes of other's patches (grischka, Ramsay Jones, Michael Matz)
|
||||
- fix documentation about __TINYC__ (Urs Janssen)
|
||||
- improve build of documentation (Urs Janssen)
|
||||
- improve build instructions (Jov)
|
||||
- switch from texi2html to makeinfo --html to build tcc-doc.html (James Lyon)
|
||||
- improve out of tree build (James Lyon)
|
||||
- improved passing and returning of struct (James Lyon)
|
||||
- fix CMake build on i386 and x86-64 (James Lyon)
|
||||
- fix i386 calling convention issue (James Lyon)
|
||||
- fix error in Windows build of tests (James Lyon)
|
||||
- fix x86-64 long double passing (James Lyon)
|
||||
- fix crash with undefined struct (grischka)
|
||||
- normalize slashes on win32 to always use backslashes (grischka)
|
||||
- use runtime function for float to int conversion on i386 (grischka)
|
||||
- improved documentation for include and lib lookup on win32 (grischka)
|
||||
- detect redefinition of function (Thomas Preud'homme)
|
||||
- detect the use of array of functions (Thomas Preud'homme)
|
||||
- detect use of enumerator with wrong enumeration (Thomas Preud'homme)
|
||||
- detect redefinition of enumerator or enumeration (Thomas Preud'homme)
|
||||
- set the user-defined library search paths first (Vittorio Giovara)
|
||||
- detect usage of incomplete types inside struct/union (Amine Najahi)
|
||||
- various macro bug fixes (Joseph Poirier)
|
||||
- avoid wrong trigger of assert on x86-64 platform (Thomas Preud'homme)
|
||||
- fix NaN comparison (Thomas Preud'homme)
|
||||
- use libtcc for static linking with runtime library (Thomas Preud'homme)
|
||||
- fix negation of 0.0 and -0.0 values (Thomas Preud'homme)
|
||||
- fix use of long long as if condition (Thomas Preud'homme)
|
||||
- disable bound check if libgcc is used (Thomas Preud'homme)
|
||||
- error out when casting to void (grischka)
|
||||
- remove circular dependency in Makefile (grischka)
|
||||
- stop preventing gcc to do strict aliasing (grischka)
|
||||
- fix Windows build of tcc (grischka)
|
||||
- build runtime library for arm cross compiler (Thomas Preud'homme)
|
||||
- fix installation of arm cross-compiler (Thomas Preud'homme)
|
||||
- add basic test for cross-compiler (Thomas Preud'homme)
|
||||
- fix failure when generating PE on x86-64 (Archidemon)
|
||||
- fix floating point unary minus and plus (Michael Matz)
|
||||
- add more tests for signed zero float (Michael Matz)
|
||||
- fix precision of double on x86-64 (Vincent Lefevre)
|
||||
- fix bound checking of argv with -run switch (Kirill Smelkov)
|
||||
- work around a wine cmd bug when building tcc on Windows (Austin English)
|
||||
- reenable some bound check tests (grischka)
|
||||
- boundtest.c lookup honors VPATH (grischka)
|
||||
- diff compared to CC in test[123]b? are now errors (grischka)
|
||||
- fix test3 on Windows (grischka)
|
||||
- prevent gcc from building (non functional) libtcc.a (grischka)
|
||||
- fix warning related to PE file generation on x86-64 (grischka)
|
||||
- stop mixing ordinary and implicit rule in Makefile (Iavael)
|
||||
- fix integer to double conversion on ARM (Thomas Preud'homme)
|
||||
- fix parameter passing of structure < 4 bytes on ARM (Thomas Preud'homme)
|
||||
- disable builtin_frame_address test on ARM due to gcc bug (Thomas Preud'homme)
|
||||
- fix initialization of struct on ARM (Thomas Preud'homme)
|
||||
- fix parameter passing of (unsigned) long long bitfield (Thomas Preud'homme)
|
||||
- improve float to integer tests (Thomas Preud'homme)
|
||||
- fix relocation of Thumb branch to ARM function (Thomas Preud'homme)
|
||||
- fix char wrong compatibility with [un]signed char (Thomas Preud'homme)
|
||||
- choose the code to compile based on target in libtcc1 (Thomas Preud'homme)
|
||||
- fix various clang warnings (Thomas Preud'homme)
|
||||
- don't hardcode tcc in Makefile for tests (Thomas Preud'homme)
|
||||
- fix relocation of __bound_init bound checking code (Thomas Preud'homme)
|
||||
- accept only one basic type for a given variable (Thomas Preud'homme)
|
||||
- fix error when using va_* with tcc using libgcc (Thomas Preud'homme)
|
||||
- support GOT32 and PLT32 reloc on the same symbol (Thomas Preud'homme)
|
||||
- fix memory leak due to symbol attributes (mingodad)
|
||||
- partially fix bound checking of argv and arge (Thomas Preud'homme)
|
||||
- fix possible dereference when getting name of symbol (grischka)
|
||||
- fix va_list type definition on x86-64 (Daniel Glöckner)
|
||||
- reduce number of scan-build false positive (mingodad)
|
||||
|
||||
version 0.9.26:
|
||||
|
||||
|
64
Makefile
64
Makefile
@ -66,7 +66,7 @@ NATIVE_DEFINES_$(CONFIG_i386) += -DTCC_TARGET_I386
|
||||
NATIVE_DEFINES_$(CONFIG_x86-64) += -DTCC_TARGET_X86_64
|
||||
NATIVE_DEFINES_$(CONFIG_WIN32) += -DTCC_TARGET_PE
|
||||
NATIVE_DEFINES_$(CONFIG_uClibc) += -DTCC_UCLIBC
|
||||
NATIVE_DEFINES_$(CONFIG_arm) += -DTCC_TARGET_ARM -DWITHOUT_LIBTCC
|
||||
NATIVE_DEFINES_$(CONFIG_arm) += -DTCC_TARGET_ARM
|
||||
NATIVE_DEFINES_$(CONFIG_arm_eabihf) += -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT
|
||||
NATIVE_DEFINES_$(CONFIG_arm_eabi) += -DTCC_ARM_EABI
|
||||
NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP
|
||||
@ -75,18 +75,30 @@ NATIVE_DEFINES += $(NATIVE_DEFINES_yes)
|
||||
ifeq ($(TOP),.)
|
||||
|
||||
PROGS=tcc$(EXESUF)
|
||||
I386_CROSS = i386-tcc$(EXESUF)
|
||||
WIN32_CROSS = i386-win32-tcc$(EXESUF)
|
||||
WIN64_CROSS = x86_64-win32-tcc$(EXESUF)
|
||||
WINCE_CROSS = arm-win32-tcc$(EXESUF)
|
||||
X64_CROSS = x86_64-tcc$(EXESUF)
|
||||
ARM_FPA_CROSS = arm-fpa-tcc$(EXESUF)
|
||||
ARM_FPA_LD_CROSS = arm-fpa-ld-tcc$(EXESUF)
|
||||
ARM_VFP_CROSS = arm-vfp-tcc$(EXESUF)
|
||||
ARM_EABI_CROSS = arm-eabi-tcc$(EXESUF)
|
||||
I386_CROSS = i386-linux-gnu-tcc$(EXESUF)
|
||||
WIN32_CROSS = i386-w64-mingw32-tcc$(EXESUF)
|
||||
WIN64_CROSS = x86_64-w64-mingw32-tcc$(EXESUF)
|
||||
WINCE_CROSS = arm-wince-mingw32ce-tcc$(EXESUF)
|
||||
X64_CROSS = x86_64-linux-gnu-tcc$(EXESUF)
|
||||
ARM_FPA_CROSS = arm-linux-fpa-tcc$(EXESUF)
|
||||
ARM_FPA_LD_CROSS = arm-linux-fpa-ld-tcc$(EXESUF)
|
||||
ARM_VFP_CROSS = arm-linux-gnu-tcc$(EXESUF)
|
||||
ARM_EABI_CROSS = arm-linux-gnueabi-tcc$(EXESUF)
|
||||
ARM_EABIHF_CROSS = arm-linux-gnueabihf-tcc$(EXESUF)
|
||||
ARM_CROSS = $(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CROSS)
|
||||
C67_CROSS = c67-tcc$(EXESUF)
|
||||
|
||||
# Legacy symlinks for cross compilers
|
||||
$(I386_CROSS)_LINK = i386-tcc$(EXESUF)
|
||||
$(WIN32_CROSS)_LINK = i386-win32-tcc$(EXESUF)
|
||||
$(WIN64_CROSS)_LINK = x86_64-win32-tcc$(EXESUF)
|
||||
$(WINCE_CROSS)_LINK = arm-win32-tcc$(EXESUF)
|
||||
$(X64_CROSS)_LINK = x86_64-tcc$(EXESUF)
|
||||
$(ARM_FPA_CROSS)_LINK = arm-fpa-tcc$(EXESUF)
|
||||
$(ARM_FPA_LD_CROSS)_LINK = arm-fpa-ld-tcc$(EXESUF)
|
||||
$(ARM_VFP_CROSS)_LINK = arm-vfp-tcc$(EXESUF)
|
||||
$(ARM_EABI_CROSS)_LINK = arm-eabi-tcc$(EXESUF)
|
||||
|
||||
CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
|
||||
CORE_FILES += tcc.h config.h libtcc.h tcctok.h
|
||||
I386_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h
|
||||
@ -122,16 +134,15 @@ LIBTCC1=libtcc1.a
|
||||
else ifeq ($(ARCH),arm)
|
||||
NATIVE_FILES=$(ARM_FILES)
|
||||
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(C67_CROSS)
|
||||
LIBTCC1=libtcc1.a
|
||||
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a lib/i386/libtcc1.a
|
||||
endif
|
||||
PROGS_CROSS_LINK=$(foreach PROG_CROSS,$(PROGS_CROSS),$($(PROG_CROSS)_LINK))
|
||||
|
||||
ifeq ($(TARGETOS),Darwin)
|
||||
PROGS+=tiny_libmaker$(EXESUF)
|
||||
endif
|
||||
|
||||
ifdef CONFIG_USE_LIBGCC
|
||||
LIBTCC1=
|
||||
endif
|
||||
|
||||
TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCC_EXTRA)
|
||||
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
|
||||
|
||||
@ -149,6 +160,7 @@ tcc$(EXESUF): tcc.o $(LIBTCC)
|
||||
# Cross Tiny C Compilers
|
||||
%-tcc$(EXESUF): tcc.c
|
||||
$(CC) -o $@ $< -DONE_SOURCE $(DEFINES) $(CPPFLAGS) $(CFLAGS) $(LIBS) $(LDFLAGS)
|
||||
$(if $($@_LINK),ln -sf $@ $($@_LINK))
|
||||
|
||||
# profiling version
|
||||
tcc_p$(EXESUF): $(NATIVE_FILES)
|
||||
@ -168,7 +180,7 @@ $(C67_CROSS): DEFINES = -DTCC_TARGET_C67
|
||||
$(ARM_FPA_CROSS): DEFINES = -DTCC_TARGET_ARM
|
||||
$(ARM_FPA_LD_CROSS)$(EXESUF): DEFINES = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12
|
||||
$(ARM_VFP_CROSS): DEFINES = -DTCC_TARGET_ARM -DTCC_ARM_VFP
|
||||
$(ARM_EABI_CROSS): DEFINES = -DTCC_TARGET_ARM -DTCC_ARM_EABI
|
||||
$(ARM_EABI_CROSS): DEFINES = -DTCC_TARGET_ARM -DTCC_ARM_EABI -DTCC_ARM_VFP
|
||||
|
||||
$(I386_CROSS): $(I386_FILES)
|
||||
$(X64_CROSS): $(X86_64_FILES)
|
||||
@ -229,18 +241,21 @@ else
|
||||
INSTALLBIN=$(INSTALL)
|
||||
endif
|
||||
|
||||
install-strip: install
|
||||
strip $(foreach PROG,$(PROGS),"$(bindir)"/$(PROG))
|
||||
|
||||
ifndef CONFIG_WIN32
|
||||
install: $(PROGS) $(TCCLIBS) $(TCCDOCS)
|
||||
mkdir -p "$(bindir)"
|
||||
ifeq ($(CC),tcc)
|
||||
$(INSTALL) -m755 $(PROGS) "$(bindir)"
|
||||
$(INSTALL) -m755 $(PROGS) $(PROGS_CROSS_LINK) "$(bindir)"
|
||||
else
|
||||
$(INSTALLBIN) -m755 $(PROGS) "$(bindir)"
|
||||
endif
|
||||
mkdir -p "$(mandir)/man1"
|
||||
-$(INSTALL) tcc.1 "$(mandir)/man1"
|
||||
-$(INSTALL) -m644 tcc.1 "$(mandir)/man1"
|
||||
mkdir -p "$(infodir)"
|
||||
-$(INSTALL) tcc-doc.info "$(infodir)"
|
||||
-$(INSTALL) -m644 tcc-doc.info "$(infodir)"
|
||||
mkdir -p "$(tccdir)"
|
||||
mkdir -p "$(tccdir)/include"
|
||||
ifneq ($(LIBTCC1),)
|
||||
@ -248,7 +263,7 @@ ifneq ($(LIBTCC1),)
|
||||
endif
|
||||
$(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) $(top_srcdir)/tcclib.h "$(tccdir)/include"
|
||||
mkdir -p "$(libdir)"
|
||||
$(INSTALL) -m755 $(LIBTCC) "$(libdir)"
|
||||
$(INSTALL) -m644 $(LIBTCC) "$(libdir)"
|
||||
ifdef DISABLE_STATIC
|
||||
ln -sf "$(ln_libdir)/libtcc.so.1.0" "$(libdir)/libtcc.so.1"
|
||||
ln -sf "$(ln_libdir)/libtcc.so.1.0" "$(libdir)/libtcc.so"
|
||||
@ -260,7 +275,7 @@ endif
|
||||
ifdef CONFIG_CROSS
|
||||
mkdir -p "$(tccdir)/win32/lib/32"
|
||||
mkdir -p "$(tccdir)/win32/lib/64"
|
||||
ifeq ($(ARCH),x86-64)
|
||||
ifneq ($(ARCH),i386)
|
||||
mkdir -p "$(tccdir)/i386"
|
||||
$(INSTALL) -m644 lib/i386/libtcc1.a "$(tccdir)/i386"
|
||||
cp -r "$(tccdir)/include" "$(tccdir)/i386"
|
||||
@ -269,7 +284,7 @@ endif
|
||||
$(INSTALL) -m644 lib/i386-win32/libtcc1.a "$(tccdir)/win32/lib/32"
|
||||
$(INSTALL) -m644 lib/x86_64-win32/libtcc1.a "$(tccdir)/win32/lib/64"
|
||||
cp -r $(top_srcdir)/win32/include/. "$(tccdir)/win32/include"
|
||||
cp -r $(top_srcdir)/include/. "$(tccdir)/win32/include"
|
||||
cp -r "$(tccdir)/include" "$(tccdir)/win32"
|
||||
endif
|
||||
|
||||
uninstall:
|
||||
@ -282,7 +297,7 @@ uninstall:
|
||||
rm -fv "$(libdir)/libtcc.so*"
|
||||
rm -rf "$(tccdir)/win32"
|
||||
-rmdir $(tccdir)/include
|
||||
ifeq ($(ARCH),x86-64)
|
||||
ifneq ($(ARCH),i386)
|
||||
rm -rf "$(tccdir)/i386"
|
||||
endif
|
||||
else
|
||||
@ -328,7 +343,7 @@ tcc-doc.info: tcc-doc.texi
|
||||
export LIBTCC1
|
||||
|
||||
%est:
|
||||
$(MAKE) -C tests $@
|
||||
$(MAKE) -C tests $@ 'PROGS_CROSS=$(PROGS_CROSS)'
|
||||
|
||||
clean:
|
||||
rm -vf $(PROGS) tcc_p$(EXESUF) tcc.pod *~ *.o *.a *.so* *.out *.exe libtcc_test$(EXESUF)
|
||||
@ -358,9 +373,6 @@ tar: tcc-doc.html
|
||||
rm -rf $(TCC-VERSION)
|
||||
git reset
|
||||
|
||||
Makefile: $(top_srcdir)/Makefile
|
||||
cp $< $@
|
||||
|
||||
.PHONY: all clean tar distclean install uninstall FORCE
|
||||
|
||||
endif # ifeq ($(TOP),.)
|
||||
|
@ -27,9 +27,10 @@
|
||||
|
||||
Author (name) I agree (YES/NO) Files/Features (optional)
|
||||
------------------------------------------------------------------------------
|
||||
Daniel Glöckner ? arm-gen.c
|
||||
Daniel Glöckner NO arm-gen.c
|
||||
Daniel Glöckner YES not arm-gen.c
|
||||
Fabrice Bellard YES original author
|
||||
Frédéric Feret ? x86 64/16 bit asm
|
||||
Frédéric Féret YES x86 64/16 bit asm
|
||||
grischka YES tccpe.c
|
||||
Shinichiro Hamaji YES x86_64-gen.c
|
||||
Thomas Preud'homme YES arm-gen.c
|
||||
|
47
c67-gen.c
47
c67-gen.c
@ -245,8 +245,8 @@ void gsym(int t)
|
||||
}
|
||||
|
||||
// these are regs that tcc doesn't really know about,
|
||||
// but asign them unique values so the mapping routines
|
||||
// can distinquish them
|
||||
// but assign them unique values so the mapping routines
|
||||
// can distinguish them
|
||||
|
||||
#define C67_A0 105
|
||||
#define C67_SP 106
|
||||
@ -1879,10 +1879,11 @@ static void gcall_or_jmp(int is_jmp)
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 1 if this function returns via an sret pointer, 0 otherwise */
|
||||
ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) {
|
||||
/* Return the number of registers needed to return the struct, or 0 if
|
||||
returning via struct pointer. */
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) {
|
||||
*ret_align = 1; // Never have to re-align return values for x86-64
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* generate function call with address in (vtop->t, vtop->c) and free function
|
||||
@ -1900,8 +1901,6 @@ void gfunc_call(int nb_args)
|
||||
for (i = 0; i < nb_args; i++) {
|
||||
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
ALWAYS_ASSERT(FALSE);
|
||||
} else if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
ALWAYS_ASSERT(FALSE);
|
||||
} else {
|
||||
/* simple type (currently always same size) */
|
||||
/* XXX: implicit cast ? */
|
||||
@ -1970,6 +1969,7 @@ void gfunc_prolog(CType * func_type)
|
||||
/* if the function returns a structure, then add an
|
||||
implicit pointer parameter */
|
||||
func_vt = sym->type;
|
||||
func_var = (sym->c == FUNC_ELLIPSIS);
|
||||
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
|
||||
func_vc = addr;
|
||||
addr += 4;
|
||||
@ -2102,7 +2102,7 @@ int gtst(int inv, int t)
|
||||
C67_NOP(5);
|
||||
t = ind1; //return where we need to patch
|
||||
|
||||
} else if (v == VT_JMP || v == VT_JMPI) {
|
||||
} else { /* VT_JMP || VT_JMPI */
|
||||
/* && or || optimization */
|
||||
if ((v & 1) == inv) {
|
||||
/* insert vtop->c jump list in t */
|
||||
@ -2128,37 +2128,6 @@ int gtst(int inv, int t)
|
||||
t = gjmp(t);
|
||||
gsym(vtop->c.i);
|
||||
}
|
||||
} else {
|
||||
if (is_float(vtop->type.t)) {
|
||||
vpushi(0);
|
||||
gen_op(TOK_NE);
|
||||
}
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
/* constant jmp optimization */
|
||||
if ((vtop->c.i != 0) != inv)
|
||||
t = gjmp(t);
|
||||
} else {
|
||||
// I think we need to get the value on the stack
|
||||
// into a register, test it, and generate a branch
|
||||
// return the address of the branch, so it can be
|
||||
// later patched
|
||||
|
||||
v = gv(RC_INT); // get value into a reg
|
||||
ind1 = ind;
|
||||
C67_MVKL(C67_A0, t); //r=reg to load, constant
|
||||
C67_MVKH(C67_A0, t); //r=reg to load, constant
|
||||
|
||||
if (v != TREG_EAX && // check if not already in a conditional test reg
|
||||
v != TREG_EDX && v != TREG_ST0 && v != C67_B2) {
|
||||
C67_MV(v, C67_B2);
|
||||
v = C67_B2;
|
||||
}
|
||||
|
||||
C67_IREG_B_REG(inv, v, C67_A0); // [!R] B.S2x A0
|
||||
C67_NOP(5);
|
||||
t = ind1; //return where we need to patch
|
||||
ind1 = ind;
|
||||
}
|
||||
}
|
||||
vtop--;
|
||||
return t;
|
||||
|
114
configure
vendored
114
configure
vendored
@ -56,6 +56,7 @@ case $targetos in
|
||||
DragonFly) noldl=yes;;
|
||||
OpenBSD) noldl=yes;;
|
||||
FreeBSD) noldl=yes;;
|
||||
NetBSD) noldl=yes;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
@ -70,46 +71,52 @@ if test -z "$source_path" -o "$source_path" = "." ; then
|
||||
source_path_used="no"
|
||||
fi
|
||||
|
||||
case "$cpu" in
|
||||
i386|i486|i586|i686|i86pc|BePC|i686-AT386)
|
||||
cpu="x86"
|
||||
;;
|
||||
x86_64|amd64)
|
||||
cpu="x86-64"
|
||||
;;
|
||||
arm*)
|
||||
case "$cpu" in
|
||||
arm|armv4l)
|
||||
cpuver=4
|
||||
;;
|
||||
armv5tel|armv5tejl)
|
||||
cpuver=5
|
||||
;;
|
||||
armv6j|armv6l)
|
||||
cpuver=6
|
||||
;;
|
||||
armv7a|armv7l)
|
||||
cpuver=7
|
||||
;;
|
||||
esac
|
||||
cpu="armv4l"
|
||||
;;
|
||||
alpha)
|
||||
cpu="alpha"
|
||||
;;
|
||||
"Power Macintosh"|ppc|ppc64)
|
||||
cpu="powerpc"
|
||||
;;
|
||||
mips)
|
||||
cpu="mips"
|
||||
;;
|
||||
s390)
|
||||
cpu="s390"
|
||||
;;
|
||||
*)
|
||||
cpu="unknown"
|
||||
;;
|
||||
esac
|
||||
classify_cpu ()
|
||||
{
|
||||
cpu="$1"
|
||||
|
||||
case "$cpu" in
|
||||
x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386)
|
||||
cpu="x86"
|
||||
;;
|
||||
x86_64|amd64)
|
||||
cpu="x86-64"
|
||||
;;
|
||||
arm*)
|
||||
case "$cpu" in
|
||||
arm|armv4l)
|
||||
cpuver=4
|
||||
;;
|
||||
armv5tel|armv5tejl)
|
||||
cpuver=5
|
||||
;;
|
||||
armv6j|armv6l)
|
||||
cpuver=6
|
||||
;;
|
||||
armv7a|armv7l)
|
||||
cpuver=7
|
||||
;;
|
||||
esac
|
||||
cpu="armv4l"
|
||||
;;
|
||||
alpha)
|
||||
cpu="alpha"
|
||||
;;
|
||||
"Power Macintosh"|ppc|ppc64)
|
||||
cpu="powerpc"
|
||||
;;
|
||||
mips)
|
||||
cpu="mips"
|
||||
;;
|
||||
s390)
|
||||
cpu="s390"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported CPU: $cpu"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
for opt do
|
||||
eval opt=\"$opt\"
|
||||
@ -140,14 +147,6 @@ for opt do
|
||||
;;
|
||||
--cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--cc=*) cc=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
|
||||
;;
|
||||
--extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
|
||||
;;
|
||||
--extra-libs=*) extralibs=${opt#--extra-libs=}
|
||||
;;
|
||||
--sysincludepaths=*) tcc_sysincludepaths=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--libpaths=*) tcc_libpaths=`echo $opt | cut -d '=' -f 2`
|
||||
@ -156,7 +155,15 @@ for opt do
|
||||
;;
|
||||
--elfinterp=*) tcc_elfinterp=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
|
||||
--cc=*) cc=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
|
||||
;;
|
||||
--extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
|
||||
;;
|
||||
--extra-libs=*) extralibs=${opt#--extra-libs=}
|
||||
;;
|
||||
--cpu=*) build_cpu=`echo $opt | cut -d '=' -f 2`
|
||||
;;
|
||||
--enable-gprof) gprof="yes"
|
||||
;;
|
||||
@ -185,6 +192,8 @@ for opt do
|
||||
esac
|
||||
done
|
||||
|
||||
classify_cpu "$cpu"
|
||||
|
||||
# Checking for CFLAGS
|
||||
if test -z "$CFLAGS"; then
|
||||
CFLAGS="-Wall -g -O2"
|
||||
@ -270,10 +279,11 @@ Advanced options (experts only):
|
||||
--cc=CC use C compiler CC [$cc]
|
||||
--extra-cflags= specify compiler flags [$CFLAGS]
|
||||
--extra-ldflags= specify linker options []
|
||||
--cpu=CPU CPU [$cpu]
|
||||
--strip-binaries strip symbol tables from resulting binaries
|
||||
--disable-static make libtcc.so instead of libtcc.a
|
||||
--disable-rpath disable use of -rpath with the above
|
||||
--with-libgcc use /lib/libgcc_s.so.1 instead of libtcc.a
|
||||
--with-libgcc use libgcc_s.so.1 instead of libtcc1.a in dynamic link
|
||||
--enable-mingw32 build windows version on linux with mingw32
|
||||
--enable-cygwin build windows version on windows with cygwin
|
||||
--enable-cross build cross compilers
|
||||
@ -304,7 +314,7 @@ if test -z "$cross_prefix" ; then
|
||||
if test "$mingw32" = "no" ; then
|
||||
triplet="$($CONFTEST triplet)"
|
||||
if test -f "/usr/lib/$triplet/crti.o" ; then
|
||||
tcc_lddir="lib/$triplet"
|
||||
tcc_lddir="lib"
|
||||
multiarch_triplet="$triplet"
|
||||
elif test -f "/usr/lib64/crti.o" ; then
|
||||
tcc_lddir="lib64"
|
||||
@ -355,8 +365,8 @@ Doc directory $docdir
|
||||
Target root prefix $sysroot
|
||||
Source path $source_path
|
||||
C compiler $cc
|
||||
Build CPU $cpu
|
||||
Target OS $targetos
|
||||
CPU $cpu
|
||||
Big Endian $bigendian
|
||||
gprof enabled $gprof
|
||||
cross compilers $build_cross
|
||||
|
@ -37,6 +37,10 @@
|
||||
# define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
int _CRT_glob = 0;
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
switch(argc == 2 ? argv[1][0] : 0) {
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#define TOK_ASM_first TOK_ASM_clc
|
||||
#define TOK_ASM_last TOK_ASM_emms
|
||||
#define TOK_ASM_alllast TOK_ASM_pxor
|
||||
|
||||
#define OPC_JMP 0x01 /* jmp operand */
|
||||
#define OPC_B 0x02 /* only used with OPC_WL */
|
||||
@ -715,6 +716,9 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
|
||||
g(b >> 8);
|
||||
g(b);
|
||||
return;
|
||||
} else if (opcode <= TOK_ASM_alllast) {
|
||||
tcc_error("bad operand with opcode '%s'",
|
||||
get_tok_str(opcode, NULL));
|
||||
} else {
|
||||
tcc_error("unknown opcode '%s'",
|
||||
get_tok_str(opcode, NULL));
|
||||
@ -1378,7 +1382,7 @@ ST_FUNC void subst_asm_operand(CString *add_str,
|
||||
}
|
||||
}
|
||||
|
||||
/* generate prolog and epilog code for asm statment */
|
||||
/* generate prolog and epilog code for asm statement */
|
||||
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
|
||||
int nb_outputs, int is_output,
|
||||
uint8_t *clobber_regs,
|
||||
|
@ -463,7 +463,7 @@ ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
|
||||
DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
|
||||
DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
|
||||
DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
|
||||
DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
|
||||
DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) /* must be last !OP0 */
|
||||
|
||||
#undef ALT
|
||||
#undef DEF_ASM_OP0
|
||||
|
133
i386-gen.c
133
i386-gen.c
@ -338,6 +338,15 @@ static void gadd_sp(int val)
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_static_call(int v)
|
||||
{
|
||||
Sym *sym;
|
||||
|
||||
sym = external_global_sym(v, &func_old_type, 0);
|
||||
oad(0xe8, -4);
|
||||
greloc(cur_text_section, sym, ind-4, R_386_PC32);
|
||||
}
|
||||
|
||||
/* 'is_jmp' is '1' if it is a jump */
|
||||
static void gcall_or_jmp(int is_jmp)
|
||||
{
|
||||
@ -365,8 +374,9 @@ static void gcall_or_jmp(int is_jmp)
|
||||
static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX };
|
||||
static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX };
|
||||
|
||||
/* Return 1 if this function returns via an sret pointer, 0 otherwise */
|
||||
ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align)
|
||||
/* Return the number of registers needed to return the struct, or 0 if
|
||||
returning via struct pointer. */
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align)
|
||||
{
|
||||
#ifdef TCC_TARGET_PE
|
||||
int size, align;
|
||||
@ -374,19 +384,19 @@ ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align)
|
||||
*ret_align = 1; // Never have to re-align return values for x86
|
||||
size = type_size(vt, &align);
|
||||
if (size > 8) {
|
||||
return 1;
|
||||
return 0;
|
||||
} else if (size > 4) {
|
||||
ret->ref = NULL;
|
||||
ret->t = VT_LLONG;
|
||||
return 0;
|
||||
return 1;
|
||||
} else {
|
||||
ret->ref = NULL;
|
||||
ret->t = VT_INT;
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
*ret_align = 1; // Never have to re-align return values for x86
|
||||
return 1;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -447,7 +457,7 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
}
|
||||
save_regs(0); /* save used temporary registers */
|
||||
func_sym = vtop->type.ref;
|
||||
func_call = FUNC_CALL(func_sym->r);
|
||||
func_call = func_sym->a.func_call;
|
||||
/* fast call case */
|
||||
if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) ||
|
||||
func_call == FUNC_FASTCALLW) {
|
||||
@ -495,7 +505,7 @@ ST_FUNC void gfunc_prolog(CType *func_type)
|
||||
CType *type;
|
||||
|
||||
sym = func_type->ref;
|
||||
func_call = FUNC_CALL(sym->r);
|
||||
func_call = sym->a.func_call;
|
||||
addr = 8;
|
||||
loc = 0;
|
||||
func_vc = 0;
|
||||
@ -517,6 +527,7 @@ ST_FUNC void gfunc_prolog(CType *func_type)
|
||||
/* if the function returns a structure, then add an
|
||||
implicit pointer parameter */
|
||||
func_vt = sym->type;
|
||||
func_var = (sym->c == FUNC_ELLIPSIS);
|
||||
#ifdef TCC_TARGET_PE
|
||||
size = type_size(&func_vt,&align);
|
||||
if (((func_vt.t & VT_BTYPE) == VT_STRUCT) && (size > 8)) {
|
||||
@ -582,7 +593,7 @@ ST_FUNC void gfunc_epilog(void)
|
||||
&& func_bound_offset != lbounds_section->data_offset) {
|
||||
int saved_ind;
|
||||
int *bounds_ptr;
|
||||
Sym *sym, *sym_data;
|
||||
Sym *sym_data;
|
||||
/* add end of table info */
|
||||
bounds_ptr = section_ptr_add(lbounds_section, sizeof(int));
|
||||
*bounds_ptr = 0;
|
||||
@ -594,20 +605,16 @@ ST_FUNC void gfunc_epilog(void)
|
||||
greloc(cur_text_section, sym_data,
|
||||
ind + 1, R_386_32);
|
||||
oad(0xb8, 0); /* mov %eax, xxx */
|
||||
sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0);
|
||||
greloc(cur_text_section, sym,
|
||||
ind + 1, R_386_PC32);
|
||||
oad(0xe8, -4);
|
||||
gen_static_call(TOK___bound_local_new);
|
||||
|
||||
ind = saved_ind;
|
||||
/* generate bound check local freeing */
|
||||
o(0x5250); /* save returned value, if any */
|
||||
greloc(cur_text_section, sym_data,
|
||||
ind + 1, R_386_32);
|
||||
oad(0xb8, 0); /* mov %eax, xxx */
|
||||
sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0);
|
||||
greloc(cur_text_section, sym,
|
||||
ind + 1, R_386_PC32);
|
||||
oad(0xe8, -4);
|
||||
gen_static_call(TOK___bound_local_delete);
|
||||
|
||||
o(0x585a); /* restore returned value, if any */
|
||||
}
|
||||
#endif
|
||||
@ -626,10 +633,8 @@ ST_FUNC void gfunc_epilog(void)
|
||||
ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (v >= 4096) {
|
||||
Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
|
||||
oad(0xb8, v); /* mov stacksize, %eax */
|
||||
oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
|
||||
greloc(cur_text_section, sym, ind-4, R_386_PC32);
|
||||
gen_static_call(TOK___chkstk); /* call __chkstk, (does the stackframe too) */
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@ -672,7 +677,7 @@ ST_FUNC int gtst(int inv, int t)
|
||||
/* fast case : can jump directly since flags are set */
|
||||
g(0x0f);
|
||||
t = psym((vtop->c.i - 16) ^ inv, t);
|
||||
} else if (v == VT_JMP || v == VT_JMPI) {
|
||||
} else { /* VT_JMP || VT_JMPI */
|
||||
/* && or || optimization */
|
||||
if ((v & 1) == inv) {
|
||||
/* insert vtop->c jump list in t */
|
||||
@ -685,23 +690,6 @@ ST_FUNC int gtst(int inv, int t)
|
||||
t = gjmp(t);
|
||||
gsym(vtop->c.i);
|
||||
}
|
||||
} else {
|
||||
if (is_float(vtop->type.t) ||
|
||||
(vtop->type.t & VT_BTYPE) == VT_LLONG) {
|
||||
vpushi(0);
|
||||
gen_op(TOK_NE);
|
||||
}
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
/* constant jmp optimization */
|
||||
if ((vtop->c.i != 0) != inv)
|
||||
t = gjmp(t);
|
||||
} else {
|
||||
v = gv(RC_INT);
|
||||
o(0x85);
|
||||
o(0xc0 + v * 9);
|
||||
g(0x0f);
|
||||
t = psym(0x85 ^ inv, t);
|
||||
}
|
||||
}
|
||||
vtop--;
|
||||
return t;
|
||||
@ -885,7 +873,10 @@ ST_FUNC void gen_opf(int op)
|
||||
swapped = 0;
|
||||
if (swapped)
|
||||
o(0xc9d9); /* fxch %st(1) */
|
||||
o(0xe9da); /* fucompp */
|
||||
if (op == TOK_EQ || op == TOK_NE)
|
||||
o(0xe9da); /* fucompp */
|
||||
else
|
||||
o(0xd9de); /* fcompp */
|
||||
o(0xe0df); /* fnstsw %ax */
|
||||
if (op == TOK_EQ) {
|
||||
o(0x45e480); /* and $0x45, %ah */
|
||||
@ -989,55 +980,20 @@ ST_FUNC void gen_cvt_itof(int t)
|
||||
}
|
||||
|
||||
/* convert fp to int 't' type */
|
||||
/* XXX: handle long long case */
|
||||
ST_FUNC void gen_cvt_ftoi(int t)
|
||||
{
|
||||
int r, r2, size;
|
||||
Sym *sym;
|
||||
CType ushort_type;
|
||||
|
||||
ushort_type.t = VT_SHORT | VT_UNSIGNED;
|
||||
ushort_type.ref = 0;
|
||||
|
||||
gv(RC_FLOAT);
|
||||
if (t != VT_INT)
|
||||
size = 8;
|
||||
else
|
||||
size = 4;
|
||||
|
||||
o(0x2dd9); /* ldcw xxx */
|
||||
sym = external_global_sym(TOK___tcc_int_fpu_control,
|
||||
&ushort_type, VT_LVAL);
|
||||
greloc(cur_text_section, sym,
|
||||
ind, R_386_32);
|
||||
gen_le32(0);
|
||||
|
||||
oad(0xec81, size); /* sub $xxx, %esp */
|
||||
if (size == 4)
|
||||
o(0x1cdb); /* fistpl */
|
||||
int bt = vtop->type.t & VT_BTYPE;
|
||||
if (bt == VT_FLOAT)
|
||||
vpush_global_sym(&func_old_type, TOK___fixsfdi);
|
||||
else if (bt == VT_LDOUBLE)
|
||||
vpush_global_sym(&func_old_type, TOK___fixxfdi);
|
||||
else
|
||||
o(0x3cdf); /* fistpll */
|
||||
o(0x24);
|
||||
o(0x2dd9); /* ldcw xxx */
|
||||
sym = external_global_sym(TOK___tcc_fpu_control,
|
||||
&ushort_type, VT_LVAL);
|
||||
greloc(cur_text_section, sym,
|
||||
ind, R_386_32);
|
||||
gen_le32(0);
|
||||
|
||||
r = get_reg(RC_INT);
|
||||
o(0x58 + r); /* pop r */
|
||||
if (size == 8) {
|
||||
if (t == VT_LLONG) {
|
||||
vtop->r = r; /* mark reg as used */
|
||||
r2 = get_reg(RC_INT);
|
||||
o(0x58 + r2); /* pop r2 */
|
||||
vtop->r2 = r2;
|
||||
} else {
|
||||
o(0x04c483); /* add $4, %esp */
|
||||
}
|
||||
}
|
||||
vtop->r = r;
|
||||
vpush_global_sym(&func_old_type, TOK___fixdfdi);
|
||||
vswap();
|
||||
gfunc_call(1);
|
||||
vpushi(0);
|
||||
vtop->r = REG_IRET;
|
||||
vtop->r2 = REG_LRET;
|
||||
}
|
||||
|
||||
/* convert from one floating point type to another */
|
||||
@ -1060,18 +1016,13 @@ ST_FUNC void ggoto(void)
|
||||
/* generate a bounded pointer addition */
|
||||
ST_FUNC void gen_bounded_ptr_add(void)
|
||||
{
|
||||
Sym *sym;
|
||||
|
||||
/* prepare fast i386 function call (args in eax and edx) */
|
||||
gv2(RC_EAX, RC_EDX);
|
||||
/* save all temporary registers */
|
||||
vtop -= 2;
|
||||
save_regs(0);
|
||||
/* do a fast function call */
|
||||
sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0);
|
||||
greloc(cur_text_section, sym,
|
||||
ind + 1, R_386_PC32);
|
||||
oad(0xe8, -4);
|
||||
gen_static_call(TOK___bound_ptr_add);
|
||||
/* returned pointer is in eax */
|
||||
vtop++;
|
||||
vtop->r = TREG_EAX | VT_BOUNDED;
|
||||
|
@ -191,7 +191,7 @@
|
||||
DEF_FP(mul)
|
||||
|
||||
DEF_ASM(fcom)
|
||||
DEF_ASM(fcom_1) /* non existant op, just to have a regular table */
|
||||
DEF_ASM(fcom_1) /* non existent op, just to have a regular table */
|
||||
DEF_FP1(com)
|
||||
|
||||
DEF_FP(comp)
|
||||
|
16
il-gen.c
16
il-gen.c
@ -441,6 +441,7 @@ void gfunc_prolog(int t)
|
||||
/* if the function returns a structure, then add an
|
||||
implicit pointer parameter */
|
||||
func_vt = sym->t;
|
||||
func_var = (sym->c == FUNC_ELLIPSIS);
|
||||
if ((func_vt & VT_BTYPE) == VT_STRUCT) {
|
||||
func_vc = addr;
|
||||
addr++;
|
||||
@ -515,7 +516,7 @@ int gtst(int inv, int t)
|
||||
break;
|
||||
}
|
||||
t = out_opj(c, t);
|
||||
} else if (v == VT_JMP || v == VT_JMPI) {
|
||||
} else { /* VT_JMP || VT_JMPI */
|
||||
/* && or || optimization */
|
||||
if ((v & 1) == inv) {
|
||||
/* insert vtop->c jump list in t */
|
||||
@ -528,19 +529,6 @@ int gtst(int inv, int t)
|
||||
t = gjmp(t);
|
||||
gsym(vtop->c.i);
|
||||
}
|
||||
} else {
|
||||
if (is_float(vtop->t)) {
|
||||
vpushi(0);
|
||||
gen_op(TOK_NE);
|
||||
}
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {
|
||||
/* constant jmp optimization */
|
||||
if ((vtop->c.i != 0) != inv)
|
||||
t = gjmp(t);
|
||||
} else {
|
||||
v = gv(RC_INT);
|
||||
t = out_opj(IL_OP_BRTRUE - inv, t);
|
||||
}
|
||||
}
|
||||
vtop--;
|
||||
return t;
|
||||
|
@ -27,7 +27,7 @@
|
||||
#define DBL_MAX_10_EXP 308
|
||||
|
||||
/* horrible intel long double */
|
||||
#ifdef __i386__
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
|
||||
#define LDBL_MANT_DIG 64
|
||||
#define LDBL_DIG 18
|
||||
|
@ -4,18 +4,28 @@
|
||||
#ifdef __x86_64__
|
||||
#ifndef _WIN64
|
||||
|
||||
typedef void *va_list;
|
||||
//This should be in sync with the declaration on our lib/libtcc1.c
|
||||
/* GCC compatible definition of va_list. */
|
||||
typedef struct {
|
||||
unsigned int gp_offset;
|
||||
unsigned int fp_offset;
|
||||
union {
|
||||
unsigned int overflow_offset;
|
||||
char *overflow_arg_area;
|
||||
};
|
||||
char *reg_save_area;
|
||||
} __va_list_struct;
|
||||
|
||||
va_list __va_start(void *fp);
|
||||
void *__va_arg(va_list ap, int arg_type, int size, int align);
|
||||
va_list __va_copy(va_list src);
|
||||
void __va_end(va_list ap);
|
||||
typedef __va_list_struct va_list[1];
|
||||
|
||||
#define va_start(ap, last) ((ap) = __va_start(__builtin_frame_address(0)))
|
||||
void __va_start(__va_list_struct *ap, void *fp);
|
||||
void *__va_arg(__va_list_struct *ap, int arg_type, int size, int align);
|
||||
|
||||
#define va_start(ap, last) __va_start(ap, __builtin_frame_address(0))
|
||||
#define va_arg(ap, type) \
|
||||
(*(type *)(__va_arg(ap, __builtin_va_arg_types(type), sizeof(type), __alignof__(type))))
|
||||
#define va_copy(dest, src) ((dest) = __va_copy(src))
|
||||
#define va_end(ap) __va_end(ap)
|
||||
#define va_copy(dest, src) (*(dest) = *(src))
|
||||
#define va_end(ap)
|
||||
|
||||
#else /* _WIN64 */
|
||||
typedef char *va_list;
|
||||
@ -25,6 +35,17 @@ typedef char *va_list;
|
||||
#define va_end(ap)
|
||||
#endif
|
||||
|
||||
#elif __arm__
|
||||
typedef char *va_list;
|
||||
#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
|
||||
#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
|
||||
& ~(_tcc_alignof(type) - 1))
|
||||
#define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)
|
||||
#define va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
|
||||
&~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
|
||||
#define va_copy(dest, src) (dest) = (src)
|
||||
#define va_end(ap)
|
||||
|
||||
#else /* __i386__ */
|
||||
typedef char *va_list;
|
||||
/* only correct for i386 */
|
||||
|
@ -6,5 +6,6 @@
|
||||
#define bool _Bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define __bool_true_false_are_defined 1
|
||||
|
||||
#endif /* _STDBOOL_H */
|
||||
|
@ -26,3 +26,18 @@ typedef unsigned long long int uint64_t;
|
||||
void *alloca(size_t size);
|
||||
|
||||
#endif
|
||||
|
||||
/* Older glibc require a wint_t from <stddef.h> (when requested
|
||||
by __need_wint_t, as otherwise stddef.h isn't allowed to
|
||||
define this type). Note that this must be outside the normal
|
||||
_STDDEF_H guard, so that it works even when we've included the file
|
||||
already (without requiring wint_t). Some other libs define _WINT_T
|
||||
if they've already provided that type, so we can use that as guard.
|
||||
TCC defines __WINT_TYPE__ for us. */
|
||||
#if defined (__need_wint_t)
|
||||
#ifndef _WINT_T
|
||||
#define _WINT_T
|
||||
typedef __WINT_TYPE__ wint_t;
|
||||
#endif
|
||||
#undef __need_wint_t
|
||||
#endif
|
||||
|
25
lib/Makefile
25
lib/Makefile
@ -6,7 +6,7 @@ TOP = ..
|
||||
include $(TOP)/Makefile
|
||||
VPATH = $(top_srcdir)/lib $(top_srcdir)/win32/lib
|
||||
|
||||
ifndef TARGET
|
||||
ifndef TARGET # native library
|
||||
ifdef CONFIG_WIN64
|
||||
TARGET = x86_64-win32
|
||||
else
|
||||
@ -24,6 +24,11 @@ ifndef TARGET
|
||||
ifneq ($(TARGETOS),Darwin)
|
||||
XCC = $(CC)
|
||||
endif
|
||||
else
|
||||
ifeq ($(ARCH),arm)
|
||||
TARGET = arm
|
||||
XCC = $(CC)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@ -41,20 +46,27 @@ cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF)
|
||||
|
||||
I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O)
|
||||
X86_64_O = libtcc1.o alloca86_64.o
|
||||
ARM_O = libtcc1.o armeabi.o alloca-arm.o
|
||||
WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
|
||||
WIN64_O = $(X86_64_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
|
||||
|
||||
# build TCC runtime library to contain PIC code, so it can be linked
|
||||
# into shared libraries
|
||||
PICFLAGS = -fPIC
|
||||
|
||||
ifeq "$(TARGET)" "i386-win32"
|
||||
OBJ = $(addprefix $(DIR)/,$(WIN32_O))
|
||||
TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE
|
||||
XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include
|
||||
XAR = $(DIR)/tiny_libmaker$(EXESUF)
|
||||
PICFLAGS =
|
||||
else
|
||||
ifeq "$(TARGET)" "x86_64-win32"
|
||||
OBJ = $(addprefix $(DIR)/,$(WIN64_O))
|
||||
TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE
|
||||
XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include
|
||||
XAR = $(DIR)/tiny_libmaker$(EXESUF)
|
||||
PICFLAGS =
|
||||
else
|
||||
ifeq "$(TARGET)" "i386"
|
||||
OBJ = $(addprefix $(DIR)/,$(I386_O))
|
||||
@ -65,14 +77,20 @@ ifeq "$(TARGET)" "x86_64"
|
||||
OBJ = $(addprefix $(DIR)/,$(X86_64_O))
|
||||
TGT = -DTCC_TARGET_X86_64
|
||||
XCC ?= $(TCC) -B$(TOP)
|
||||
else
|
||||
ifeq "$(TARGET)" "arm"
|
||||
OBJ = $(addprefix $(DIR)/,$(ARM_O))
|
||||
TGT = -DTCC_TARGET_ARM
|
||||
XCC ?= $(TCC) -B$(TOP)
|
||||
else
|
||||
$(error libtcc1.a not supported on target '$(TARGET)')
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
XFLAGS = $(CPPFLAGS) $(CFLAGS) $(TGT)
|
||||
XFLAGS = $(CPPFLAGS) $(CFLAGS) $(PICFLAGS) $(TGT)
|
||||
|
||||
ifeq ($(TARGETOS),Darwin)
|
||||
XAR = $(DIR)/tiny_libmaker$(EXESUF)
|
||||
@ -100,6 +118,3 @@ $(DIR)/exists :
|
||||
|
||||
clean :
|
||||
rm -rfv i386-win32 x86_64-win32 i386 x86_64
|
||||
|
||||
Makefile: $(top_srcdir)/lib/Makefile
|
||||
cp $< $@
|
||||
|
11
lib/alloca-arm.S
Normal file
11
lib/alloca-arm.S
Normal file
@ -0,0 +1,11 @@
|
||||
.text
|
||||
.align 2
|
||||
.global alloca
|
||||
.type alloca, %function
|
||||
alloca:
|
||||
rsb sp, r0, sp
|
||||
bic sp, sp, #7
|
||||
mov r0, sp
|
||||
mov pc, lr
|
||||
.size alloca, .-alloca
|
||||
.section .note.GNU-stack,"",%progbits
|
468
lib/armeabi.c
Normal file
468
lib/armeabi.c
Normal file
@ -0,0 +1,468 @@
|
||||
#include <limits.h>
|
||||
|
||||
/* We rely on the little endianness and EABI calling convention for this to
|
||||
work */
|
||||
|
||||
typedef struct double_unsigned_struct {
|
||||
unsigned low;
|
||||
unsigned high;
|
||||
} double_unsigned_struct;
|
||||
|
||||
typedef struct unsigned_int_struct {
|
||||
unsigned low;
|
||||
int high;
|
||||
} unsigned_int_struct;
|
||||
|
||||
#define REGS_RETURN(name, type) \
|
||||
void name ## _return(type ret) {}
|
||||
|
||||
|
||||
/* Float helper functions */
|
||||
|
||||
#define FLOAT_EXP_BITS 8
|
||||
#define FLOAT_FRAC_BITS 23
|
||||
|
||||
#define DOUBLE_EXP_BITS 11
|
||||
#define DOUBLE_FRAC_BITS 52
|
||||
|
||||
#define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1)
|
||||
|
||||
REGS_RETURN(unsigned_int_struct, unsigned_int_struct)
|
||||
REGS_RETURN(double_unsigned_struct, double_unsigned_struct)
|
||||
|
||||
/* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */
|
||||
|
||||
|
||||
/* float to [unsigned] long long conversion */
|
||||
#define DEFINE__AEABI_F2XLZ(name, with_sign) \
|
||||
void __aeabi_ ## name(unsigned val) \
|
||||
{ \
|
||||
int exp, high_shift, sign; \
|
||||
double_unsigned_struct ret; \
|
||||
\
|
||||
/* compute sign */ \
|
||||
sign = val >> 31; \
|
||||
\
|
||||
/* compute real exponent */ \
|
||||
exp = val >> FLOAT_FRAC_BITS; \
|
||||
exp &= (1 << FLOAT_EXP_BITS) - 1; \
|
||||
exp -= ONE_EXP(FLOAT); \
|
||||
\
|
||||
/* undefined behavior if truncated value cannot be represented */ \
|
||||
if (with_sign) { \
|
||||
if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
|
||||
return; \
|
||||
} else { \
|
||||
if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
val &= (1 << FLOAT_FRAC_BITS) - 1; \
|
||||
if (exp >= 32) { \
|
||||
ret.high = 1 << (exp - 32); \
|
||||
if (exp - 32 >= FLOAT_FRAC_BITS) { \
|
||||
ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \
|
||||
ret.low = 0; \
|
||||
} else { \
|
||||
high_shift = FLOAT_FRAC_BITS - (exp - 32); \
|
||||
ret.high |= val >> high_shift; \
|
||||
ret.low = val << (32 - high_shift); \
|
||||
} \
|
||||
} else { \
|
||||
ret.high = 0; \
|
||||
ret.low = 1 << exp; \
|
||||
if (exp > FLOAT_FRAC_BITS) \
|
||||
ret.low |= val << (exp - FLOAT_FRAC_BITS); \
|
||||
else \
|
||||
ret.low |= val >> (FLOAT_FRAC_BITS - exp); \
|
||||
} \
|
||||
\
|
||||
/* encode negative integer using 2's complement */ \
|
||||
if (with_sign && sign) { \
|
||||
ret.low = ~ret.low; \
|
||||
ret.high = ~ret.high; \
|
||||
if (ret.low == UINT_MAX) { \
|
||||
ret.low = 0; \
|
||||
ret.high++; \
|
||||
} else \
|
||||
ret.low++; \
|
||||
} \
|
||||
\
|
||||
double_unsigned_struct_return(ret); \
|
||||
}
|
||||
|
||||
/* float to unsigned long long conversion */
|
||||
DEFINE__AEABI_F2XLZ(f2ulz, 0)
|
||||
|
||||
/* float to long long conversion */
|
||||
DEFINE__AEABI_F2XLZ(f2lz, 1)
|
||||
|
||||
/* double to [unsigned] long long conversion */
|
||||
#define DEFINE__AEABI_D2XLZ(name, with_sign) \
|
||||
void __aeabi_ ## name(double_unsigned_struct val) \
|
||||
{ \
|
||||
int exp, high_shift, sign; \
|
||||
double_unsigned_struct ret; \
|
||||
\
|
||||
/* compute sign */ \
|
||||
sign = val.high >> 31; \
|
||||
\
|
||||
/* compute real exponent */ \
|
||||
exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \
|
||||
exp &= (1 << DOUBLE_EXP_BITS) - 1; \
|
||||
exp -= ONE_EXP(DOUBLE); \
|
||||
\
|
||||
/* undefined behavior if truncated value cannot be represented */ \
|
||||
if (with_sign) { \
|
||||
if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
|
||||
return; \
|
||||
} else { \
|
||||
if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
|
||||
if (exp >= 32) { \
|
||||
ret.high = 1 << (exp - 32); \
|
||||
if (exp >= DOUBLE_FRAC_BITS) { \
|
||||
high_shift = exp - DOUBLE_FRAC_BITS; \
|
||||
ret.high |= val.high << high_shift; \
|
||||
ret.high |= val.low >> (32 - high_shift); \
|
||||
ret.low = val.low << high_shift; \
|
||||
} else { \
|
||||
high_shift = DOUBLE_FRAC_BITS - exp; \
|
||||
ret.high |= val.high >> high_shift; \
|
||||
ret.low = val.high << (32 - high_shift); \
|
||||
ret.low |= val.low >> high_shift; \
|
||||
} \
|
||||
} else { \
|
||||
ret.high = 0; \
|
||||
ret.low = 1 << exp; \
|
||||
if (exp > DOUBLE_FRAC_BITS - 32) { \
|
||||
high_shift = exp - DOUBLE_FRAC_BITS - 32; \
|
||||
ret.low |= val.high << high_shift; \
|
||||
ret.low |= val.low >> (32 - high_shift); \
|
||||
} else \
|
||||
ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \
|
||||
} \
|
||||
\
|
||||
/* encode negative integer using 2's complement */ \
|
||||
if (with_sign && sign) { \
|
||||
ret.low = ~ret.low; \
|
||||
ret.high = ~ret.high; \
|
||||
if (ret.low == UINT_MAX) { \
|
||||
ret.low = 0; \
|
||||
ret.high++; \
|
||||
} else \
|
||||
ret.low++; \
|
||||
} \
|
||||
\
|
||||
double_unsigned_struct_return(ret); \
|
||||
}
|
||||
|
||||
/* double to unsigned long long conversion */
|
||||
DEFINE__AEABI_D2XLZ(d2ulz, 0)
|
||||
|
||||
/* double to long long conversion */
|
||||
DEFINE__AEABI_D2XLZ(d2lz, 1)
|
||||
|
||||
/* long long to float conversion */
|
||||
#define DEFINE__AEABI_XL2F(name, with_sign) \
|
||||
unsigned __aeabi_ ## name(unsigned long long v) \
|
||||
{ \
|
||||
int s /* shift */, flb /* first lost bit */, sign = 0; \
|
||||
unsigned p = 0 /* power */, ret; \
|
||||
double_unsigned_struct val; \
|
||||
\
|
||||
/* fraction in negative float is encoded in 1's complement */ \
|
||||
if (with_sign && (v & (1ULL << 63))) { \
|
||||
sign = 1; \
|
||||
v = ~v + 1; \
|
||||
} \
|
||||
val.low = v; \
|
||||
val.high = v >> 32; \
|
||||
/* fill fraction bits */ \
|
||||
for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
|
||||
if (p) { \
|
||||
ret = val.high & (p - 1); \
|
||||
if (s < FLOAT_FRAC_BITS) { \
|
||||
ret <<= FLOAT_FRAC_BITS - s; \
|
||||
ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \
|
||||
flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \
|
||||
} else { \
|
||||
flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
|
||||
ret >>= s - FLOAT_FRAC_BITS; \
|
||||
} \
|
||||
s += 32; \
|
||||
} else { \
|
||||
for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
|
||||
if (p) { \
|
||||
ret = val.low & (p - 1); \
|
||||
if (s <= FLOAT_FRAC_BITS) { \
|
||||
ret <<= FLOAT_FRAC_BITS - s; \
|
||||
flb = 0; \
|
||||
} else { \
|
||||
flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
|
||||
ret >>= s - FLOAT_FRAC_BITS; \
|
||||
} \
|
||||
} else \
|
||||
return 0; \
|
||||
} \
|
||||
if (flb) \
|
||||
ret++; \
|
||||
\
|
||||
/* fill exponent bits */ \
|
||||
ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
|
||||
\
|
||||
/* fill sign bit */ \
|
||||
ret |= sign << 31; \
|
||||
\
|
||||
return ret; \
|
||||
}
|
||||
|
||||
/* unsigned long long to float conversion */
|
||||
DEFINE__AEABI_XL2F(ul2f, 0)
|
||||
|
||||
/* long long to float conversion */
|
||||
DEFINE__AEABI_XL2F(l2f, 1)
|
||||
|
||||
/* long long to double conversion */
|
||||
#define __AEABI_XL2D(name, with_sign) \
|
||||
void __aeabi_ ## name(unsigned long long v) \
|
||||
{ \
|
||||
int s /* shift */, high_shift, sign = 0; \
|
||||
unsigned tmp, p = 0; \
|
||||
double_unsigned_struct val, ret; \
|
||||
\
|
||||
/* fraction in negative float is encoded in 1's complement */ \
|
||||
if (with_sign && (v & (1ULL << 63))) { \
|
||||
sign = 1; \
|
||||
v = ~v + 1; \
|
||||
} \
|
||||
val.low = v; \
|
||||
val.high = v >> 32; \
|
||||
\
|
||||
/* fill fraction bits */ \
|
||||
for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
|
||||
if (p) { \
|
||||
tmp = val.high & (p - 1); \
|
||||
if (s < DOUBLE_FRAC_BITS - 32) { \
|
||||
high_shift = DOUBLE_FRAC_BITS - 32 - s; \
|
||||
ret.high = tmp << high_shift; \
|
||||
ret.high |= val.low >> (32 - high_shift); \
|
||||
ret.low = val.low << high_shift; \
|
||||
} else { \
|
||||
high_shift = s - (DOUBLE_FRAC_BITS - 32); \
|
||||
ret.high = tmp >> high_shift; \
|
||||
ret.low = tmp << (32 - high_shift); \
|
||||
ret.low |= val.low >> high_shift; \
|
||||
if ((val.low >> (high_shift - 1)) & 1) { \
|
||||
if (ret.low == UINT_MAX) { \
|
||||
ret.high++; \
|
||||
ret.low = 0; \
|
||||
} else \
|
||||
ret.low++; \
|
||||
} \
|
||||
} \
|
||||
s += 32; \
|
||||
} else { \
|
||||
for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
|
||||
if (p) { \
|
||||
tmp = val.low & (p - 1); \
|
||||
if (s <= DOUBLE_FRAC_BITS - 32) { \
|
||||
high_shift = DOUBLE_FRAC_BITS - 32 - s; \
|
||||
ret.high = tmp << high_shift; \
|
||||
ret.low = 0; \
|
||||
} else { \
|
||||
high_shift = s - (DOUBLE_FRAC_BITS - 32); \
|
||||
ret.high = tmp >> high_shift; \
|
||||
ret.low = tmp << (32 - high_shift); \
|
||||
} \
|
||||
} else { \
|
||||
ret.high = ret.low = 0; \
|
||||
double_unsigned_struct_return(ret); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
/* fill exponent bits */ \
|
||||
ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \
|
||||
\
|
||||
/* fill sign bit */ \
|
||||
ret.high |= sign << 31; \
|
||||
\
|
||||
double_unsigned_struct_return(ret); \
|
||||
}
|
||||
|
||||
/* unsigned long long to double conversion */
|
||||
__AEABI_XL2D(ul2d, 0)
|
||||
|
||||
/* long long to double conversion */
|
||||
__AEABI_XL2D(l2d, 1)
|
||||
|
||||
|
||||
/* Long long helper functions */
|
||||
|
||||
/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
|
||||
|
||||
#define define_aeabi_xdivmod_signed_type(basetype, type) \
|
||||
typedef struct type { \
|
||||
basetype quot; \
|
||||
unsigned basetype rem; \
|
||||
} type
|
||||
|
||||
#define define_aeabi_xdivmod_unsigned_type(basetype, type) \
|
||||
typedef struct type { \
|
||||
basetype quot; \
|
||||
basetype rem; \
|
||||
} type
|
||||
|
||||
#define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
|
||||
static inline rettype aeabi_ ## name (type num, type den) \
|
||||
{ \
|
||||
rettype ret; \
|
||||
type quot = 0; \
|
||||
\
|
||||
/* Increase quotient while it is less than numerator */ \
|
||||
while (num >= den) { \
|
||||
type q = 1; \
|
||||
\
|
||||
/* Find closest power of two */ \
|
||||
while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
|
||||
q <<= 1; \
|
||||
\
|
||||
/* Compute difference between current quotient and numerator */ \
|
||||
num -= q * den; \
|
||||
quot += q; \
|
||||
} \
|
||||
ret.quot = quot; \
|
||||
ret.rem = num; \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \
|
||||
void __aeabi_ ## name(type numerator, type denominator) \
|
||||
{ \
|
||||
unsigned type num, den; \
|
||||
urettype uxdiv_ret; \
|
||||
rettype ret; \
|
||||
\
|
||||
if (numerator >= 0) \
|
||||
num = numerator; \
|
||||
else \
|
||||
num = 0 - numerator; \
|
||||
if (denominator >= 0) \
|
||||
den = denominator; \
|
||||
else \
|
||||
den = 0 - denominator; \
|
||||
uxdiv_ret = aeabi_ ## uiname(num, den); \
|
||||
/* signs differ */ \
|
||||
if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
|
||||
ret.quot = 0 - uxdiv_ret.quot; \
|
||||
else \
|
||||
ret.quot = uxdiv_ret.quot; \
|
||||
if (numerator < 0) \
|
||||
ret.rem = 0 - uxdiv_ret.rem; \
|
||||
else \
|
||||
ret.rem = uxdiv_ret.rem; \
|
||||
\
|
||||
rettype ## _return(ret); \
|
||||
}
|
||||
|
||||
define_aeabi_xdivmod_signed_type(long long, lldiv_t);
|
||||
define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t);
|
||||
define_aeabi_xdivmod_signed_type(int, idiv_t);
|
||||
define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t);
|
||||
|
||||
REGS_RETURN(lldiv_t, lldiv_t)
|
||||
REGS_RETURN(ulldiv_t, ulldiv_t)
|
||||
REGS_RETURN(idiv_t, idiv_t)
|
||||
REGS_RETURN(uidiv_t, uidiv_t)
|
||||
|
||||
AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULONG)
|
||||
|
||||
__AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG)
|
||||
|
||||
void __aeabi_uldivmod(unsigned long long num, unsigned long long den)
|
||||
{
|
||||
ulldiv_t_return(aeabi_uldivmod(num, den));
|
||||
}
|
||||
|
||||
void __aeabi_llsl(double_unsigned_struct val, int shift)
|
||||
{
|
||||
double_unsigned_struct ret;
|
||||
|
||||
if (shift >= 32) {
|
||||
val.high = val.low;
|
||||
val.low = 0;
|
||||
shift -= 32;
|
||||
}
|
||||
if (shift > 0) {
|
||||
ret.low = val.low << shift;
|
||||
ret.high = (val.high << shift) | (val.low >> (32 - shift));
|
||||
double_unsigned_struct_return(ret);
|
||||
return;
|
||||
}
|
||||
double_unsigned_struct_return(val);
|
||||
}
|
||||
|
||||
#define aeabi_lsr(val, shift, fill, type) \
|
||||
type ## _struct ret; \
|
||||
\
|
||||
if (shift >= 32) { \
|
||||
val.low = val.high; \
|
||||
val.high = fill; \
|
||||
shift -= 32; \
|
||||
} \
|
||||
if (shift > 0) { \
|
||||
ret.high = val.high >> shift; \
|
||||
ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
|
||||
type ## _struct_return(ret); \
|
||||
return; \
|
||||
} \
|
||||
type ## _struct_return(val);
|
||||
|
||||
void __aeabi_llsr(double_unsigned_struct val, int shift)
|
||||
{
|
||||
aeabi_lsr(val, shift, 0, double_unsigned);
|
||||
}
|
||||
|
||||
void __aeabi_lasr(unsigned_int_struct val, int shift)
|
||||
{
|
||||
aeabi_lsr(val, shift, val.high >> 31, unsigned_int);
|
||||
}
|
||||
|
||||
|
||||
/* Integer division functions */
|
||||
|
||||
AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
|
||||
|
||||
int __aeabi_idiv(int numerator, int denominator)
|
||||
{
|
||||
unsigned num, den;
|
||||
uidiv_t ret;
|
||||
|
||||
if (numerator >= 0)
|
||||
num = numerator;
|
||||
else
|
||||
num = 0 - numerator;
|
||||
if (denominator >= 0)
|
||||
den = denominator;
|
||||
else
|
||||
den = 0 - denominator;
|
||||
ret = aeabi_uidivmod(num, den);
|
||||
if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */
|
||||
ret.quot *= -1;
|
||||
return ret.quot;
|
||||
}
|
||||
|
||||
unsigned __aeabi_uidiv(unsigned num, unsigned den)
|
||||
{
|
||||
return aeabi_uidivmod(num, den).quot;
|
||||
}
|
||||
|
||||
__AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT)
|
||||
|
||||
void __aeabi_uidivmod(unsigned num, unsigned den)
|
||||
{
|
||||
uidiv_t_return(aeabi_uidivmod(num, den));
|
||||
}
|
13
lib/bcheck.c
13
lib/bcheck.c
@ -22,7 +22,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) \
|
||||
&& !defined(__DragonFly__) && !defined(__OpenBSD__)
|
||||
&& !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#if !defined(_WIN32)
|
||||
@ -41,7 +41,7 @@
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
|
||||
|| defined(__DragonFly__) || defined(__dietlibc__) \
|
||||
|| defined(__UCLIBC__) || defined(__OpenBSD__) \
|
||||
|| defined(__UCLIBC__) || defined(__OpenBSD__) || defined(__NetBSD__) \
|
||||
|| defined(_WIN32) || defined(TCC_UCLIBC)
|
||||
#warning Bound checking does not support malloc (etc.) in this environment.
|
||||
#undef CONFIG_TCC_MALLOC_HOOKS
|
||||
@ -418,6 +418,13 @@ void __bound_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
void __bound_main_arg(void **p)
|
||||
{
|
||||
void *start = p;
|
||||
while (*p++);
|
||||
__bound_new_region(start, (void *) p - start);
|
||||
}
|
||||
|
||||
void __bound_exit(void)
|
||||
{
|
||||
restore_malloc_hooks();
|
||||
@ -628,7 +635,7 @@ int __bound_delete_region(void *p)
|
||||
}
|
||||
|
||||
/* return the size of the region starting at p, or EMPTY_SIZE if non
|
||||
existant region. */
|
||||
existent region. */
|
||||
static unsigned long get_region_size(void *p)
|
||||
{
|
||||
unsigned long addr = (unsigned long)p;
|
||||
|
@ -28,6 +28,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define W_TYPE_SIZE 32
|
||||
#define BITS_PER_UNIT 8
|
||||
|
||||
@ -107,10 +109,10 @@ union float_long {
|
||||
};
|
||||
|
||||
/* XXX: we don't support several builtin supports for now */
|
||||
#ifndef __x86_64__
|
||||
#if !defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_ARM)
|
||||
|
||||
/* XXX: use gcc/tcc intrinsic ? */
|
||||
#if defined(__i386__)
|
||||
#if defined(TCC_TARGET_I386)
|
||||
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
||||
__asm__ ("subl %5,%1\n\tsbbl %3,%0" \
|
||||
: "=r" ((USItype) (sh)), \
|
||||
@ -478,13 +480,6 @@ long long __ashldi3(long long a, int b)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__i386__)
|
||||
/* FPU control word for rounding to nearest mode */
|
||||
unsigned short __tcc_fpu_control = 0x137f;
|
||||
/* FPU control word for round to zero mode for int conversion */
|
||||
unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00;
|
||||
#endif
|
||||
|
||||
#endif /* !__x86_64__ */
|
||||
|
||||
/* XXX: fix tcc's code generator to do this instead */
|
||||
@ -605,15 +600,38 @@ unsigned long long __fixunsxfdi (long double a1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) && !defined(_WIN64)
|
||||
long long __fixsfdi (float a1)
|
||||
{
|
||||
long long ret; int s;
|
||||
ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1);
|
||||
return s ? ret : -ret;
|
||||
}
|
||||
|
||||
long long __fixdfdi (double a1)
|
||||
{
|
||||
long long ret; int s;
|
||||
ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1);
|
||||
return s ? ret : -ret;
|
||||
}
|
||||
|
||||
long long __fixxfdi (long double a1)
|
||||
{
|
||||
long long ret; int s;
|
||||
ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1);
|
||||
return s ? ret : -ret;
|
||||
}
|
||||
|
||||
#if defined(TCC_TARGET_X86_64) && !defined(_WIN64)
|
||||
|
||||
#ifndef __TINYC__
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#else
|
||||
/* Avoid including stdlib.h because it is not easily available when
|
||||
cross compiling */
|
||||
extern void *malloc(unsigned long long);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
extern void free(void*);
|
||||
extern void abort(void);
|
||||
#endif
|
||||
@ -622,8 +640,9 @@ enum __va_arg_type {
|
||||
__va_gen_reg, __va_float_reg, __va_stack
|
||||
};
|
||||
|
||||
//This should be in sync with the declaration on our include/stdarg.h
|
||||
/* GCC compatible definition of va_list. */
|
||||
struct __va_list_struct {
|
||||
typedef struct {
|
||||
unsigned int gp_offset;
|
||||
unsigned int fp_offset;
|
||||
union {
|
||||
@ -631,19 +650,22 @@ struct __va_list_struct {
|
||||
char *overflow_arg_area;
|
||||
};
|
||||
char *reg_save_area;
|
||||
};
|
||||
} __va_list_struct;
|
||||
|
||||
void *__va_start(void *fp)
|
||||
#undef __va_start
|
||||
#undef __va_arg
|
||||
#undef __va_copy
|
||||
#undef __va_end
|
||||
|
||||
void __va_start(__va_list_struct *ap, void *fp)
|
||||
{
|
||||
struct __va_list_struct *ap =
|
||||
(struct __va_list_struct *)malloc(sizeof(struct __va_list_struct));
|
||||
*ap = *(struct __va_list_struct *)((char *)fp - 16);
|
||||
memset(ap, 0, sizeof(__va_list_struct));
|
||||
*ap = *(__va_list_struct *)((char *)fp - 16);
|
||||
ap->overflow_arg_area = (char *)fp + ap->overflow_offset;
|
||||
ap->reg_save_area = (char *)fp - 176 - 16;
|
||||
return ap;
|
||||
}
|
||||
|
||||
void *__va_arg(struct __va_list_struct *ap,
|
||||
void *__va_arg(__va_list_struct *ap,
|
||||
enum __va_arg_type arg_type,
|
||||
int size, int align)
|
||||
{
|
||||
@ -669,7 +691,7 @@ void *__va_arg(struct __va_list_struct *ap,
|
||||
case __va_stack:
|
||||
use_overflow_area:
|
||||
ap->overflow_arg_area += size;
|
||||
ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -(long long)align);
|
||||
ap->overflow_arg_area = (char*)((intptr_t)(ap->overflow_arg_area + align - 1) & -(intptr_t)align);
|
||||
return ap->overflow_arg_area - size;
|
||||
|
||||
default:
|
||||
@ -680,28 +702,38 @@ void *__va_arg(struct __va_list_struct *ap,
|
||||
}
|
||||
}
|
||||
|
||||
void *__va_copy(struct __va_list_struct *src)
|
||||
{
|
||||
struct __va_list_struct *dest =
|
||||
(struct __va_list_struct *)malloc(sizeof(struct __va_list_struct));
|
||||
*dest = *src;
|
||||
return dest;
|
||||
}
|
||||
|
||||
void __va_end(struct __va_list_struct *ap)
|
||||
{
|
||||
free(ap);
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
||||
/* Flushing for tccrun */
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
#if defined(TCC_TARGET_X86_64) || defined(TCC_TARGET_I386)
|
||||
|
||||
void __clear_cache(char *beginning, char *end)
|
||||
{
|
||||
}
|
||||
|
||||
#elif defined(TCC_TARGET_ARM)
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void __clear_cache(char *beginning, char *end)
|
||||
{
|
||||
/* __ARM_NR_cacheflush is kernel private and should not be used in user space.
|
||||
* However, there is no ARM asm parser in tcc so we use it for now */
|
||||
#if 1
|
||||
syscall(__ARM_NR_cacheflush, beginning, end, 0);
|
||||
#else
|
||||
__asm__ ("push {r7}\n\t"
|
||||
"mov r7, #0xf0002\n\t"
|
||||
"mov r2, #0\n\t"
|
||||
"swi 0\n\t"
|
||||
"pop {r7}\n\t"
|
||||
"ret");
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
#warning __clear_cache not defined for this architecture, avoid using tcc -run
|
||||
#endif
|
||||
|
176
libtcc.c
176
libtcc.c
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TCC - Tiny C Compiler
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2001-2004 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
@ -78,21 +78,13 @@ ST_FUNC void asm_global_instr(void)
|
||||
#endif
|
||||
|
||||
/********************************************************/
|
||||
|
||||
#ifdef _WIN32
|
||||
// GCC appears to use '/' for relative paths and '\\' for absolute paths on Windows
|
||||
static char *normalize_slashes(char *path)
|
||||
{
|
||||
char *p;
|
||||
if (path[1] == ':') {
|
||||
for (p = path+2; *p; ++p)
|
||||
if (*p == '/')
|
||||
*p = '\\';
|
||||
} else {
|
||||
for (p = path; *p; ++p)
|
||||
if (*p == '\\')
|
||||
*p = '/';
|
||||
}
|
||||
for (p = path; *p; ++p)
|
||||
if (*p == '\\')
|
||||
*p = '/';
|
||||
return path;
|
||||
}
|
||||
|
||||
@ -129,7 +121,7 @@ void dlclose(void *p)
|
||||
#endif
|
||||
|
||||
#ifdef LIBTCC_AS_DLL
|
||||
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
|
||||
BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved)
|
||||
{
|
||||
if (DLL_PROCESS_ATTACH == dwReason)
|
||||
tcc_module = hDll;
|
||||
@ -164,7 +156,7 @@ PUB_FUNC char *pstrcat(char *buf, int buf_size, const char *s)
|
||||
{
|
||||
int len;
|
||||
len = strlen(buf);
|
||||
if (len < buf_size)
|
||||
if (len < buf_size)
|
||||
pstrcpy(buf + len, buf_size - len, s);
|
||||
return buf;
|
||||
}
|
||||
@ -222,7 +214,7 @@ PUB_FUNC void *tcc_malloc(unsigned long size)
|
||||
void *ptr;
|
||||
ptr = malloc(size);
|
||||
if (!ptr && size)
|
||||
tcc_error("memory full");
|
||||
tcc_error("memory full (malloc)");
|
||||
#ifdef MEM_DEBUG
|
||||
mem_cur_size += malloc_usable_size(ptr);
|
||||
if (mem_cur_size > mem_max_size)
|
||||
@ -247,7 +239,7 @@ PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size)
|
||||
#endif
|
||||
ptr1 = realloc(ptr, size);
|
||||
if (!ptr1 && size)
|
||||
tcc_error("memory full");
|
||||
tcc_error("memory full (realloc)");
|
||||
#ifdef MEM_DEBUG
|
||||
/* NOTE: count not correct if alloc error, but not critical */
|
||||
mem_cur_size += malloc_usable_size(ptr1);
|
||||
@ -283,7 +275,7 @@ ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data)
|
||||
{
|
||||
int nb, nb_alloc;
|
||||
void **pp;
|
||||
|
||||
|
||||
nb = *nb_ptr;
|
||||
pp = *ptab;
|
||||
/* every power of two we double array size */
|
||||
@ -379,7 +371,7 @@ ST_FUNC void section_realloc(Section *sec, unsigned long new_size)
|
||||
{
|
||||
unsigned long size;
|
||||
unsigned char *data;
|
||||
|
||||
|
||||
size = sec->data_allocated;
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
@ -422,7 +414,7 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name)
|
||||
int i;
|
||||
for(i = 1; i < s1->nb_sections; i++) {
|
||||
sec = s1->sections[i];
|
||||
if (!strcmp(name, sec->name))
|
||||
if (!strcmp(name, sec->name))
|
||||
return sec;
|
||||
}
|
||||
/* sections are created as PROGBITS */
|
||||
@ -431,7 +423,7 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name)
|
||||
|
||||
/* update sym->c so that it points to an external symbol in section
|
||||
'section' with value 'value' */
|
||||
ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||
ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||
addr_t value, unsigned long size,
|
||||
int can_add_underscore)
|
||||
{
|
||||
@ -442,7 +434,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||
|
||||
if (section == NULL)
|
||||
sh_num = SHN_UNDEF;
|
||||
else if (section == SECTION_ABS)
|
||||
else if (section == SECTION_ABS)
|
||||
sh_num = SHN_ABS;
|
||||
else
|
||||
sh_num = section->sh_num;
|
||||
@ -476,13 +468,13 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||
switch(sym->v) {
|
||||
#ifdef TCC_TARGET_PE
|
||||
/* XXX: we rely only on malloc hooks */
|
||||
case TOK_malloc:
|
||||
case TOK_free:
|
||||
case TOK_realloc:
|
||||
case TOK_memalign:
|
||||
case TOK_calloc:
|
||||
case TOK_malloc:
|
||||
case TOK_free:
|
||||
case TOK_realloc:
|
||||
case TOK_memalign:
|
||||
case TOK_calloc:
|
||||
#endif
|
||||
case TOK_memcpy:
|
||||
case TOK_memcpy:
|
||||
case TOK_memmove:
|
||||
case TOK_memset:
|
||||
case TOK_strlen:
|
||||
@ -499,23 +491,26 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (sym->type.t & VT_EXPORT)
|
||||
other |= 1;
|
||||
other |= ST_PE_EXPORT;
|
||||
if (sym_type == STT_FUNC && sym->type.ref) {
|
||||
int attr = sym->type.ref->r;
|
||||
if (FUNC_EXPORT(attr))
|
||||
other |= 1;
|
||||
if (FUNC_CALL(attr) == FUNC_STDCALL && can_add_underscore) {
|
||||
sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr) * PTR_SIZE);
|
||||
Sym *ref = sym->type.ref;
|
||||
if (ref->a.func_export)
|
||||
other |= ST_PE_EXPORT;
|
||||
if (ref->a.func_call == FUNC_STDCALL && can_add_underscore) {
|
||||
sprintf(buf1, "_%s@%d", name, ref->a.func_args * PTR_SIZE);
|
||||
name = buf1;
|
||||
other |= 2;
|
||||
other |= ST_PE_STDCALL;
|
||||
can_add_underscore = 0;
|
||||
}
|
||||
} else {
|
||||
if (find_elf_sym(tcc_state->dynsymtab_section, name))
|
||||
other |= 4;
|
||||
other |= ST_PE_IMPORT;
|
||||
if (sym->type.t & VT_IMPORT)
|
||||
other |= 4;
|
||||
other |= ST_PE_IMPORT;
|
||||
}
|
||||
#else
|
||||
if (! (sym->type.t & VT_STATIC))
|
||||
other = (sym->type.t & VT_VIS_MASK) >> VT_VIS_SHIFT;
|
||||
#endif
|
||||
if (tcc_state->leading_underscore && can_add_underscore) {
|
||||
buf1[0] = '_';
|
||||
@ -535,7 +530,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC void put_extern_sym(Sym *sym, Section *section,
|
||||
ST_FUNC void put_extern_sym(Sym *sym, Section *section,
|
||||
addr_t value, unsigned long size)
|
||||
{
|
||||
put_extern_sym2(sym, section, value, size, 1);
|
||||
@ -575,7 +570,7 @@ static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
|
||||
{
|
||||
char buf[2048];
|
||||
BufferedFile **pf, *f;
|
||||
|
||||
|
||||
buf[0] = '\0';
|
||||
/* use upper file if inline ":asm:" or token ":paste:" */
|
||||
for (f = file; f && f->filename[0] == ':'; f = f->prev)
|
||||
@ -726,28 +721,28 @@ static int tcc_compile(TCCState *s1)
|
||||
|
||||
cur_text_section = NULL;
|
||||
funcname = "";
|
||||
anon_sym = SYM_FIRST_ANOM;
|
||||
anon_sym = SYM_FIRST_ANOM;
|
||||
|
||||
/* file info: full path + filename */
|
||||
section_sym = 0; /* avoid warning */
|
||||
if (s1->do_debug) {
|
||||
section_sym = put_elf_sym(symtab_section, 0, 0,
|
||||
ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
|
||||
section_sym = put_elf_sym(symtab_section, 0, 0,
|
||||
ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
|
||||
text_section->sh_num, NULL);
|
||||
getcwd(buf, sizeof(buf));
|
||||
#ifdef _WIN32
|
||||
normalize_slashes(buf);
|
||||
#endif
|
||||
pstrcat(buf, sizeof(buf), "/");
|
||||
put_stabs_r(buf, N_SO, 0, 0,
|
||||
put_stabs_r(buf, N_SO, 0, 0,
|
||||
text_section->data_offset, text_section, section_sym);
|
||||
put_stabs_r(file->filename, N_SO, 0, 0,
|
||||
put_stabs_r(file->filename, N_SO, 0, 0,
|
||||
text_section->data_offset, text_section, section_sym);
|
||||
}
|
||||
/* an elf symbol of type STT_FILE must be put so that STB_LOCAL
|
||||
symbols can be safely used */
|
||||
put_elf_sym(symtab_section, 0, 0,
|
||||
ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
|
||||
put_elf_sym(symtab_section, 0, 0,
|
||||
ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
|
||||
SHN_ABS, file->filename);
|
||||
|
||||
/* define some often used types */
|
||||
@ -765,7 +760,7 @@ static int tcc_compile(TCCState *s1)
|
||||
func_old_type.t = VT_FUNC;
|
||||
func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
|
||||
#ifdef TCC_TARGET_ARM
|
||||
arm_init_types();
|
||||
arm_init(s1);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
@ -802,7 +797,7 @@ static int tcc_compile(TCCState *s1)
|
||||
|
||||
/* end of translation unit info */
|
||||
if (s1->do_debug) {
|
||||
put_stabs_r(NULL, N_SO, 0, 0,
|
||||
put_stabs_r(NULL, N_SO, 0, 0,
|
||||
text_section->data_offset, text_section, section_sym);
|
||||
}
|
||||
}
|
||||
@ -811,7 +806,7 @@ static int tcc_compile(TCCState *s1)
|
||||
|
||||
/* reset define stack, but leave -Dsymbols (may be incorrect if
|
||||
they are undefined) */
|
||||
free_defines(define_start);
|
||||
free_defines(define_start);
|
||||
|
||||
gen_inline_functions();
|
||||
|
||||
@ -950,6 +945,16 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||
tcc_define_symbol(s, "__arm", NULL);
|
||||
tcc_define_symbol(s, "arm", NULL);
|
||||
tcc_define_symbol(s, "__APCS_32__", NULL);
|
||||
tcc_define_symbol(s, "__ARMEL__", NULL);
|
||||
#if defined(TCC_ARM_EABI)
|
||||
tcc_define_symbol(s, "__ARM_EABI__", NULL);
|
||||
#endif
|
||||
#if defined(TCC_ARM_HARDFLOAT)
|
||||
s->float_abi = ARM_HARD_FLOAT;
|
||||
tcc_define_symbol(s, "__ARM_PCS_VFP", NULL);
|
||||
#else
|
||||
s->float_abi = ARM_SOFTFP_FLOAT;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
@ -986,16 +991,23 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
|
||||
tcc_define_symbol(s, "__WINT_TYPE__", "unsigned short");
|
||||
#else
|
||||
tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
|
||||
/* wint_t is unsigned int by default, but (signed) int on BSDs
|
||||
and unsigned short on windows. Other OSes might have still
|
||||
other conventions, sigh. */
|
||||
#if defined(__FreeBSD__) || defined (__FreeBSD_kernel__)
|
||||
tcc_define_symbol(s, "__WINT_TYPE__", "int");
|
||||
#else
|
||||
tcc_define_symbol(s, "__WINT_TYPE__", "unsigned int");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TCC_TARGET_PE
|
||||
/* glibc defines */
|
||||
tcc_define_symbol(s, "__REDIRECT(name, proto, alias)", "name proto __asm__ (#alias)");
|
||||
tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", "name proto __asm__ (#alias) __THROW");
|
||||
/* default library paths */
|
||||
tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
|
||||
/* paths for crt objects */
|
||||
tcc_split_path(s, (void ***)&s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
|
||||
#endif
|
||||
@ -1011,13 +1023,13 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||
/* symbols are always generated for linking stage */
|
||||
symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
|
||||
".strtab",
|
||||
".hashtab", SHF_PRIVATE);
|
||||
".hashtab", SHF_PRIVATE);
|
||||
strtab_section = symtab_section->link;
|
||||
s->symtab = symtab_section;
|
||||
|
||||
|
||||
/* private symbol table for dynamic symbols */
|
||||
s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
|
||||
".dynstrtab",
|
||||
".dynstrtab",
|
||||
".dynhashtab", SHF_PRIVATE);
|
||||
s->alacarte_link = 1;
|
||||
s->nocommon = 1;
|
||||
@ -1032,6 +1044,9 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||
#endif
|
||||
#ifdef TCC_TARGET_I386
|
||||
s->seg_size = 32;
|
||||
#endif
|
||||
#ifdef TCC_IS_NATIVE
|
||||
s->runtime_main = "main";
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
@ -1050,7 +1065,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
|
||||
for(i = 0; i < s1->nb_priv_sections; i++)
|
||||
free_section(s1->priv_sections[i]);
|
||||
dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
|
||||
|
||||
|
||||
/* free any loaded DLLs */
|
||||
#ifdef TCC_IS_NATIVE
|
||||
for ( i = 0; i < s1->nb_loaded_dlls; i++) {
|
||||
@ -1059,7 +1074,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
|
||||
dlclose(ref->handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* free loaded dlls array */
|
||||
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
|
||||
|
||||
@ -1085,12 +1100,14 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
|
||||
#ifdef TCC_IS_NATIVE
|
||||
# ifdef HAVE_SELINUX
|
||||
munmap (s1->write_mem, s1->mem_size);
|
||||
munmap (s1->runtime_mem, s1->mem_size);
|
||||
munmap (s1->runtime_mem, s1->mem_size);
|
||||
# else
|
||||
tcc_free(s1->runtime_mem);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if(s1->sym_attrs) tcc_free(s1->sym_attrs);
|
||||
|
||||
tcc_free(s1);
|
||||
}
|
||||
|
||||
@ -1192,7 +1209,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||
#endif
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = tcc_load_dll(s1, fd, filename,
|
||||
ret = tcc_load_dll(s1, fd, filename,
|
||||
(flags & AFF_REFERENCED_DLL) != 0);
|
||||
}
|
||||
goto the_end;
|
||||
@ -1299,8 +1316,6 @@ LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val)
|
||||
So it is handled here as if it were in a DLL. */
|
||||
pe_putimport(s, 0, name, (uintptr_t)val);
|
||||
#else
|
||||
/* XXX: Same problem on linux but currently "solved" elsewhere
|
||||
via the rather dirty 'runtime_plt_and_got' hack. */
|
||||
add_elf_sym(symtab_section, (uintptr_t)val, 0,
|
||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
||||
SHN_ABS, name);
|
||||
@ -1324,9 +1339,9 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
||||
/* define symbol */
|
||||
tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
|
||||
/* create bounds sections */
|
||||
bounds_section = new_section(s, ".bounds",
|
||||
bounds_section = new_section(s, ".bounds",
|
||||
SHT_PROGBITS, SHF_ALLOC);
|
||||
lbounds_section = new_section(s, ".lbounds",
|
||||
lbounds_section = new_section(s, ".lbounds",
|
||||
SHT_PROGBITS, SHF_ALLOC);
|
||||
}
|
||||
#endif
|
||||
@ -1347,8 +1362,8 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
||||
put_stabs("", 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
|
||||
#ifdef TCC_TARGET_PE
|
||||
# ifdef _WIN32
|
||||
tcc_add_systemdir(s);
|
||||
# endif
|
||||
@ -1557,6 +1572,10 @@ static int tcc_set_linker(TCCState *s, const char *option)
|
||||
} else
|
||||
goto err;
|
||||
|
||||
} else if (link_option(option, "as-needed", &p)) {
|
||||
ignoring = 1;
|
||||
} else if (link_option(option, "O", &p)) {
|
||||
ignoring = 1;
|
||||
} else if (link_option(option, "rpath=", &p)) {
|
||||
s->rpath = copy_linker_arg(p);
|
||||
} else if (link_option(option, "section-alignment=", &p)) {
|
||||
@ -1628,6 +1647,7 @@ enum {
|
||||
TCC_OPTION_b,
|
||||
TCC_OPTION_g,
|
||||
TCC_OPTION_c,
|
||||
TCC_OPTION_float_abi,
|
||||
TCC_OPTION_static,
|
||||
TCC_OPTION_shared,
|
||||
TCC_OPTION_soname,
|
||||
@ -1647,7 +1667,6 @@ enum {
|
||||
TCC_OPTION_pedantic,
|
||||
TCC_OPTION_pthread,
|
||||
TCC_OPTION_run,
|
||||
TCC_OPTION_norunsrc,
|
||||
TCC_OPTION_v,
|
||||
TCC_OPTION_w,
|
||||
TCC_OPTION_pipe,
|
||||
@ -1680,6 +1699,9 @@ static const TCCOption tcc_options[] = {
|
||||
#endif
|
||||
{ "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "c", TCC_OPTION_c, 0 },
|
||||
#ifdef TCC_TARGET_ARM
|
||||
{ "mfloat-abi", TCC_OPTION_float_abi, TCC_OPTION_HAS_ARG },
|
||||
#endif
|
||||
{ "static", TCC_OPTION_static, 0 },
|
||||
{ "shared", TCC_OPTION_shared, 0 },
|
||||
{ "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
|
||||
@ -1687,7 +1709,6 @@ static const TCCOption tcc_options[] = {
|
||||
{ "pedantic", TCC_OPTION_pedantic, 0},
|
||||
{ "pthread", TCC_OPTION_pthread, 0},
|
||||
{ "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "norunsrc", TCC_OPTION_norunsrc, 0 },
|
||||
{ "rdynamic", TCC_OPTION_rdynamic, 0 },
|
||||
{ "r", TCC_OPTION_r, 0 },
|
||||
{ "s", TCC_OPTION_s, 0 },
|
||||
@ -1699,7 +1720,7 @@ static const TCCOption tcc_options[] = {
|
||||
{ "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
|
||||
{ "nostdinc", TCC_OPTION_nostdinc, 0 },
|
||||
{ "nostdlib", TCC_OPTION_nostdlib, 0 },
|
||||
{ "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
|
||||
{ "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
|
||||
{ "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
||||
{ "w", TCC_OPTION_w, 0 },
|
||||
{ "pipe", TCC_OPTION_pipe, 0},
|
||||
@ -1726,7 +1747,6 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
|
||||
const TCCOption *popt;
|
||||
const char *optarg, *r;
|
||||
int run = 0;
|
||||
int norunsrc = 0;
|
||||
int pthread = 0;
|
||||
int optind = 0;
|
||||
|
||||
@ -1739,8 +1759,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
|
||||
r = argv[optind++];
|
||||
if (r[0] != '-' || r[1] == '\0') {
|
||||
/* add a new file */
|
||||
if (!run || !norunsrc)
|
||||
dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));
|
||||
dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));
|
||||
if (run) {
|
||||
optind--;
|
||||
/* argv[0] will be this file */
|
||||
@ -1817,6 +1836,18 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
|
||||
case TCC_OPTION_c:
|
||||
s->output_type = TCC_OUTPUT_OBJ;
|
||||
break;
|
||||
#ifdef TCC_TARGET_ARM
|
||||
case TCC_OPTION_float_abi:
|
||||
/* tcc doesn't support soft float yet */
|
||||
if (!strcmp(optarg, "softfp")) {
|
||||
s->float_abi = ARM_SOFTFP_FLOAT;
|
||||
tcc_undefine_symbol(s, "__ARM_PCS_VFP");
|
||||
} else if (!strcmp(optarg, "hard"))
|
||||
s->float_abi = ARM_HARD_FLOAT;
|
||||
else
|
||||
tcc_error("unsupported float abi '%s'", optarg);
|
||||
break;
|
||||
#endif
|
||||
case TCC_OPTION_static:
|
||||
s->static_link = 1;
|
||||
break;
|
||||
@ -1854,9 +1885,6 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
|
||||
tcc_set_options(s, optarg);
|
||||
run = 1;
|
||||
break;
|
||||
case TCC_OPTION_norunsrc:
|
||||
norunsrc = 1;
|
||||
break;
|
||||
case TCC_OPTION_v:
|
||||
do ++s->verbose; while (*optarg++ == 'v');
|
||||
break;
|
||||
@ -1865,7 +1893,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
|
||||
goto unsupported_option;
|
||||
break;
|
||||
case TCC_OPTION_W:
|
||||
if (tcc_set_warning(s, optarg, 1) < 0 &&
|
||||
if (tcc_set_warning(s, optarg, 1) < 0 &&
|
||||
s->warn_unsupported)
|
||||
goto unsupported_option;
|
||||
break;
|
||||
@ -1952,7 +1980,7 @@ PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
|
||||
tt = 0.001;
|
||||
if (total_bytes < 1)
|
||||
total_bytes = 1;
|
||||
printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
|
||||
printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
|
||||
tok_ident - TOK_IDENT, total_lines, total_bytes,
|
||||
tt, (int)(total_lines / tt),
|
||||
total_bytes / tt / 1000000.0);
|
||||
@ -1961,7 +1989,7 @@ PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time)
|
||||
PUB_FUNC void tcc_set_environment(TCCState *s)
|
||||
{
|
||||
char * path;
|
||||
|
||||
|
||||
path = getenv("C_INCLUDE_PATH");
|
||||
if(path != NULL) {
|
||||
tcc_add_include_path(s, path);
|
||||
|
11
tcc-doc.texi
11
tcc-doc.texi
@ -176,6 +176,9 @@ In a script, it gives the following header:
|
||||
#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11
|
||||
@end example
|
||||
|
||||
@item -mfloat-abi (ARM only)
|
||||
Select the float ABI. Possible values: @code{softfp} and @code{hard}
|
||||
|
||||
@item -dumpversion
|
||||
Print only the compiler version and nothing else.
|
||||
|
||||
@ -217,7 +220,7 @@ Undefine preprocessor symbol @samp{sym}.
|
||||
|
||||
Compilation flags:
|
||||
|
||||
Note: each of the following warning options has a negative form beginning with
|
||||
Note: each of the following options has a negative form beginning with
|
||||
@option{-fno-}.
|
||||
|
||||
@table @option
|
||||
@ -338,7 +341,7 @@ Generate additional support code to check
|
||||
memory allocations and array/pointer bounds. @option{-g} is implied. Note
|
||||
that the generated code is slower and bigger in this case.
|
||||
|
||||
Note: @option{-b} is only available on i386 for the moment.
|
||||
Note: @option{-b} is only available on i386 when using libtcc for the moment.
|
||||
|
||||
@item -bt N
|
||||
Display N callers in stack traces. This is useful with @option{-g} or
|
||||
@ -967,7 +970,7 @@ be the best solution.
|
||||
#define VT_BITFIELD 0x0040 /* bitfield modifier */
|
||||
#define VT_CONSTANT 0x0800 /* const modifier */
|
||||
#define VT_VOLATILE 0x1000 /* volatile modifier */
|
||||
#define VT_SIGNED 0x2000 /* signed type */
|
||||
#define VT_DEFSIGN 0x2000 /* signed type */
|
||||
|
||||
#define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */
|
||||
@end example
|
||||
@ -1077,7 +1080,7 @@ are used when bound checking is activated
|
||||
|
||||
@item stab_section
|
||||
@itemx stabstr_section
|
||||
are used when debugging is actived to store debug information
|
||||
are used when debugging is active to store debug information
|
||||
|
||||
@item symtab_section
|
||||
@itemx strtab_section
|
||||
|
5
tcc.c
5
tcc.c
@ -69,7 +69,6 @@ static void help(void)
|
||||
" -Bdir use 'dir' as tcc internal library and include path\n"
|
||||
" -MD generate target dependencies for make\n"
|
||||
" -MF depfile put generated dependencies here\n"
|
||||
" -norunsrc Do not compile the file which is the first argument after -run.\n"
|
||||
);
|
||||
}
|
||||
|
||||
@ -79,7 +78,7 @@ static void help(void)
|
||||
#include <process.h>
|
||||
static int execvp_win32(const char *prog, char **argv)
|
||||
{
|
||||
int ret = spawnvp(P_NOWAIT, prog, (char const*const*)argv);
|
||||
int ret = spawnvp(P_NOWAIT, prog, (const char *const*)argv);
|
||||
if (-1 == ret)
|
||||
return ret;
|
||||
cwait(&ret, ret, WAIT_CHILD);
|
||||
@ -224,7 +223,7 @@ static void display_info(TCCState *s, int what)
|
||||
print_paths("crt", s->crt_paths, s->nb_crt_paths);
|
||||
print_paths("libraries", s->library_paths, s->nb_library_paths);
|
||||
print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths);
|
||||
printf("elfinterp:\n %s\n", CONFIG_TCC_ELFINTERP);
|
||||
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
252
tcc.h
252
tcc.h
@ -55,18 +55,27 @@
|
||||
# ifndef CONFIG_TCC_STATIC
|
||||
# include <dlfcn.h>
|
||||
# endif
|
||||
#else
|
||||
/* XXX: need to define this to use them in non ISOC99 context */
|
||||
extern float strtof (const char *__nptr, char **__endptr);
|
||||
extern long double strtold (const char *__nptr, char **__endptr);
|
||||
#else /* on _WIN32: */
|
||||
# include <windows.h>
|
||||
# include <sys/timeb.h>
|
||||
# include <io.h> /* open, close etc. */
|
||||
# include <direct.h> /* getcwd */
|
||||
# ifdef __GNUC__
|
||||
# include <stdint.h>
|
||||
# else
|
||||
typedef UINT_PTR uintptr_t;
|
||||
# endif
|
||||
# define inline __inline
|
||||
# define inp next_inp
|
||||
# define snprintf _snprintf
|
||||
# define vsnprintf _vsnprintf
|
||||
# ifndef __GNUC__
|
||||
# define strtold (long double)strtod
|
||||
# define strtof (float)strtod
|
||||
# define strtoll _strtoi64
|
||||
# define strtoull _strtoui64
|
||||
# endif
|
||||
# ifdef LIBTCC_AS_DLL
|
||||
# define LIBTCCAPI __declspec(dllexport)
|
||||
# define PUB_FUNC LIBTCCAPI
|
||||
@ -79,6 +88,30 @@
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define NORETURN __attribute__ ((noreturn))
|
||||
#elif defined _MSC_VER
|
||||
# define NORETURN __declspec(noreturn)
|
||||
#else
|
||||
# define NORETURN
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# define IS_DIRSEP(c) (c == '/' || c == '\\')
|
||||
# define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2])))
|
||||
# define PATHCMP stricmp
|
||||
#else
|
||||
# define IS_DIRSEP(c) (c == '/')
|
||||
# define IS_ABSPATH(p) IS_DIRSEP(p[0])
|
||||
# define PATHCMP strcmp
|
||||
#endif
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
#define PATHSEP ';'
|
||||
#else
|
||||
#define PATHSEP ':'
|
||||
#endif
|
||||
|
||||
#include "elf.h"
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# define ELFCLASSW ELFCLASS64
|
||||
@ -128,7 +161,8 @@
|
||||
#endif
|
||||
|
||||
#if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
|
||||
!defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)
|
||||
!defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64) && \
|
||||
!defined(CONFIG_USE_LIBGCC)
|
||||
#define CONFIG_TCC_BCHECK /* enable bound checking code */
|
||||
#endif
|
||||
|
||||
@ -169,9 +203,17 @@
|
||||
# define CONFIG_LDDIR "lib"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MULTIARCHDIR
|
||||
# define USE_MUADIR(s) s "/" CONFIG_MULTIARCHDIR
|
||||
# define ALSO_MUADIR(s) s "/" CONFIG_MULTIARCHDIR ":" s
|
||||
#else
|
||||
# define USE_MUADIR(s) s
|
||||
# define ALSO_MUADIR(s) s
|
||||
#endif
|
||||
|
||||
/* path to find crt1.o, crti.o and crtn.o */
|
||||
#ifndef CONFIG_TCC_CRTPREFIX
|
||||
# define CONFIG_TCC_CRTPREFIX CONFIG_SYSROOT "/usr/" CONFIG_LDDIR
|
||||
# define CONFIG_TCC_CRTPREFIX USE_MUADIR(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR)
|
||||
#endif
|
||||
|
||||
/* Below: {B} is substituted by CONFIG_TCCDIR (rsp. -B option) */
|
||||
@ -180,17 +222,10 @@
|
||||
#ifndef CONFIG_TCC_SYSINCLUDEPATHS
|
||||
# ifdef TCC_TARGET_PE
|
||||
# define CONFIG_TCC_SYSINCLUDEPATHS "{B}/include;{B}/include/winapi"
|
||||
# elif defined CONFIG_MULTIARCHDIR
|
||||
# define CONFIG_TCC_SYSINCLUDEPATHS \
|
||||
CONFIG_SYSROOT "/usr/local/include" \
|
||||
":" CONFIG_SYSROOT "/usr/local/include/" CONFIG_MULTIARCHDIR \
|
||||
":" CONFIG_SYSROOT "/usr/include" \
|
||||
":" CONFIG_SYSROOT "/usr/include/" CONFIG_MULTIARCHDIR \
|
||||
":" "{B}/include"
|
||||
# else
|
||||
# define CONFIG_TCC_SYSINCLUDEPATHS \
|
||||
CONFIG_SYSROOT "/usr/local/include" \
|
||||
":" CONFIG_SYSROOT "/usr/include" \
|
||||
ALSO_MUADIR(CONFIG_SYSROOT "/usr/local/include") \
|
||||
":" ALSO_MUADIR(CONFIG_SYSROOT "/usr/include") \
|
||||
":" "{B}/include"
|
||||
# endif
|
||||
#endif
|
||||
@ -198,12 +233,12 @@
|
||||
/* library search paths */
|
||||
#ifndef CONFIG_TCC_LIBPATHS
|
||||
# ifdef TCC_TARGET_PE
|
||||
# define CONFIG_TCC_LIBPATHS "{B}/lib;{B}"
|
||||
# define CONFIG_TCC_LIBPATHS "{B}/lib"
|
||||
# else
|
||||
# define CONFIG_TCC_LIBPATHS \
|
||||
CONFIG_SYSROOT "/usr/" CONFIG_LDDIR \
|
||||
":" CONFIG_SYSROOT "/" CONFIG_LDDIR \
|
||||
":" CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR
|
||||
ALSO_MUADIR(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \
|
||||
":" ALSO_MUADIR(CONFIG_SYSROOT "/" CONFIG_LDDIR) \
|
||||
":" ALSO_MUADIR(CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@ -217,25 +252,30 @@
|
||||
# else
|
||||
# define CONFIG_TCC_ELFINTERP "/lib/ld.so.1"
|
||||
# endif
|
||||
# elif defined __DragonFly__
|
||||
# define CONFIG_TCC_ELFINTERP "/usr/libexec/ld-elf.so.2"
|
||||
# elif defined __GNU__
|
||||
# define CONFIG_TCC_ELFINTERP "/lib/ld.so"
|
||||
# elif defined TCC_ARM_HARDFLOAT
|
||||
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-armhf.so.3"
|
||||
# elif defined TCC_ARM_EABI
|
||||
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.3"
|
||||
# elif defined(TCC_TARGET_X86_64)
|
||||
# define CONFIG_TCC_ELFINTERP "/lib64/ld-linux-x86-64.so.2"
|
||||
# elif defined(TCC_UCLIBC)
|
||||
# define CONFIG_TCC_ELFINTERP "/lib/ld-uClibc.so.0"
|
||||
# elif defined(TCC_TARGET_PE)
|
||||
# define CONFIG_TCC_ELFINTERP "-"
|
||||
# else
|
||||
# elif !defined(TCC_ARM_EABI)
|
||||
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* var elf_interp dans *-gen.c */
|
||||
#ifdef CONFIG_TCC_ELFINTERP
|
||||
# define DEFAULT_ELFINTERP(s) CONFIG_TCC_ELFINTERP
|
||||
#else
|
||||
# define DEFAULT_ELFINTERP(s) default_elfinterp(s)
|
||||
#endif
|
||||
|
||||
/* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */
|
||||
#define TCC_LIBGCC CONFIG_SYSROOT "/" CONFIG_LDDIR "/libgcc_s.so.1"
|
||||
#define TCC_LIBGCC USE_MUADIR(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1"
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* include the target specific definitions */
|
||||
@ -310,7 +350,7 @@ typedef union CValue {
|
||||
long long ll;
|
||||
unsigned long long ull;
|
||||
struct CString *cstr;
|
||||
void *ptr;
|
||||
addr_t ptr_offset;
|
||||
int tab[LDOUBLE_SIZE/4];
|
||||
} CValue;
|
||||
|
||||
@ -324,11 +364,36 @@ typedef struct SValue {
|
||||
struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
|
||||
} SValue;
|
||||
|
||||
struct Attribute {
|
||||
unsigned
|
||||
func_call : 3, /* calling convention (0..5), see below */
|
||||
aligned : 5, /* alignement (0..16) */
|
||||
packed : 1,
|
||||
func_export : 1,
|
||||
func_import : 1,
|
||||
func_args : 5,
|
||||
func_proto : 1,
|
||||
mode : 4,
|
||||
weak : 1,
|
||||
visibility : 2,
|
||||
fill : 8; // 8 bits left to fit well in union below
|
||||
};
|
||||
|
||||
/* GNUC attribute definition */
|
||||
typedef struct AttributeDef {
|
||||
struct Attribute a;
|
||||
struct Section *section;
|
||||
int alias_target; /* token */
|
||||
} AttributeDef;
|
||||
|
||||
/* symbol management */
|
||||
typedef struct Sym {
|
||||
int v; /* symbol token */
|
||||
char *asm_label; /* associated asm label */
|
||||
long r; /* associated register */
|
||||
union {
|
||||
long r; /* associated register */
|
||||
struct Attribute a;
|
||||
};
|
||||
union {
|
||||
long c; /* associated number */
|
||||
int *d; /* define token stream */
|
||||
@ -379,32 +444,6 @@ typedef struct DLLReference {
|
||||
char name[1];
|
||||
} DLLReference;
|
||||
|
||||
/* GNUC attribute definition */
|
||||
typedef struct AttributeDef {
|
||||
unsigned
|
||||
func_call : 3, /* calling convention (0..5), see below */
|
||||
aligned : 5, /* alignement (0..16) */
|
||||
packed : 1,
|
||||
func_export : 1,
|
||||
func_import : 1,
|
||||
func_args : 5,
|
||||
mode : 4,
|
||||
weak : 1,
|
||||
fill : 11;
|
||||
struct Section *section;
|
||||
int alias_target; /* token */
|
||||
} AttributeDef;
|
||||
|
||||
/* gr: wrappers for casting sym->r for other purposes */
|
||||
#define FUNC_CALL(r) (((AttributeDef*)&(r))->func_call)
|
||||
#define FUNC_EXPORT(r) (((AttributeDef*)&(r))->func_export)
|
||||
#define FUNC_IMPORT(r) (((AttributeDef*)&(r))->func_import)
|
||||
#define FUNC_ARGS(r) (((AttributeDef*)&(r))->func_args)
|
||||
#define FUNC_ALIGN(r) (((AttributeDef*)&(r))->aligned)
|
||||
#define FUNC_PACKED(r) (((AttributeDef*)&(r))->packed)
|
||||
#define ATTR_MODE(r) (((AttributeDef*)&(r))->mode)
|
||||
#define INT_ATTR(ad) (*(int*)(ad))
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
|
||||
@ -519,6 +558,7 @@ typedef struct ASMOperand {
|
||||
|
||||
struct sym_attr {
|
||||
unsigned long got_offset;
|
||||
unsigned long plt_offset;
|
||||
#ifdef TCC_TARGET_ARM
|
||||
unsigned char plt_thumb_stub:1;
|
||||
#endif
|
||||
@ -561,6 +601,9 @@ struct TCCState {
|
||||
/* compile with built-in memory and bounds checker */
|
||||
int do_bounds_check;
|
||||
#endif
|
||||
#ifdef TCC_TARGET_ARM
|
||||
enum float_abi float_abi; /* float ABI of the generated code*/
|
||||
#endif
|
||||
|
||||
addr_t text_addr; /* address of text section */
|
||||
int has_text_addr;
|
||||
@ -665,18 +708,13 @@ struct TCCState {
|
||||
#endif
|
||||
|
||||
#ifdef TCC_IS_NATIVE
|
||||
const char *runtime_main;
|
||||
/* for tcc_relocate */
|
||||
void *runtime_mem;
|
||||
# ifdef HAVE_SELINUX
|
||||
void *write_mem;
|
||||
unsigned long mem_size;
|
||||
# endif
|
||||
# if !defined TCC_TARGET_PE && (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM)
|
||||
/* write PLT and GOT here */
|
||||
char *runtime_plt_and_got;
|
||||
unsigned runtime_plt_and_got_offset;
|
||||
# define TCC_HAS_RUNTIME_PLTGOT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* used by main and tcc_parse_args only */
|
||||
@ -738,7 +776,7 @@ struct TCCState {
|
||||
#define VT_BITFIELD 0x0040 /* bitfield modifier */
|
||||
#define VT_CONSTANT 0x0800 /* const modifier */
|
||||
#define VT_VOLATILE 0x1000 /* volatile modifier */
|
||||
#define VT_SIGNED 0x2000 /* signed type */
|
||||
#define VT_DEFSIGN 0x2000 /* signed type */
|
||||
#define VT_VLA 0x00020000 /* VLA type (also has VT_PTR and VT_ARRAY) */
|
||||
|
||||
/* storage */
|
||||
@ -749,11 +787,19 @@ struct TCCState {
|
||||
#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */
|
||||
#define VT_EXPORT 0x00008000 /* win32: data exported from dll */
|
||||
#define VT_WEAK 0x00010000 /* weak symbol */
|
||||
#define VT_TLS 0x00040000 /* thread-local storage */
|
||||
#define VT_VIS_SHIFT 19 /* shift for symbol visibility, overlapping
|
||||
bitfield values, because bitfields never
|
||||
have linkage and hence never have
|
||||
visibility. */
|
||||
#define VT_VIS_SIZE 2 /* We have four visibilities. */
|
||||
#define VT_VIS_MASK (((1 << VT_VIS_SIZE)-1) << VT_VIS_SHIFT)
|
||||
|
||||
#define VT_STRUCT_SHIFT 19 /* shift for bitfield shift values (max: 32 - 2*6) */
|
||||
|
||||
#define VT_STRUCT_SHIFT 18 /* shift for bitfield shift values (max: 32 - 2*6) */
|
||||
|
||||
/* type mask (except storage) */
|
||||
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK)
|
||||
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK | VT_VIS_MASK)
|
||||
#define VT_TYPE (~(VT_STORAGE))
|
||||
|
||||
/* token values */
|
||||
@ -774,35 +820,39 @@ struct TCCState {
|
||||
|
||||
#define TOK_LAND 0xa0
|
||||
#define TOK_LOR 0xa1
|
||||
|
||||
#define TOK_DEC 0xa2
|
||||
#define TOK_MID 0xa3 /* inc/dec, to void constant */
|
||||
#define TOK_INC 0xa4
|
||||
#define TOK_UDIV 0xb0 /* unsigned division */
|
||||
#define TOK_UMOD 0xb1 /* unsigned modulo */
|
||||
#define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
|
||||
#define TOK_CINT 0xb3 /* number in tokc */
|
||||
#define TOK_CCHAR 0xb4 /* char constant in tokc */
|
||||
#define TOK_STR 0xb5 /* pointer to string in tokc */
|
||||
#define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
|
||||
#define TOK_LCHAR 0xb7
|
||||
#define TOK_LSTR 0xb8
|
||||
#define TOK_CFLOAT 0xb9 /* float constant */
|
||||
#define TOK_LINENUM 0xba /* line number info */
|
||||
#define TOK_CDOUBLE 0xc0 /* double constant */
|
||||
#define TOK_CLDOUBLE 0xc1 /* long double constant */
|
||||
|
||||
/* tokens that carry values (in additional token string space / tokc) --> */
|
||||
#define TOK_CCHAR 0xb3 /* char constant in tokc */
|
||||
#define TOK_LCHAR 0xb4
|
||||
#define TOK_CINT 0xb5 /* number in tokc */
|
||||
#define TOK_CUINT 0xb6 /* unsigned int constant */
|
||||
#define TOK_CLLONG 0xb7 /* long long constant */
|
||||
#define TOK_CULLONG 0xb8 /* unsigned long long constant */
|
||||
#define TOK_STR 0xb9 /* pointer to string in tokc */
|
||||
#define TOK_LSTR 0xba
|
||||
#define TOK_CFLOAT 0xbb /* float constant */
|
||||
#define TOK_CDOUBLE 0xbc /* double constant */
|
||||
#define TOK_CLDOUBLE 0xbd /* long double constant */
|
||||
#define TOK_PPNUM 0xbe /* preprocessor number */
|
||||
#define TOK_LINENUM 0xbf /* line number info */
|
||||
/* <-- */
|
||||
|
||||
#define TOK_TWOSHARPS 0xc0 /* ## preprocessing token */
|
||||
#define TOK_PLCHLDR 0xc1 /* placeholder token as defined in C99 */
|
||||
#define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
|
||||
#define TOK_ADDC1 0xc3 /* add with carry generation */
|
||||
#define TOK_ADDC2 0xc4 /* add with carry use */
|
||||
#define TOK_SUBC1 0xc5 /* add with carry generation */
|
||||
#define TOK_SUBC2 0xc6 /* add with carry use */
|
||||
#define TOK_CUINT 0xc8 /* unsigned int constant */
|
||||
#define TOK_CLLONG 0xc9 /* long long constant */
|
||||
#define TOK_CULLONG 0xca /* unsigned long long constant */
|
||||
#define TOK_ARROW 0xcb
|
||||
#define TOK_DOTS 0xcc /* three dots */
|
||||
#define TOK_SHR 0xcd /* unsigned shift right */
|
||||
#define TOK_PPNUM 0xce /* preprocessor number */
|
||||
#define TOK_NOSUBST 0xcf /* means following token has already been pp'd */
|
||||
|
||||
#define TOK_SHL 0x01 /* shift left */
|
||||
@ -926,37 +976,6 @@ enum tcc_token {
|
||||
|
||||
#define TOK_UIDENT TOK_DEFINE
|
||||
|
||||
#ifdef _WIN32
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#ifndef __GNUC__
|
||||
# define strtold (long double)strtod
|
||||
# define strtof (float)strtod
|
||||
# define strtoll _strtoi64
|
||||
# define strtoull _strtoui64
|
||||
#endif
|
||||
#else
|
||||
/* XXX: need to define this to use them in non ISOC99 context */
|
||||
extern float strtof (const char *__nptr, char **__endptr);
|
||||
extern long double strtold (const char *__nptr, char **__endptr);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define IS_DIRSEP(c) (c == '/' || c == '\\')
|
||||
#define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2])))
|
||||
#define PATHCMP stricmp
|
||||
#else
|
||||
#define IS_DIRSEP(c) (c == '/')
|
||||
#define IS_ABSPATH(p) IS_DIRSEP(p[0])
|
||||
#define PATHCMP strcmp
|
||||
#endif
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
#define PATHSEP ';'
|
||||
#else
|
||||
#define PATHSEP ':'
|
||||
#endif
|
||||
|
||||
/* space exlcuding newline */
|
||||
static inline int is_space(int ch)
|
||||
{
|
||||
@ -1033,7 +1052,7 @@ PUB_FUNC char *tcc_strdup(const char *str);
|
||||
#define strdup(s) use_tcc_strdup(s)
|
||||
PUB_FUNC void tcc_memstats(void);
|
||||
PUB_FUNC void tcc_error_noabort(const char *fmt, ...);
|
||||
PUB_FUNC void tcc_error(const char *fmt, ...);
|
||||
PUB_FUNC NORETURN void tcc_error(const char *fmt, ...);
|
||||
PUB_FUNC void tcc_warning(const char *fmt, ...);
|
||||
|
||||
/* other utilities */
|
||||
@ -1131,7 +1150,7 @@ ST_FUNC void preprocess_init(TCCState *s1);
|
||||
ST_FUNC void preprocess_new(void);
|
||||
ST_FUNC int tcc_preprocess(TCCState *s1);
|
||||
ST_FUNC void skip(int c);
|
||||
ST_FUNC void expect(const char *msg);
|
||||
ST_FUNC NORETURN void expect(const char *msg);
|
||||
|
||||
/* ------------ tccgen.c ------------ */
|
||||
|
||||
@ -1169,6 +1188,7 @@ ST_DATA int const_wanted; /* true if constant wanted */
|
||||
ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */
|
||||
ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
|
||||
ST_DATA CType func_vt; /* current function return type (used by return instruction) */
|
||||
ST_DATA int func_var; /* true if current function is variadic */
|
||||
ST_DATA int func_vc;
|
||||
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
|
||||
ST_DATA char *funcname;
|
||||
@ -1250,6 +1270,7 @@ ST_FUNC void put_stabd(int type, int other, int desc);
|
||||
ST_FUNC void relocate_common_syms(void);
|
||||
ST_FUNC void relocate_syms(TCCState *s1, int do_resolve);
|
||||
ST_FUNC void relocate_section(TCCState *s1, Section *s);
|
||||
ST_FUNC void relocate_plt(TCCState *s1);
|
||||
|
||||
ST_FUNC void tcc_add_linker_symbols(TCCState *s1);
|
||||
ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
|
||||
@ -1260,7 +1281,7 @@ ST_FUNC void build_got_entries(TCCState *s1);
|
||||
ST_FUNC void tcc_add_runtime(TCCState *s1);
|
||||
|
||||
ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err);
|
||||
#ifdef TCC_IS_NATIVE
|
||||
#if defined TCC_IS_NATIVE || defined TCC_TARGET_PE
|
||||
ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name);
|
||||
#endif
|
||||
|
||||
@ -1281,7 +1302,7 @@ ST_FUNC void gsym_addr(int t, int a);
|
||||
ST_FUNC void gsym(int t);
|
||||
ST_FUNC void load(int r, SValue *sv);
|
||||
ST_FUNC void store(int r, SValue *v);
|
||||
ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *align);
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align);
|
||||
ST_FUNC void gfunc_call(int nb_args);
|
||||
ST_FUNC void gfunc_prolog(CType *func_type);
|
||||
ST_FUNC void gfunc_epilog(void);
|
||||
@ -1326,7 +1347,10 @@ ST_FUNC void gen_opl(int op);
|
||||
|
||||
/* ------------ arm-gen.c ------------ */
|
||||
#ifdef TCC_TARGET_ARM
|
||||
ST_FUNC void arm_init_types(void);
|
||||
#ifdef TCC_ARM_EABI
|
||||
ST_FUNC char *default_elfinterp(struct TCCState *s);
|
||||
#endif
|
||||
ST_FUNC void arm_init(struct TCCState *s);
|
||||
ST_FUNC uint32_t encbranch(int pos, int addr, int fail);
|
||||
ST_FUNC void gen_cvt_itof1(int t);
|
||||
#endif
|
||||
@ -1368,6 +1392,10 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
|
||||
#endif
|
||||
/* symbol properties stored in Elf32_Sym->st_other */
|
||||
# define ST_PE_EXPORT 0x10
|
||||
# define ST_PE_IMPORT 0x20
|
||||
# define ST_PE_STDCALL 0x40
|
||||
#endif
|
||||
|
||||
/* ------------ tccrun.c ----------------- */
|
||||
|
14
tccasm.c
14
tccasm.c
@ -232,7 +232,7 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
|
||||
} else {
|
||||
goto cannot_relocate;
|
||||
}
|
||||
pe->sym = NULL; /* same symbols can be substracted to NULL */
|
||||
pe->sym = NULL; /* same symbols can be subtracted to NULL */
|
||||
} else {
|
||||
cannot_relocate:
|
||||
tcc_error("invalid operation with label");
|
||||
@ -483,6 +483,7 @@ static void asm_parse_directive(TCCState *s1)
|
||||
case TOK_ASM_globl:
|
||||
case TOK_ASM_global:
|
||||
case TOK_ASM_weak:
|
||||
case TOK_ASM_hidden:
|
||||
tok1 = tok;
|
||||
do {
|
||||
Sym *sym;
|
||||
@ -493,9 +494,12 @@ static void asm_parse_directive(TCCState *s1)
|
||||
sym = label_push(&s1->asm_labels, tok, 0);
|
||||
sym->type.t = VT_VOID;
|
||||
}
|
||||
sym->type.t &= ~VT_STATIC;
|
||||
if (tok1 != TOK_ASM_hidden)
|
||||
sym->type.t &= ~VT_STATIC;
|
||||
if (tok1 == TOK_ASM_weak)
|
||||
sym->type.t |= VT_WEAK;
|
||||
else if (tok1 == TOK_ASM_hidden)
|
||||
sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT;
|
||||
next();
|
||||
} while (tok == ',');
|
||||
break;
|
||||
@ -588,12 +592,12 @@ static void asm_parse_directive(TCCState *s1)
|
||||
tcc_error("label not found: %s", get_tok_str(tok, NULL));
|
||||
}
|
||||
|
||||
next();
|
||||
skip(',');
|
||||
/* XXX .size name,label2-label1 */
|
||||
if (s1->warn_unsupported)
|
||||
tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL));
|
||||
|
||||
next();
|
||||
skip(',');
|
||||
while (tok != '\n' && tok != CH_EOF) {
|
||||
next();
|
||||
}
|
||||
@ -622,7 +626,7 @@ static void asm_parse_directive(TCCState *s1)
|
||||
}
|
||||
|
||||
if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
|
||||
sym->type.t = VT_FUNC;
|
||||
sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC;
|
||||
}
|
||||
else if (s1->warn_unsupported)
|
||||
tcc_warning("change type of '%s' from 0x%x to '%s' ignored",
|
||||
|
112
tccpe.c
112
tccpe.c
@ -363,7 +363,7 @@ struct pe_info {
|
||||
static const char *pe_export_name(TCCState *s1, ElfW(Sym) *sym)
|
||||
{
|
||||
const char *name = symtab_section->link->data + sym->st_name;
|
||||
if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & 2))
|
||||
if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL))
|
||||
return name + 1;
|
||||
return name;
|
||||
}
|
||||
@ -378,7 +378,7 @@ static int pe_find_import(TCCState * s1, ElfW(Sym) *sym)
|
||||
s = pe_export_name(s1, sym);
|
||||
if (n) {
|
||||
/* second try: */
|
||||
if (sym->st_other & 2) {
|
||||
if (sym->st_other & ST_PE_STDCALL) {
|
||||
/* try w/0 stdcall deco (windows API convention) */
|
||||
p = strrchr(s, '@');
|
||||
if (!p || s[0] != '_')
|
||||
@ -663,7 +663,7 @@ static int pe_write(struct pe_info *pe)
|
||||
}
|
||||
}
|
||||
|
||||
pstrcpy((char*)psh->Name, sizeof psh->Name, sh_name);
|
||||
strncpy((char*)psh->Name, sh_name, sizeof psh->Name);
|
||||
|
||||
psh->Characteristics = pe_sec_flags[si->cls];
|
||||
psh->VirtualAddress = addr;
|
||||
@ -819,27 +819,39 @@ static void pe_build_imports(struct pe_info *pe)
|
||||
ElfW(Sym) *imp_sym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
|
||||
ElfW(Sym) *org_sym = (ElfW(Sym) *)symtab_section->data + iat_index;
|
||||
const char *name = pe->s1->dynsymtab_section->link->data + imp_sym->st_name;
|
||||
int ordinal;
|
||||
|
||||
org_sym->st_value = thk_ptr;
|
||||
org_sym->st_shndx = pe->thunk->sh_num;
|
||||
v = pe->thunk->data_offset + rva_base;
|
||||
section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */
|
||||
put_elf_str(pe->thunk, name);
|
||||
|
||||
if (dllref)
|
||||
v = 0, ordinal = imp_sym->st_value; /* ordinal from pe_load_def */
|
||||
else
|
||||
ordinal = 0, v = imp_sym->st_value; /* address from tcc_add_symbol() */
|
||||
|
||||
#ifdef TCC_IS_NATIVE
|
||||
if (pe->type == PE_RUN) {
|
||||
v = imp_sym->st_value;
|
||||
if (dllref) {
|
||||
if ( !dllref->handle )
|
||||
dllref->handle = LoadLibrary(dllref->name);
|
||||
v = (ADDR3264)GetProcAddress(dllref->handle, name);
|
||||
v = (ADDR3264)GetProcAddress(dllref->handle, ordinal?(LPCSTR)NULL+ordinal:name);
|
||||
}
|
||||
if (!v)
|
||||
tcc_error_noabort("undefined symbol '%s'", name);
|
||||
}
|
||||
tcc_error_noabort("can't build symbol '%s'", name);
|
||||
} else
|
||||
#endif
|
||||
if (ordinal) {
|
||||
v = ordinal | (ADDR3264)1 << (sizeof(ADDR3264)*8 - 1);
|
||||
} else {
|
||||
v = pe->thunk->data_offset + rva_base;
|
||||
section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */
|
||||
put_elf_str(pe->thunk, name);
|
||||
}
|
||||
|
||||
} else {
|
||||
v = 0; /* last entry is zero */
|
||||
}
|
||||
|
||||
*(ADDR3264*)(pe->thunk->data+thk_ptr) =
|
||||
*(ADDR3264*)(pe->thunk->data+ent_ptr) = v;
|
||||
thk_ptr += sizeof (ADDR3264);
|
||||
@ -887,7 +899,7 @@ static void pe_build_exports(struct pe_info *pe)
|
||||
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
|
||||
sym = (ElfW(Sym)*)symtab_section->data + sym_index;
|
||||
name = pe_export_name(pe->s1, sym);
|
||||
if ((sym->st_other & 1)
|
||||
if ((sym->st_other & ST_PE_EXPORT)
|
||||
/* export only symbols from actually written sections */
|
||||
&& pe->s1->sections[sym->st_shndx]->sh_addr) {
|
||||
p = tcc_malloc(sizeof *p);
|
||||
@ -896,9 +908,9 @@ static void pe_build_exports(struct pe_info *pe)
|
||||
dynarray_add((void***)&sorted, &sym_count, p);
|
||||
}
|
||||
#if 0
|
||||
if (sym->st_other & 1)
|
||||
if (sym->st_other & ST_PE_EXPORT)
|
||||
printf("export: %s\n", name);
|
||||
if (sym->st_other & 2)
|
||||
if (sym->st_other & ST_PE_STDCALL)
|
||||
printf("stdcall: %s\n", name);
|
||||
#endif
|
||||
}
|
||||
@ -1270,7 +1282,7 @@ static int pe_check_symbols(struct pe_info *pe)
|
||||
/* patch the original symbol */
|
||||
sym->st_value = offset;
|
||||
sym->st_shndx = text_section->sh_num;
|
||||
sym->st_other &= ~1; /* do not export */
|
||||
sym->st_other &= ~ST_PE_EXPORT; /* do not export */
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1289,7 +1301,7 @@ static int pe_check_symbols(struct pe_info *pe)
|
||||
} else if (pe->s1->rdynamic
|
||||
&& ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
|
||||
/* if -rdynamic option, then export all non local symbols */
|
||||
sym->st_other |= 1;
|
||||
sym->st_other |= ST_PE_EXPORT;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@ -1451,7 +1463,7 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2)
|
||||
if (!sym->c)
|
||||
put_extern_sym(sym, NULL, 0, 0);
|
||||
esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
|
||||
if (!(esym->st_other & 4))
|
||||
if (!(esym->st_other & ST_PE_IMPORT))
|
||||
return sv;
|
||||
|
||||
// printf("import %04x %04x %04x %s\n", sv->type.t, sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL));
|
||||
@ -1571,30 +1583,20 @@ static char *trimback(char *a, char *e)
|
||||
return a;
|
||||
}
|
||||
|
||||
static char *get_line(char *line, int size, int fd)
|
||||
{
|
||||
int n;
|
||||
for (n = 0; n < size - 1; )
|
||||
if (read(fd, line + n, 1) < 1 || line[n++] == '\n')
|
||||
break;
|
||||
if (0 == n)
|
||||
return NULL;
|
||||
trimback(line, line + n);
|
||||
return trimfront(line);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
static int pe_load_def(TCCState *s1, int fd)
|
||||
{
|
||||
int state = 0, ret = -1, dllindex = 0;
|
||||
char line[400], dllname[80], *p;
|
||||
int state = 0, ret = -1, dllindex = 0, ord;
|
||||
char line[400], dllname[80], *p, *x;
|
||||
FILE *fp;
|
||||
|
||||
for (;;) {
|
||||
p = get_line(line, sizeof line, fd);
|
||||
if (NULL == p)
|
||||
break;
|
||||
fp = fdopen(dup(fd), "rb");
|
||||
while (fgets(line, sizeof line, fp))
|
||||
{
|
||||
p = trimfront(trimback(line, strchr(line, 0)));
|
||||
if (0 == *p || ';' == *p)
|
||||
continue;
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (0 != strnicmp(p, "LIBRARY", 7))
|
||||
@ -1612,14 +1614,27 @@ static int pe_load_def(TCCState *s1, int fd)
|
||||
case 2:
|
||||
dllindex = add_dllref(s1, dllname);
|
||||
++state;
|
||||
|
||||
/* fall through */
|
||||
default:
|
||||
pe_putimport(s1, dllindex, p, 0);
|
||||
/* get ordinal and will store in sym->st_value */
|
||||
ord = 0;
|
||||
x = strchr(p, ' ');
|
||||
if (x) {
|
||||
*x = 0, x = strrchr(x + 1, '@');
|
||||
if (x) {
|
||||
char *d;
|
||||
ord = (int)strtol(x + 1, &d, 10);
|
||||
if (*d)
|
||||
ord = 0;
|
||||
}
|
||||
}
|
||||
pe_putimport(s1, dllindex, p, ord);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
quit:
|
||||
fclose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1726,7 +1741,6 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
||||
static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
||||
{
|
||||
const char *start_symbol;
|
||||
ADDR3264 addr = 0;
|
||||
int pe_type = 0;
|
||||
|
||||
if (find_elf_sym(symtab_section, PE_STDSYM("WinMain","@16")))
|
||||
@ -1747,14 +1761,11 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
||||
: PE_GUI == pe_type ? "__winstart" : "__start"
|
||||
;
|
||||
|
||||
if (!s1->leading_underscore || strchr(start_symbol, '@')) {
|
||||
if (!s1->leading_underscore || strchr(start_symbol, '@'))
|
||||
++start_symbol;
|
||||
if (start_symbol[0] != '_')
|
||||
start_symbol = NULL;
|
||||
}
|
||||
|
||||
/* grab the startup code from libtcc1 */
|
||||
if (start_symbol)
|
||||
if (TCC_OUTPUT_MEMORY != s1->output_type || PE_GUI == pe_type)
|
||||
add_elf_sym(symtab_section,
|
||||
0, 0,
|
||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
||||
@ -1776,21 +1787,16 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
||||
}
|
||||
}
|
||||
|
||||
if (TCC_OUTPUT_MEMORY == s1->output_type)
|
||||
if (TCC_OUTPUT_MEMORY == s1->output_type) {
|
||||
pe_type = PE_RUN;
|
||||
|
||||
if (start_symbol) {
|
||||
addr = get_elf_sym_addr(s1, start_symbol, 1);
|
||||
if (PE_RUN == pe_type && addr)
|
||||
/* for -run GUI's, put '_runwinmain' instead of 'main' */
|
||||
add_elf_sym(symtab_section,
|
||||
addr, 0,
|
||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
||||
text_section->sh_num, "main");
|
||||
#ifdef TCC_IS_NATIVE
|
||||
s1->runtime_main = start_symbol;
|
||||
#endif
|
||||
} else {
|
||||
pe->start_addr = (DWORD)(uintptr_t)tcc_get_symbol_err(s1, start_symbol);
|
||||
}
|
||||
|
||||
pe->type = pe_type;
|
||||
pe->start_addr = addr;
|
||||
}
|
||||
|
||||
ST_FUNC int pe_output_file(TCCState * s1, const char *filename)
|
||||
|
472
tccpp.c
472
tccpp.c
@ -58,7 +58,6 @@ static const int *unget_saved_macro_ptr;
|
||||
static int unget_saved_buffer[TOK_MAX_SIZE + 1];
|
||||
static int unget_buffer_enabled;
|
||||
static TokenSym *hash_ident[TOK_HASH_SIZE];
|
||||
static char token_buf[STRING_MAX_SIZE + 1];
|
||||
/* true if isid(c) || isnum(c) */
|
||||
static unsigned char isidnum_table[256-CH_EOF];
|
||||
|
||||
@ -70,8 +69,33 @@ static const char tcc_keywords[] =
|
||||
|
||||
/* WARNING: the content of this string encodes token numbers */
|
||||
static const unsigned char tok_two_chars[] =
|
||||
/* outdated -- gr
|
||||
"<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253"
|
||||
"-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
|
||||
*/{
|
||||
'<','=', TOK_LE,
|
||||
'>','=', TOK_GE,
|
||||
'!','=', TOK_NE,
|
||||
'&','&', TOK_LAND,
|
||||
'|','|', TOK_LOR,
|
||||
'+','+', TOK_INC,
|
||||
'-','-', TOK_DEC,
|
||||
'=','=', TOK_EQ,
|
||||
'<','<', TOK_SHL,
|
||||
'>','>', TOK_SAR,
|
||||
'+','=', TOK_A_ADD,
|
||||
'-','=', TOK_A_SUB,
|
||||
'*','=', TOK_A_MUL,
|
||||
'/','=', TOK_A_DIV,
|
||||
'%','=', TOK_A_MOD,
|
||||
'&','=', TOK_A_AND,
|
||||
'^','=', TOK_A_XOR,
|
||||
'|','=', TOK_A_OR,
|
||||
'-','>', TOK_ARROW,
|
||||
'.','.', 0xa8, // C++ token ?
|
||||
'#','#', TOK_TWOSHARPS,
|
||||
0
|
||||
};
|
||||
|
||||
struct macro_level {
|
||||
struct macro_level *prev;
|
||||
@ -197,7 +221,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
|
||||
int i;
|
||||
|
||||
if (tok_ident >= SYM_FIRST_ANOM)
|
||||
tcc_error("memory full");
|
||||
tcc_error("memory full (symbols)");
|
||||
|
||||
/* expand token table if needed */
|
||||
i = tok_ident - TOK_IDENT;
|
||||
@ -264,6 +288,10 @@ ST_FUNC char *get_tok_str(int v, CValue *cv)
|
||||
cstr_buf.size_allocated = sizeof(buf);
|
||||
p = buf;
|
||||
|
||||
/* just an explanation, should never happen:
|
||||
if (v <= TOK_LINENUM && v >= TOK_CINT && cv == NULL)
|
||||
tcc_error("internal error: get_tok_str"); */
|
||||
|
||||
switch(v) {
|
||||
case TOK_CINT:
|
||||
case TOK_CUINT:
|
||||
@ -276,7 +304,7 @@ ST_FUNC char *get_tok_str(int v, CValue *cv)
|
||||
#ifdef _WIN32
|
||||
sprintf(p, "%u", (unsigned)cv->ull);
|
||||
#else
|
||||
sprintf(p, "%Lu", cv->ull);
|
||||
sprintf(p, "%llu", cv->ull);
|
||||
#endif
|
||||
break;
|
||||
case TOK_LCHAR:
|
||||
@ -311,6 +339,15 @@ ST_FUNC char *get_tok_str(int v, CValue *cv)
|
||||
cstr_ccat(&cstr_buf, '\"');
|
||||
cstr_ccat(&cstr_buf, '\0');
|
||||
break;
|
||||
|
||||
case TOK_CFLOAT:
|
||||
case TOK_CDOUBLE:
|
||||
case TOK_CLDOUBLE:
|
||||
case TOK_LINENUM:
|
||||
return NULL; /* should not happen */
|
||||
|
||||
/* above tokens have value, the ones below don't */
|
||||
|
||||
case TOK_LT:
|
||||
v = '<';
|
||||
goto addv;
|
||||
@ -1175,9 +1212,9 @@ static void tok_print(int *str)
|
||||
ST_FUNC void parse_define(void)
|
||||
{
|
||||
Sym *s, *first, **ps;
|
||||
int v, t, varg, is_vaargs, spc;
|
||||
int v, t, varg, is_vaargs, spc, ptok, macro_list_start;
|
||||
TokenString str;
|
||||
|
||||
|
||||
v = tok;
|
||||
if (v < TOK_IDENT)
|
||||
tcc_error("invalid macro name '%s'", get_tok_str(tok, &tokc));
|
||||
@ -1216,8 +1253,13 @@ ST_FUNC void parse_define(void)
|
||||
tok_str_new(&str);
|
||||
spc = 2;
|
||||
/* EOF testing necessary for '-D' handling */
|
||||
ptok = 0;
|
||||
macro_list_start = 1;
|
||||
while (tok != TOK_LINEFEED && tok != TOK_EOF) {
|
||||
/* remove spaces around ## and after '#' */
|
||||
if (!macro_list_start && spc == 2 && tok == TOK_TWOSHARPS)
|
||||
tcc_error("'##' invalid at start of macro");
|
||||
ptok = tok;
|
||||
/* remove spaces around ## and after '#' */
|
||||
if (TOK_TWOSHARPS == tok) {
|
||||
if (1 == spc)
|
||||
--str.len;
|
||||
@ -1230,7 +1272,10 @@ ST_FUNC void parse_define(void)
|
||||
tok_str_add2(&str, tok, &tokc);
|
||||
skip:
|
||||
next_nomacro_spc();
|
||||
macro_list_start = 0;
|
||||
}
|
||||
if (ptok == TOK_TWOSHARPS)
|
||||
tcc_error("'##' invalid at end of macro");
|
||||
if (spc == 1)
|
||||
--str.len; /* remove trailing space */
|
||||
tok_str_add(&str, 0);
|
||||
@ -1247,7 +1292,7 @@ static inline int hash_cached_include(const char *filename)
|
||||
unsigned int h;
|
||||
|
||||
h = TOK_HASH_INIT;
|
||||
s = filename;
|
||||
s = (unsigned char *) filename;
|
||||
while (*s) {
|
||||
h = TOK_HASH_FUNC(h, *s);
|
||||
s++;
|
||||
@ -1528,7 +1573,7 @@ include_done:
|
||||
c = (define_find(tok) != 0) ^ c;
|
||||
do_if:
|
||||
if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
|
||||
tcc_error("memory full");
|
||||
tcc_error("memory full (ifdef)");
|
||||
*s1->ifdef_stack_ptr++ = c;
|
||||
goto test_skip;
|
||||
case TOK_ELSE:
|
||||
@ -1744,261 +1789,156 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long
|
||||
cstr_wccat(outstr, '\0');
|
||||
}
|
||||
|
||||
/* we use 64 bit numbers */
|
||||
#define BN_SIZE 2
|
||||
|
||||
/* bn = (bn << shift) | or_val */
|
||||
static void bn_lshift(unsigned int *bn, int shift, int or_val)
|
||||
{
|
||||
int i;
|
||||
unsigned int v;
|
||||
for(i=0;i<BN_SIZE;i++) {
|
||||
v = bn[i];
|
||||
bn[i] = (v << shift) | or_val;
|
||||
or_val = v >> (32 - shift);
|
||||
}
|
||||
}
|
||||
|
||||
static void bn_zero(unsigned int *bn)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<BN_SIZE;i++) {
|
||||
bn[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* parse number in null terminated string 'p' and return it in the
|
||||
current token */
|
||||
static void parse_number(const char *p)
|
||||
{
|
||||
int b, t, shift, frac_bits, s, exp_val, ch;
|
||||
char *q;
|
||||
unsigned int bn[BN_SIZE];
|
||||
double d;
|
||||
int b, t, c;
|
||||
|
||||
/* number */
|
||||
q = token_buf;
|
||||
ch = *p++;
|
||||
t = ch;
|
||||
ch = *p++;
|
||||
*q++ = t;
|
||||
c = *p++;
|
||||
t = *p++;
|
||||
b = 10;
|
||||
if (t == '.') {
|
||||
goto float_frac_parse;
|
||||
} else if (t == '0') {
|
||||
if (ch == 'x' || ch == 'X') {
|
||||
q--;
|
||||
ch = *p++;
|
||||
if(c=='.'){
|
||||
--p;
|
||||
goto float_frac_parse;
|
||||
}
|
||||
if(c == '0'){
|
||||
if (t == 'x' || t == 'X') {
|
||||
b = 16;
|
||||
} else if (tcc_ext && (ch == 'b' || ch == 'B')) {
|
||||
q--;
|
||||
ch = *p++;
|
||||
c = *p++;
|
||||
} else if (tcc_ext && (t == 'b' || t == 'B')) {
|
||||
b = 2;
|
||||
}
|
||||
}
|
||||
/* parse all digits. cannot check octal numbers at this stage
|
||||
because of floating point constants */
|
||||
while (1) {
|
||||
if (ch >= 'a' && ch <= 'f')
|
||||
t = ch - 'a' + 10;
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
t = ch - 'A' + 10;
|
||||
else if (isnum(ch))
|
||||
t = ch - '0';
|
||||
else
|
||||
break;
|
||||
if (t >= b)
|
||||
break;
|
||||
if (q >= token_buf + STRING_MAX_SIZE) {
|
||||
num_too_long:
|
||||
tcc_error("number too long");
|
||||
}
|
||||
*q++ = ch;
|
||||
ch = *p++;
|
||||
}
|
||||
if (ch == '.' ||
|
||||
((ch == 'e' || ch == 'E') && b == 10) ||
|
||||
((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
|
||||
if (b != 10) {
|
||||
/* NOTE: strtox should support that for hexa numbers, but
|
||||
non ISOC99 libcs do not support it, so we prefer to do
|
||||
it by hand */
|
||||
/* hexadecimal or binary floats */
|
||||
/* XXX: handle overflows */
|
||||
*q = '\0';
|
||||
if (b == 16)
|
||||
shift = 4;
|
||||
else
|
||||
shift = 2;
|
||||
bn_zero(bn);
|
||||
q = token_buf;
|
||||
while (1) {
|
||||
t = *q++;
|
||||
if (t == '\0') {
|
||||
break;
|
||||
} else if (t >= 'a') {
|
||||
t = t - 'a' + 10;
|
||||
} else if (t >= 'A') {
|
||||
t = t - 'A' + 10;
|
||||
} else {
|
||||
t = t - '0';
|
||||
}
|
||||
bn_lshift(bn, shift, t);
|
||||
}
|
||||
frac_bits = 0;
|
||||
if (ch == '.') {
|
||||
ch = *p++;
|
||||
while (1) {
|
||||
t = ch;
|
||||
if (t >= 'a' && t <= 'f') {
|
||||
t = t - 'a' + 10;
|
||||
} else if (t >= 'A' && t <= 'F') {
|
||||
t = t - 'A' + 10;
|
||||
} else if (t >= '0' && t <= '9') {
|
||||
t = t - '0';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (t >= b)
|
||||
tcc_error("invalid digit");
|
||||
bn_lshift(bn, shift, t);
|
||||
frac_bits += shift;
|
||||
ch = *p++;
|
||||
}
|
||||
}
|
||||
if (ch != 'p' && ch != 'P')
|
||||
expect("exponent");
|
||||
ch = *p++;
|
||||
s = 1;
|
||||
exp_val = 0;
|
||||
if (ch == '+') {
|
||||
ch = *p++;
|
||||
} else if (ch == '-') {
|
||||
s = -1;
|
||||
ch = *p++;
|
||||
}
|
||||
if (ch < '0' || ch > '9')
|
||||
expect("exponent digits");
|
||||
while (ch >= '0' && ch <= '9') {
|
||||
exp_val = exp_val * 10 + ch - '0';
|
||||
ch = *p++;
|
||||
}
|
||||
exp_val = exp_val * s;
|
||||
|
||||
/* now we can generate the number */
|
||||
/* XXX: should patch directly float number */
|
||||
d = (double)bn[1] * 4294967296.0 + (double)bn[0];
|
||||
d = ldexp(d, exp_val - frac_bits);
|
||||
t = toup(ch);
|
||||
if (t == 'F') {
|
||||
ch = *p++;
|
||||
tok = TOK_CFLOAT;
|
||||
/* float : should handle overflow */
|
||||
tokc.f = (float)d;
|
||||
} else if (t == 'L') {
|
||||
ch = *p++;
|
||||
#ifdef TCC_TARGET_PE
|
||||
tok = TOK_CDOUBLE;
|
||||
tokc.d = d;
|
||||
#else
|
||||
tok = TOK_CLDOUBLE;
|
||||
/* XXX: not large enough */
|
||||
tokc.ld = (long double)d;
|
||||
#endif
|
||||
} else {
|
||||
tok = TOK_CDOUBLE;
|
||||
tokc.d = d;
|
||||
}
|
||||
} else {
|
||||
/* decimal floats */
|
||||
if (ch == '.') {
|
||||
if (q >= token_buf + STRING_MAX_SIZE)
|
||||
goto num_too_long;
|
||||
*q++ = ch;
|
||||
ch = *p++;
|
||||
float_frac_parse:
|
||||
while (ch >= '0' && ch <= '9') {
|
||||
if (q >= token_buf + STRING_MAX_SIZE)
|
||||
goto num_too_long;
|
||||
*q++ = ch;
|
||||
ch = *p++;
|
||||
}
|
||||
}
|
||||
if (ch == 'e' || ch == 'E') {
|
||||
if (q >= token_buf + STRING_MAX_SIZE)
|
||||
goto num_too_long;
|
||||
*q++ = ch;
|
||||
ch = *p++;
|
||||
if (ch == '-' || ch == '+') {
|
||||
if (q >= token_buf + STRING_MAX_SIZE)
|
||||
goto num_too_long;
|
||||
*q++ = ch;
|
||||
ch = *p++;
|
||||
}
|
||||
if (ch < '0' || ch > '9')
|
||||
expect("exponent digits");
|
||||
while (ch >= '0' && ch <= '9') {
|
||||
if (q >= token_buf + STRING_MAX_SIZE)
|
||||
goto num_too_long;
|
||||
*q++ = ch;
|
||||
ch = *p++;
|
||||
}
|
||||
}
|
||||
*q = '\0';
|
||||
t = toup(ch);
|
||||
errno = 0;
|
||||
if (t == 'F') {
|
||||
ch = *p++;
|
||||
tok = TOK_CFLOAT;
|
||||
tokc.f = strtof(token_buf, NULL);
|
||||
} else if (t == 'L') {
|
||||
ch = *p++;
|
||||
#ifdef TCC_TARGET_PE
|
||||
tok = TOK_CDOUBLE;
|
||||
tokc.d = strtod(token_buf, NULL);
|
||||
#else
|
||||
tok = TOK_CLDOUBLE;
|
||||
tokc.ld = strtold(token_buf, NULL);
|
||||
#endif
|
||||
} else {
|
||||
tok = TOK_CDOUBLE;
|
||||
tokc.d = strtod(token_buf, NULL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unsigned long long n, n1;
|
||||
int lcount, ucount;
|
||||
c = *p++;
|
||||
}else{
|
||||
--p;
|
||||
}
|
||||
}else
|
||||
--p;
|
||||
if(strchr(p , '.') || (b == 10 && (strchr(p,'e') || strchr(p,'E'))) ||
|
||||
((b == 2 || b == 16)&& (strchr(p,'p') || strchr(p,'P')))){
|
||||
long double ld, sh, fb;
|
||||
int exp;
|
||||
/* NOTE: strtox should support that for hexa numbers, but
|
||||
non ISOC99 libcs do not support it, so we prefer to do
|
||||
it by hand */
|
||||
/* hexadecimal or binary floats */
|
||||
/* XXX: handle overflows */
|
||||
float_frac_parse:
|
||||
fb = 1.0L/b;
|
||||
sh = b;
|
||||
ld = 0.0;
|
||||
|
||||
/* integer number */
|
||||
*q = '\0';
|
||||
q = token_buf;
|
||||
if (b == 10 && *q == '0') {
|
||||
while(1){
|
||||
if (c == '\0')
|
||||
break;
|
||||
if (c >= 'a' && c <= 'f')
|
||||
t = c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
t = c - 'A' + 10;
|
||||
else if(isnum(c))
|
||||
t = c - '0';
|
||||
else
|
||||
break;
|
||||
if (t >= b)
|
||||
tcc_error("invalid digit");
|
||||
ld = ld * b + t;
|
||||
c = *p++;
|
||||
}
|
||||
if (c == '.'){
|
||||
c = *p++;
|
||||
sh = fb;
|
||||
while (1){
|
||||
if (c == '\0')
|
||||
break;
|
||||
if (c >= 'a' && c <= 'f')
|
||||
t = c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
t = c - 'A' + 10;
|
||||
else if (isnum(c))
|
||||
t =c - '0';
|
||||
else
|
||||
break;
|
||||
if (t >= b){
|
||||
if(b == 10 && (c == 'e' || c == 'E' || c == 'f' || c == 'F'))
|
||||
break;
|
||||
tcc_error("invalid digit");
|
||||
}
|
||||
ld += sh*t;
|
||||
sh*=fb;
|
||||
c = *p++;
|
||||
}
|
||||
}
|
||||
if ((b == 16 || b == 2) && c != 'p' && c != 'P')
|
||||
expect("exponent");
|
||||
if(((c == 'e' || c == 'E') && b == 10) ||
|
||||
((c == 'p' || c == 'P') && (b == 16 || b == 2))){
|
||||
c = *p++;
|
||||
if(c == '+' || c == '-'){
|
||||
if (c == '-')
|
||||
sh = fb;
|
||||
c = *p++;
|
||||
}else
|
||||
sh = b;
|
||||
if (!isnum(c))
|
||||
expect("exponent digits");
|
||||
exp = 0;
|
||||
do{
|
||||
exp = exp * 10 + c - '0';
|
||||
c = *p++;
|
||||
}while(isnum(c));
|
||||
while (exp != 0){
|
||||
if (exp & 1)
|
||||
ld *= sh;
|
||||
exp >>= 1;
|
||||
sh *= sh;
|
||||
}
|
||||
}
|
||||
t = toup(c);
|
||||
if (t == 'F') {
|
||||
c = *p++;
|
||||
tok = TOK_CFLOAT;
|
||||
tokc.f = (float)ld;
|
||||
} else if (t == 'L') {
|
||||
c = *p++;
|
||||
#ifdef TCC_TARGET_PE
|
||||
tok = TOK_CDOUBLE;
|
||||
tokc.d = (double)ld;
|
||||
#else
|
||||
tok = TOK_CLDOUBLE;
|
||||
tokc.ld = ld;
|
||||
#endif
|
||||
} else {
|
||||
tok = TOK_CDOUBLE;
|
||||
tokc.d = (double)ld;
|
||||
}
|
||||
} else {
|
||||
uint64_t n = 0, n1;
|
||||
int warn = 1;
|
||||
int lcount, ucount;
|
||||
if (b == 10 && c == '0') {
|
||||
b = 8;
|
||||
q++;
|
||||
}
|
||||
n = 0;
|
||||
while(1) {
|
||||
t = *q++;
|
||||
/* no need for checks except for base 10 / 8 errors */
|
||||
if (t == '\0') {
|
||||
break;
|
||||
} else if (t >= 'a') {
|
||||
t = t - 'a' + 10;
|
||||
} else if (t >= 'A') {
|
||||
t = t - 'A' + 10;
|
||||
} else {
|
||||
t = t - '0';
|
||||
if (t >= b)
|
||||
tcc_error("invalid digit");
|
||||
}
|
||||
n1 = n;
|
||||
n = n * b + t;
|
||||
/* detect overflow */
|
||||
/* XXX: this test is not reliable */
|
||||
if (n < n1)
|
||||
tcc_error("integer constant overflow");
|
||||
}
|
||||
|
||||
while(1){
|
||||
if (c == '\0')
|
||||
break;
|
||||
if (c >= 'a' && c <= 'f')
|
||||
t = c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
t = c - 'A' + 10;
|
||||
else if(isnum(c))
|
||||
t = c - '0';
|
||||
else
|
||||
break;
|
||||
if (t >= b)
|
||||
tcc_error("invalid digit");
|
||||
n1 = n;
|
||||
n = n * b + t;
|
||||
if (n < n1 && warn){
|
||||
tcc_warning("integer constant overflow");
|
||||
warn = 0;
|
||||
}
|
||||
c = *p++;
|
||||
}
|
||||
/* XXX: not exactly ANSI compliant */
|
||||
if ((n & 0xffffffff00000000LL) != 0) {
|
||||
if ((n >> 63) != 0)
|
||||
@ -2013,7 +1953,7 @@ static void parse_number(const char *p)
|
||||
lcount = 0;
|
||||
ucount = 0;
|
||||
for(;;) {
|
||||
t = toup(ch);
|
||||
t = toup(c);
|
||||
if (t == 'L') {
|
||||
if (lcount >= 2)
|
||||
tcc_error("three 'l's in integer constant");
|
||||
@ -2028,7 +1968,7 @@ static void parse_number(const char *p)
|
||||
#if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE
|
||||
}
|
||||
#endif
|
||||
ch = *p++;
|
||||
c = *p++;
|
||||
} else if (t == 'U') {
|
||||
if (ucount >= 1)
|
||||
tcc_error("two 'u's in integer constant");
|
||||
@ -2037,7 +1977,7 @@ static void parse_number(const char *p)
|
||||
tok = TOK_CUINT;
|
||||
else if (tok == TOK_CLLONG)
|
||||
tok = TOK_CULLONG;
|
||||
ch = *p++;
|
||||
c = *p++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -2047,7 +1987,7 @@ static void parse_number(const char *p)
|
||||
else
|
||||
tokc.ull = n;
|
||||
}
|
||||
if (ch)
|
||||
if (c)
|
||||
tcc_error("invalid number\n");
|
||||
}
|
||||
|
||||
@ -2222,7 +2162,7 @@ maybe_newline:
|
||||
goto token_found;
|
||||
pts = &(ts->hash_next);
|
||||
}
|
||||
ts = tok_alloc_new(pts, p1, len);
|
||||
ts = tok_alloc_new(pts, (char *) p1, len);
|
||||
token_found: ;
|
||||
} else {
|
||||
/* slower case */
|
||||
@ -2519,7 +2459,8 @@ ST_FUNC void next_nomacro(void)
|
||||
} while (is_space(tok));
|
||||
}
|
||||
|
||||
/* substitute args in macro_str and return allocated string */
|
||||
/* substitute arguments in replacement lists in macro_str by the values in
|
||||
args (field d) and return allocated string */
|
||||
static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
||||
{
|
||||
int last_tok, t, spc;
|
||||
@ -2576,7 +2517,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
||||
if (gnu_ext && s->type.t &&
|
||||
last_tok == TOK_TWOSHARPS &&
|
||||
str.len >= 2 && str.str[str.len - 2] == ',') {
|
||||
if (*st == 0) {
|
||||
if (*st == TOK_PLCHLDR) {
|
||||
/* suppress ',' '##' */
|
||||
str.len -= 2;
|
||||
} else {
|
||||
@ -2747,6 +2688,8 @@ static int macro_subst_tok(TokenString *tok_str,
|
||||
tok_str_add2(&str, tok, &tokc);
|
||||
next_nomacro_spc();
|
||||
}
|
||||
if (!str.len)
|
||||
tok_str_add(&str, TOK_PLCHLDR);
|
||||
str.len -= spc;
|
||||
tok_str_add(&str, 0);
|
||||
sa1 = sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, 0);
|
||||
@ -2839,9 +2782,11 @@ static inline int *macro_twosharps(const int *macro_str)
|
||||
TOK_GET(&t, &ptr, &cval);
|
||||
/* We concatenate the two tokens */
|
||||
cstr_new(&cstr);
|
||||
cstr_cat(&cstr, get_tok_str(tok, &tokc));
|
||||
if (tok != TOK_PLCHLDR)
|
||||
cstr_cat(&cstr, get_tok_str(tok, &tokc));
|
||||
n = cstr.size;
|
||||
cstr_cat(&cstr, get_tok_str(t, &cval));
|
||||
if (t != TOK_PLCHLDR || tok == TOK_PLCHLDR)
|
||||
cstr_cat(&cstr, get_tok_str(t, &cval));
|
||||
cstr_ccat(&cstr, '\0');
|
||||
|
||||
tcc_open_bf(tcc_state, ":paste:", cstr.size);
|
||||
@ -2858,8 +2803,11 @@ static inline int *macro_twosharps(const int *macro_str)
|
||||
cstr_free(&cstr);
|
||||
}
|
||||
}
|
||||
if (tok != TOK_NOSUBST)
|
||||
if (tok != TOK_NOSUBST) {
|
||||
tok_str_add2(¯o_str1, tok, &tokc);
|
||||
tok = ' ';
|
||||
start_of_nosubsts = -1;
|
||||
}
|
||||
tok_str_add2(¯o_str1, tok, &tokc);
|
||||
}
|
||||
tok_str_add(¯o_str1, 0);
|
||||
|
54
tccrun.c
54
tccrun.c
@ -97,7 +97,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
|
||||
return -1;
|
||||
|
||||
prog_main = tcc_get_symbol_err(s1, "main");
|
||||
prog_main = tcc_get_symbol_err(s1, s1->runtime_main);
|
||||
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
if (s1->do_debug) {
|
||||
@ -110,13 +110,30 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
if (s1->do_bounds_check) {
|
||||
void (*bound_init)(void);
|
||||
void (*bound_exit)(void);
|
||||
void (*bound_new_region)(void *p, unsigned long size);
|
||||
int (*bound_delete_region)(void *p);
|
||||
int i;
|
||||
|
||||
/* set error function */
|
||||
rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
|
||||
/* XXX: use .init section so that it also work in binary ? */
|
||||
bound_init = tcc_get_symbol_err(s1, "__bound_init");
|
||||
bound_exit = tcc_get_symbol_err(s1, "__bound_exit");
|
||||
bound_new_region = tcc_get_symbol_err(s1, "__bound_new_region");
|
||||
bound_delete_region = tcc_get_symbol_err(s1, "__bound_delete_region");
|
||||
bound_init();
|
||||
/* mark argv area as valid */
|
||||
bound_new_region(argv, argc*sizeof(argv[0]));
|
||||
for (i=0; i<argc; ++i)
|
||||
bound_new_region(argv[i], strlen(argv[i]));
|
||||
|
||||
ret = (*prog_main)(argc, argv);
|
||||
|
||||
/* unmark argv area */
|
||||
for (i=0; i<argc; ++i)
|
||||
bound_delete_region(argv[i]);
|
||||
bound_delete_region(argv);
|
||||
|
||||
bound_exit();
|
||||
} else
|
||||
#endif
|
||||
@ -163,14 +180,6 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
|
||||
if (s1->nb_errors)
|
||||
return -1;
|
||||
|
||||
#ifdef TCC_HAS_RUNTIME_PLTGOT
|
||||
s1->runtime_plt_and_got_offset = 0;
|
||||
s1->runtime_plt_and_got = (char *)(mem + offset);
|
||||
/* double the size of the buffer for got and plt entries
|
||||
XXX: calculate exact size for them? */
|
||||
offset *= 2;
|
||||
#endif
|
||||
|
||||
if (0 == mem)
|
||||
return offset;
|
||||
|
||||
@ -180,6 +189,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
|
||||
if (s->reloc)
|
||||
relocate_section(s1, s);
|
||||
}
|
||||
relocate_plt(s1);
|
||||
|
||||
for(i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
@ -197,11 +207,6 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
|
||||
set_pages_executable(ptr, length);
|
||||
}
|
||||
|
||||
#ifdef TCC_HAS_RUNTIME_PLTGOT
|
||||
set_pages_executable(s1->runtime_plt_and_got,
|
||||
s1->runtime_plt_and_got_offset);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
win64_add_function_table(s1);
|
||||
#endif
|
||||
@ -217,6 +222,7 @@ static void set_pages_executable(void *ptr, unsigned long length)
|
||||
unsigned long old_protect;
|
||||
VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
|
||||
#else
|
||||
extern void __clear_cache(char *beginning, char *end);
|
||||
#ifndef PAGESIZE
|
||||
# define PAGESIZE 4096
|
||||
#endif
|
||||
@ -254,7 +260,7 @@ static addr_t rt_printline(addr_t wanted_pc, const char *msg)
|
||||
if (stab_section) {
|
||||
stab_len = stab_section->data_offset;
|
||||
stab_sym = (Stab_Sym *)stab_section->data;
|
||||
stab_str = stabstr_section->data;
|
||||
stab_str = (char *) stabstr_section->data;
|
||||
}
|
||||
|
||||
func_name[0] = '\0';
|
||||
@ -347,7 +353,7 @@ no_stabs:
|
||||
if (wanted_pc >= sym->st_value &&
|
||||
wanted_pc < sym->st_value + sym->st_size) {
|
||||
pstrcpy(last_func_name, sizeof(last_func_name),
|
||||
strtab_section->data + sym->st_name);
|
||||
(char *) strtab_section->data + sym->st_name);
|
||||
func_addr = sym->st_value;
|
||||
goto found;
|
||||
}
|
||||
@ -480,10 +486,12 @@ static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
|
||||
if (level == 0) {
|
||||
#if defined(__APPLE__)
|
||||
*paddr = uc->uc_mcontext->__ss.__eip;
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||
*paddr = uc->uc_mcontext.mc_eip;
|
||||
#elif defined(__dietlibc__)
|
||||
*paddr = uc->uc_mcontext.eip;
|
||||
#elif defined(__NetBSD__)
|
||||
*paddr = uc->uc_mcontext.__gregs[_REG_EIP];
|
||||
#else
|
||||
*paddr = uc->uc_mcontext.gregs[REG_EIP];
|
||||
#endif
|
||||
@ -491,10 +499,12 @@ static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
|
||||
} else {
|
||||
#if defined(__APPLE__)
|
||||
fp = uc->uc_mcontext->__ss.__ebp;
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||
fp = uc->uc_mcontext.mc_ebp;
|
||||
#elif defined(__dietlibc__)
|
||||
fp = uc->uc_mcontext.ebp;
|
||||
#elif defined(__NetBSD__)
|
||||
fp = uc->uc_mcontext.__gregs[_REG_EBP];
|
||||
#else
|
||||
fp = uc->uc_mcontext.gregs[REG_EBP];
|
||||
#endif
|
||||
@ -522,8 +532,10 @@ static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
|
||||
/* XXX: only support linux */
|
||||
#if defined(__APPLE__)
|
||||
*paddr = uc->uc_mcontext->__ss.__rip;
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||
*paddr = uc->uc_mcontext.mc_rip;
|
||||
#elif defined(__NetBSD__)
|
||||
*paddr = uc->uc_mcontext.__gregs[_REG_RIP];
|
||||
#else
|
||||
*paddr = uc->uc_mcontext.gregs[REG_RIP];
|
||||
#endif
|
||||
@ -531,8 +543,10 @@ static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
|
||||
} else {
|
||||
#if defined(__APPLE__)
|
||||
fp = uc->uc_mcontext->__ss.__rbp;
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||
fp = uc->uc_mcontext.mc_rbp;
|
||||
#elif defined(__NetBSD__)
|
||||
fp = uc->uc_mcontext.__gregs[_REG_RBP];
|
||||
#else
|
||||
fp = uc->uc_mcontext.gregs[REG_RBP];
|
||||
#endif
|
||||
|
121
tcctok.h
121
tcctok.h
@ -121,6 +121,8 @@
|
||||
DEF(TOK_DLLIMPORT, "dllimport")
|
||||
DEF(TOK_NORETURN1, "noreturn")
|
||||
DEF(TOK_NORETURN2, "__noreturn__")
|
||||
DEF(TOK_VISIBILITY1, "visibility")
|
||||
DEF(TOK_VISIBILITY2, "__visibility__")
|
||||
DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
|
||||
DEF(TOK_builtin_constant_p, "__builtin_constant_p")
|
||||
DEF(TOK_builtin_frame_address, "__builtin_frame_address")
|
||||
@ -143,23 +145,34 @@
|
||||
#endif
|
||||
|
||||
/* builtin functions or variables */
|
||||
#ifdef TCC_ARM_EABI
|
||||
DEF(TOK_memcpy, "__aeabi_memcpy")
|
||||
DEF(TOK_memcpy4, "__aeabi_memcpy4")
|
||||
DEF(TOK_memcpy8, "__aeabi_memcpy8")
|
||||
DEF(TOK_memset, "__aeabi_memset")
|
||||
DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
|
||||
DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
|
||||
#else
|
||||
#ifndef TCC_ARM_EABI
|
||||
DEF(TOK_memcpy, "memcpy")
|
||||
DEF(TOK_memset, "memset")
|
||||
DEF(TOK___divdi3, "__divdi3")
|
||||
DEF(TOK___moddi3, "__moddi3")
|
||||
DEF(TOK___udivdi3, "__udivdi3")
|
||||
DEF(TOK___umoddi3, "__umoddi3")
|
||||
DEF(TOK___ashrdi3, "__ashrdi3")
|
||||
DEF(TOK___lshrdi3, "__lshrdi3")
|
||||
DEF(TOK___ashldi3, "__ashldi3")
|
||||
DEF(TOK___floatundisf, "__floatundisf")
|
||||
DEF(TOK___floatundidf, "__floatundidf")
|
||||
# ifndef TCC_ARM_VFP
|
||||
DEF(TOK___floatundixf, "__floatundixf")
|
||||
DEF(TOK___fixunsxfdi, "__fixunsxfdi")
|
||||
# endif
|
||||
DEF(TOK___fixunssfdi, "__fixunssfdi")
|
||||
DEF(TOK___fixunsdfdi, "__fixunsdfdi")
|
||||
#endif
|
||||
#if defined(TCC_TARGET_ARM)
|
||||
#ifdef TCC_ARM_EABI
|
||||
|
||||
#if defined TCC_TARGET_ARM
|
||||
# ifdef TCC_ARM_EABI
|
||||
DEF(TOK_memcpy, "__aeabi_memcpy")
|
||||
DEF(TOK_memcpy4, "__aeabi_memcpy4")
|
||||
DEF(TOK_memcpy8, "__aeabi_memcpy8")
|
||||
DEF(TOK_memset, "__aeabi_memset")
|
||||
DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
|
||||
DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
|
||||
DEF(TOK___aeabi_idivmod, "__aeabi_idivmod")
|
||||
DEF(TOK___aeabi_uidivmod, "__aeabi_uidivmod")
|
||||
DEF(TOK___divsi3, "__aeabi_idiv")
|
||||
@ -168,36 +181,6 @@
|
||||
DEF(TOK___floatdidf, "__aeabi_l2d")
|
||||
DEF(TOK___fixsfdi, "__aeabi_f2lz")
|
||||
DEF(TOK___fixdfdi, "__aeabi_d2lz")
|
||||
#else
|
||||
DEF(TOK___modsi3, "__modsi3")
|
||||
DEF(TOK___umodsi3, "__umodsi3")
|
||||
DEF(TOK___divsi3, "__divsi3")
|
||||
DEF(TOK___udivsi3, "__udivsi3")
|
||||
DEF(TOK___floatdisf, "__floatdisf")
|
||||
DEF(TOK___floatdidf, "__floatdidf")
|
||||
#ifndef TCC_ARM_VFP
|
||||
DEF(TOK___floatdixf, "__floatdixf")
|
||||
DEF(TOK___fixunssfsi, "__fixunssfsi")
|
||||
DEF(TOK___fixunsdfsi, "__fixunsdfsi")
|
||||
DEF(TOK___fixunsxfsi, "__fixunsxfsi")
|
||||
DEF(TOK___fixxfdi, "__fixxfdi")
|
||||
#endif
|
||||
DEF(TOK___fixsfdi, "__fixsfdi")
|
||||
DEF(TOK___fixdfdi, "__fixdfdi")
|
||||
#endif
|
||||
#elif defined(TCC_TARGET_C67)
|
||||
DEF(TOK__divi, "_divi")
|
||||
DEF(TOK__divu, "_divu")
|
||||
DEF(TOK__divf, "_divf")
|
||||
DEF(TOK__divd, "_divd")
|
||||
DEF(TOK__remi, "_remi")
|
||||
DEF(TOK__remu, "_remu")
|
||||
#endif
|
||||
#ifdef TCC_TARGET_I386
|
||||
DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
|
||||
DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
|
||||
#endif
|
||||
#ifdef TCC_ARM_EABI
|
||||
DEF(TOK___ashrdi3, "__aeabi_lasr")
|
||||
DEF(TOK___lshrdi3, "__aeabi_llsr")
|
||||
DEF(TOK___ashldi3, "__aeabi_llsl")
|
||||
@ -205,20 +188,45 @@
|
||||
DEF(TOK___floatundidf, "__aeabi_ul2d")
|
||||
DEF(TOK___fixunssfdi, "__aeabi_f2ulz")
|
||||
DEF(TOK___fixunsdfdi, "__aeabi_d2ulz")
|
||||
#else
|
||||
DEF(TOK___ashrdi3, "__ashrdi3")
|
||||
DEF(TOK___lshrdi3, "__lshrdi3")
|
||||
DEF(TOK___ashldi3, "__ashldi3")
|
||||
DEF(TOK___floatundisf, "__floatundisf")
|
||||
DEF(TOK___floatundidf, "__floatundidf")
|
||||
#ifndef TCC_ARM_VFP
|
||||
DEF(TOK___floatundixf, "__floatundixf")
|
||||
DEF(TOK___fixunsxfdi, "__fixunsxfdi")
|
||||
# else
|
||||
DEF(TOK___modsi3, "__modsi3")
|
||||
DEF(TOK___umodsi3, "__umodsi3")
|
||||
DEF(TOK___divsi3, "__divsi3")
|
||||
DEF(TOK___udivsi3, "__udivsi3")
|
||||
DEF(TOK___floatdisf, "__floatdisf")
|
||||
DEF(TOK___floatdidf, "__floatdidf")
|
||||
# ifndef TCC_ARM_VFP
|
||||
DEF(TOK___floatdixf, "__floatdixf")
|
||||
DEF(TOK___fixunssfsi, "__fixunssfsi")
|
||||
DEF(TOK___fixunsdfsi, "__fixunsdfsi")
|
||||
DEF(TOK___fixunsxfsi, "__fixunsxfsi")
|
||||
DEF(TOK___fixxfdi, "__fixxfdi")
|
||||
# endif
|
||||
DEF(TOK___fixsfdi, "__fixsfdi")
|
||||
DEF(TOK___fixdfdi, "__fixdfdi")
|
||||
# endif
|
||||
#endif
|
||||
DEF(TOK___fixunssfdi, "__fixunssfdi")
|
||||
DEF(TOK___fixunsdfdi, "__fixunsdfdi")
|
||||
|
||||
#if defined TCC_TARGET_C67
|
||||
DEF(TOK__divi, "_divi")
|
||||
DEF(TOK__divu, "_divu")
|
||||
DEF(TOK__divf, "_divf")
|
||||
DEF(TOK__divd, "_divd")
|
||||
DEF(TOK__remi, "_remi")
|
||||
DEF(TOK__remu, "_remu")
|
||||
#endif
|
||||
#ifdef TCC_TARGET_PE
|
||||
|
||||
#if defined TCC_TARGET_I386
|
||||
DEF(TOK___fixsfdi, "__fixsfdi")
|
||||
DEF(TOK___fixdfdi, "__fixdfdi")
|
||||
DEF(TOK___fixxfdi, "__fixxfdi")
|
||||
#endif
|
||||
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
DEF(TOK_alloca, "alloca")
|
||||
#endif
|
||||
|
||||
#if defined TCC_TARGET_PE
|
||||
DEF(TOK___chkstk, "__chkstk")
|
||||
#endif
|
||||
|
||||
@ -231,22 +239,20 @@
|
||||
DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
|
||||
DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
|
||||
DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
|
||||
DEF(TOK___bound_main_arg, "__bound_main_arg")
|
||||
DEF(TOK___bound_local_new, "__bound_local_new")
|
||||
DEF(TOK___bound_local_delete, "__bound_local_delete")
|
||||
#ifdef TCC_TARGET_PE
|
||||
# ifdef TCC_TARGET_PE
|
||||
DEF(TOK_malloc, "malloc")
|
||||
DEF(TOK_free, "free")
|
||||
DEF(TOK_realloc, "realloc")
|
||||
DEF(TOK_memalign, "memalign")
|
||||
DEF(TOK_calloc, "calloc")
|
||||
#endif
|
||||
# endif
|
||||
DEF(TOK_memmove, "memmove")
|
||||
DEF(TOK_strlen, "strlen")
|
||||
DEF(TOK_strcpy, "strcpy")
|
||||
#endif
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
DEF(TOK_alloca, "alloca")
|
||||
#endif
|
||||
|
||||
/* Tiny Assembler */
|
||||
DEF_ASM(byte)
|
||||
@ -260,6 +266,7 @@
|
||||
DEF_ASM(file)
|
||||
DEF_ASM(globl)
|
||||
DEF_ASM(global)
|
||||
DEF_ASM(hidden)
|
||||
DEF_ASM(ident)
|
||||
DEF_ASM(size)
|
||||
DEF_ASM(type)
|
||||
|
@ -5,7 +5,7 @@
|
||||
TOP = ..
|
||||
include $(TOP)/Makefile
|
||||
SRCDIR = $(top_srcdir)/tests
|
||||
VPATH = $(SRCDIR)
|
||||
VPATH = $(SRCDIR) $(top_srcdir)
|
||||
|
||||
# what tests to run
|
||||
TESTS = \
|
||||
@ -13,24 +13,30 @@ TESTS = \
|
||||
hello-run \
|
||||
libtest \
|
||||
test3 \
|
||||
$(BTESTS) \
|
||||
abitest \
|
||||
vla_test-run \
|
||||
moretests
|
||||
|
||||
BTESTS = test1b test3b btest
|
||||
|
||||
ifdef CONFIG_CROSS
|
||||
TESTS += hello-cross
|
||||
endif
|
||||
|
||||
# test4 -- problem with -static
|
||||
# asmtest -- minor differences with gcc
|
||||
# btest -- works on i386 (including win32)
|
||||
# test3 -- win32 does not know how to printf long doubles
|
||||
|
||||
# bounds-checking is supported only on i386
|
||||
ifneq ($(ARCH),i386)
|
||||
TESTS := $(filter-out btest,$(TESTS))
|
||||
TESTS := $(filter-out $(BTESTS),$(TESTS))
|
||||
endif
|
||||
ifdef CONFIG_WIN32
|
||||
TESTS := $(filter-out test3,$(TESTS))
|
||||
TESTS := w32-prep $(filter-out $(BTESTS),$(TESTS))
|
||||
endif
|
||||
ifeq ($(TARGETOS),Darwin)
|
||||
TESTS := $(filter-out hello-exe test3 btest,$(TESTS))
|
||||
TESTS := $(filter-out hello-exe test3 $(BTESTS),$(TESTS))
|
||||
endif
|
||||
ifeq ($(ARCH),i386)
|
||||
else ifneq ($(ARCH),x86-64)
|
||||
@ -52,6 +58,7 @@ TCCFLAGS = -B$(TOP) -I$(TOP) -I$(top_srcdir) -I$(top_srcdir)/include
|
||||
ifdef CONFIG_WIN32
|
||||
TCCFLAGS = -B$(top_srcdir)/win32 -I$(top_srcdir) -I$(top_srcdir)/include -I$(TOP) -L$(TOP)
|
||||
endif
|
||||
XTCCFLAGS = -B$(TOP) -B$(top_srcdir)/win32 -I$(TOP) -I$(top_srcdir) -I$(top_srcdir)/include
|
||||
|
||||
TCC = $(TOP)/tcc $(TCCFLAGS)
|
||||
RUN_TCC = $(NATIVE_DEFINES) -DONE_SOURCE -run $(top_srcdir)/tcc.c $(TCCFLAGS)
|
||||
@ -69,6 +76,15 @@ hello-exe: ../examples/ex1.c
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) $< -o hello$(EXESUF) || ($(TOP)/tcc -vv; exit 1) && ./hello$(EXESUF)
|
||||
|
||||
hello-cross: ../examples/ex1.c
|
||||
@echo ------------ $@ ------------
|
||||
for XTCC in $(PROGS_CROSS) ; \
|
||||
do echo -n "Test of $$XTCC... "; \
|
||||
out=$$($(TOP)/$$XTCC $(XTCCFLAGS) -c $< 2>&1); \
|
||||
test $$? -ne 0 && { echo "Failed\n$$out\n" ; $(TOP)/$$XTCC -vv; exit 1; } ; \
|
||||
echo "Success"; \
|
||||
done
|
||||
|
||||
hello-run: ../examples/ex1.c
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) -run $<
|
||||
@ -84,48 +100,52 @@ moretests:
|
||||
@echo ------------ $@ ------------
|
||||
$(MAKE) -C tests2
|
||||
|
||||
# test.ref - generate using gcc
|
||||
# copy only tcclib.h so GCC's stddef and stdarg will be used
|
||||
w32-prep:
|
||||
cp ../libtcc1.a ../lib
|
||||
|
||||
# test.ref - generate using cc
|
||||
test.ref: tcctest.c
|
||||
gcc -o tcctest.gcc $< -I$(top_srcdir) $(CPPFLAGS) -w $(CFLAGS) $(NATIVE_DEFINES) -std=gnu99 -O0 -fno-omit-frame-pointer $(LDFLAGS)
|
||||
./tcctest.gcc > $@
|
||||
$(CC) -o tcctest.cc $< -I$(top_srcdir) $(CPPFLAGS) -w $(CFLAGS) $(NATIVE_DEFINES) -std=gnu99 -O0 -fno-omit-frame-pointer $(LDFLAGS)
|
||||
./tcctest.cc > $@
|
||||
|
||||
# auto test
|
||||
test1: test.ref
|
||||
test1 test1b: tcctest.c test.ref
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) -run $(SRCDIR)/tcctest.c > test.out1
|
||||
@if diff -u test.ref test.out1 ; then echo "Auto Test OK"; fi
|
||||
$(TCC) -run $< > test.out1
|
||||
@diff -u test.ref test.out1 && echo "Auto Test OK"
|
||||
|
||||
# iterated test2 (compile tcc then compile tcctest.c !)
|
||||
test2: test.ref
|
||||
test2 test2b: tcctest.c test.ref
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) $(RUN_TCC) $(RUN_TCC) -run $(SRCDIR)/tcctest.c > test.out2
|
||||
@if diff -u test.ref test.out2 ; then echo "Auto Test2 OK"; fi
|
||||
$(TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out2
|
||||
@diff -u test.ref test.out2 && echo "Auto Test2 OK"
|
||||
|
||||
# iterated test3 (compile tcc then compile tcc then compile tcctest.c !)
|
||||
test3: test.ref
|
||||
test3 test3b: tcctest.c test.ref
|
||||
@echo ------------ $@ ------------
|
||||
$(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $(SRCDIR)/tcctest.c > test.out3
|
||||
@if diff -u test.ref test.out3 ; then echo "Auto Test3 OK"; fi
|
||||
$(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out3
|
||||
@diff -u test.ref test.out3 && echo "Auto Test3 OK"
|
||||
|
||||
test%b : TCCFLAGS += -b
|
||||
|
||||
# binary output test
|
||||
test4: test.ref
|
||||
test4: tcctest.c test.ref
|
||||
@echo ------------ $@ ------------
|
||||
# object + link output
|
||||
$(TCC) -c -o tcctest3.o $(SRCDIR)/tcctest.c
|
||||
$(TCC) -c -o tcctest3.o $<
|
||||
$(TCC) -o tcctest3 tcctest3.o
|
||||
./tcctest3 > test3.out
|
||||
@if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi
|
||||
# dynamic output
|
||||
$(TCC) -o tcctest1 $(SRCDIR)/tcctest.c
|
||||
$(TCC) -o tcctest1 $<
|
||||
./tcctest1 > test1.out
|
||||
@if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi
|
||||
# dynamic output + bound check
|
||||
$(TCC) -b -o tcctest4 $(SRCDIR)/tcctest.c
|
||||
$(TCC) -b -o tcctest4 $<
|
||||
./tcctest4 > test4.out
|
||||
@if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi
|
||||
# static output
|
||||
$(TCC) -static -o tcctest2 $(SRCDIR)/tcctest.c
|
||||
$(TCC) -static -o tcctest2 $<
|
||||
./tcctest2 > test2.out
|
||||
@if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi
|
||||
|
||||
@ -137,15 +157,15 @@ btest: boundtest.c
|
||||
@echo ------------ $@ ------------
|
||||
@for i in $(BOUNDS_OK); do \
|
||||
echo ; echo --- boundtest $$i ---; \
|
||||
if $(TCC) -b -run boundtest.c $$i ; then \
|
||||
echo succeded as expected; \
|
||||
if $(TCC) -b -run $< $$i ; then \
|
||||
echo succeeded as expected; \
|
||||
else\
|
||||
echo Failed positive test $$i ; exit 1 ; \
|
||||
fi ;\
|
||||
done ;\
|
||||
for i in $(BOUNDS_FAIL); do \
|
||||
echo ; echo --- boundtest $$i ---; \
|
||||
if $(TCC) -b -run boundtest.c $$i ; then \
|
||||
if $(TCC) -b -run $< $$i ; then \
|
||||
echo Failed negative test $$i ; exit 1 ;\
|
||||
else\
|
||||
echo failed as expected; \
|
||||
@ -161,12 +181,12 @@ speedtest: ex2 ex3
|
||||
time ./ex3 35
|
||||
time $(TCC) -run $(top_srcdir)/examples/ex3.c 35
|
||||
|
||||
weaktest: test.ref
|
||||
$(TCC) -c tcctest.c -o weaktest.tcc.o $(CPPFLAGS) $(CFLAGS)
|
||||
$(CC) -c tcctest.c -o weaktest.gcc.o -I. $(CPPFLAGS) -w $(CFLAGS)
|
||||
weaktest: tcctest.c test.ref
|
||||
$(TCC) -c $< -o weaktest.tcc.o $(CPPFLAGS) $(CFLAGS)
|
||||
$(CC) -c $< -o weaktest.cc.o -I. $(CPPFLAGS) -w $(CFLAGS)
|
||||
objdump -t weaktest.tcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.tcc.o.txt
|
||||
objdump -t weaktest.gcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.gcc.o.txt
|
||||
diff weaktest.gcc.o.txt weaktest.tcc.o.txt && echo "Weak Auto Test OK"
|
||||
objdump -t weaktest.cc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.cc.o.txt
|
||||
diff weaktest.cc.o.txt weaktest.tcc.o.txt && echo "Weak Auto Test OK"
|
||||
|
||||
ex%: $(top_srcdir)/examples/ex%.c
|
||||
$(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
||||
@ -187,8 +207,8 @@ asmtest: asmtest.ref
|
||||
abitest-cc$(EXESUF): abitest.c $(top_builddir)/$(LIBTCC)
|
||||
$(CC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(NATIVE_DEFINES) $(LIBS) $(LINK_LIBTCC) $(LDFLAGS) -I$(top_srcdir)
|
||||
|
||||
abitest-tcc$(EXESUF): abitest.c $(top_builddir)/$(LIBTCC)
|
||||
$(TCC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(NATIVE_DEFINES) $(LIBS) $(LINK_LIBTCC) $(LDFLAGS) -I$(top_srcdir)
|
||||
abitest-tcc$(EXESUF): abitest.c libtcc.c
|
||||
$(TCC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(NATIVE_DEFINES) -DONE_SOURCE $(LIBS) $(LDFLAGS) -I$(top_srcdir)
|
||||
|
||||
abitest: abitest-cc$(EXESUF) abitest-tcc$(EXESUF)
|
||||
@echo ------------ $@ ------------
|
||||
@ -219,8 +239,7 @@ cache: tcc_g
|
||||
# clean
|
||||
clean:
|
||||
$(MAKE) -C tests2 $@
|
||||
rm -vf *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.gcc *.exe \
|
||||
hello libtcc_test tcctest[1234] ex? tcc_g tcclib.h
|
||||
|
||||
Makefile: $(SRCDIR)/Makefile
|
||||
cp $< $@
|
||||
rm -vf *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.cc \
|
||||
*-cc *-tcc *.exe \
|
||||
hello libtcc_test vla_test tcctest[1234] ex? tcc_g tcclib.h \
|
||||
../lib/libtcc1.a
|
||||
|
@ -88,7 +88,7 @@ static int ret_2float_test_callback(void *ptr) {
|
||||
ret_2float_test_type a = {10, 35};
|
||||
ret_2float_test_type r;
|
||||
r = f(a);
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3) && (f(a).x == a.x*5) && (f(a).y == a.y*3)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int ret_2float_test(void) {
|
||||
@ -116,7 +116,7 @@ static int ret_2double_test_callback(void *ptr) {
|
||||
ret_2double_test_type a = {10, 35};
|
||||
ret_2double_test_type r;
|
||||
r = f(a);
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3) && (f(a).x == a.x*5) && (f(a).y == a.y*3)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int ret_2double_test(void) {
|
||||
@ -130,6 +130,50 @@ static int ret_2double_test(void) {
|
||||
return run_callback(src, ret_2double_test_callback);
|
||||
}
|
||||
|
||||
typedef struct ret_longdouble_test_type_s2 {LONG_DOUBLE x;} ret_longdouble_test_type;
|
||||
typedef ret_longdouble_test_type (*ret_longdouble_test_function_type) (ret_longdouble_test_type);
|
||||
|
||||
static int ret_longdouble_test_callback2(void *ptr) {
|
||||
ret_longdouble_test_function_type f = (ret_longdouble_test_function_type)ptr;
|
||||
ret_longdouble_test_type a = {10};
|
||||
ret_longdouble_test_type r;
|
||||
r = f(a);
|
||||
return ((r.x == a.x*5) && (f(a).x == a.x*5)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int ret_longdouble_test2(void) {
|
||||
const char *src =
|
||||
"typedef struct ret_longdouble_test_type_s2 {long double x;} ret_longdouble_test_type;"
|
||||
"ret_longdouble_test_type f(ret_longdouble_test_type a) {\n"
|
||||
" ret_longdouble_test_type r = {a.x*5};\n"
|
||||
" return r;\n"
|
||||
"}\n";
|
||||
|
||||
return run_callback(src, ret_longdouble_test_callback2);
|
||||
}
|
||||
|
||||
typedef struct ret_longlong_test_type_s2 {int x[4];} ret_longlong_test_type;
|
||||
typedef ret_longlong_test_type (*ret_longlong_test_function_type) (ret_longlong_test_type);
|
||||
|
||||
static int ret_longlong_test_callback2(void *ptr) {
|
||||
ret_longlong_test_function_type f = (ret_longlong_test_function_type)ptr;
|
||||
ret_longlong_test_type a = {{10,11,12,13}};
|
||||
ret_longlong_test_type r;
|
||||
r = f(a);
|
||||
return ((r.x[2] == a.x[2]*5) && (f(a).x[2] == a.x[2]*5)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int ret_longlong_test2(void) {
|
||||
const char *src =
|
||||
"typedef struct ret_longlong_test_type_s2 {int x[4];} ret_longlong_test_type;"
|
||||
"ret_longlong_test_type f(ret_longlong_test_type a) {\n"
|
||||
" ret_longlong_test_type r = {.x[2] = a.x[2]*5};\n"
|
||||
" return r;\n"
|
||||
"}\n";
|
||||
|
||||
return run_callback(src, ret_longlong_test_callback2);
|
||||
}
|
||||
|
||||
/*
|
||||
* reg_pack_test: return a small struct which should be packed into
|
||||
* registers (Win32) during return.
|
||||
@ -142,7 +186,7 @@ static int reg_pack_test_callback(void *ptr) {
|
||||
reg_pack_test_type a = {10, 35};
|
||||
reg_pack_test_type r;
|
||||
r = f(a);
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3) && (f(a).x == a.x*5) && (f(a).y == a.y*3)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int reg_pack_test(void) {
|
||||
@ -168,7 +212,7 @@ static int reg_pack_longlong_test_callback(void *ptr) {
|
||||
reg_pack_longlong_test_type a = {10, 35};
|
||||
reg_pack_longlong_test_type r;
|
||||
r = f(a);
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3)) ? 0 : -1;
|
||||
return ((r.x == a.x*5) && (r.y == a.y*3) && (f(a).x == a.x*5) && (f(a).y == a.y*3)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int reg_pack_longlong_test(void) {
|
||||
@ -248,7 +292,7 @@ static int two_member_union_test_callback(void *ptr) {
|
||||
two_member_union_test_type a, b;
|
||||
a.x = 34;
|
||||
b = f(a);
|
||||
return (b.x == a.x*2) ? 0 : -1;
|
||||
return ((b.x == a.x*2) && (f(a).x == a.x*2)) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int two_member_union_test(void) {
|
||||
@ -339,8 +383,8 @@ static int stdarg_test(void) {
|
||||
"#include <stdarg.h>\n"
|
||||
"typedef struct {long long a, b, c;} stdarg_test_struct_type;\n"
|
||||
"void f(int n_int, int n_float, int n_struct, ...) {\n"
|
||||
" int i, ti;\n"
|
||||
" double td;\n"
|
||||
" int i, ti = 0;\n"
|
||||
" double td = 0.0;\n"
|
||||
" stdarg_test_struct_type ts = {0,0,0}, tmp;\n"
|
||||
" va_list ap;\n"
|
||||
" va_start(ap, n_struct);\n"
|
||||
@ -441,6 +485,8 @@ int main(int argc, char **argv) {
|
||||
RUN_TEST(ret_longdouble_test);
|
||||
RUN_TEST(ret_2float_test);
|
||||
RUN_TEST(ret_2double_test);
|
||||
RUN_TEST(ret_longlong_test2);
|
||||
RUN_TEST(ret_longdouble_test2);
|
||||
RUN_TEST(reg_pack_test);
|
||||
RUN_TEST(reg_pack_longlong_test);
|
||||
RUN_TEST(sret_test);
|
||||
|
121
tests/tcctest.c
121
tests/tcctest.c
@ -59,6 +59,7 @@
|
||||
|
||||
#include "tcclib.h"
|
||||
|
||||
void intdiv_test();
|
||||
void string_test();
|
||||
void expr_test();
|
||||
void macro_test();
|
||||
@ -167,6 +168,71 @@ int qq(int x)
|
||||
#define wq_spin_lock spin_lock
|
||||
#define TEST2() wq_spin_lock(a)
|
||||
|
||||
#define UINT_MAX ((unsigned) -1)
|
||||
|
||||
void intdiv_test(void)
|
||||
{
|
||||
printf("18/21=%u\n", 18/21);
|
||||
printf("18%21=%u\n", 18%21);
|
||||
printf("41/21=%u\n", 41/21);
|
||||
printf("41%21=%u\n", 41%21);
|
||||
printf("42/21=%u\n", 42/21);
|
||||
printf("42%21=%u\n", 42%21);
|
||||
printf("43/21=%u\n", 43/21);
|
||||
printf("43%21=%u\n", 43%21);
|
||||
printf("126/21=%u\n", 126/21);
|
||||
printf("12%/21=%u\n", 126%21);
|
||||
printf("131/21=%u\n", 131/21);
|
||||
printf("131%21=%u\n", 131%21);
|
||||
printf("(UINT_MAX/2+3)/2=%u\n", (UINT_MAX/2+3)/2);
|
||||
printf("(UINT_MAX/2+3)%2=%u\n", (UINT_MAX/2+3)%2);
|
||||
|
||||
printf("18/-21=%u\n", 18/-21);
|
||||
printf("18%-21=%u\n", 18%-21);
|
||||
printf("41/-21=%u\n", 41/-21);
|
||||
printf("41%-21=%u\n", 41%-21);
|
||||
printf("42/-21=%u\n", 42/-21);
|
||||
printf("42%-21=%u\n", 42%-21);
|
||||
printf("43/-21=%u\n", 43/-21);
|
||||
printf("43%-21=%u\n", 43%-21);
|
||||
printf("126/-21=%u\n", 126/-21);
|
||||
printf("12%/-21=%u\n", 126%-21);
|
||||
printf("131/-21=%u\n", 131/-21);
|
||||
printf("131%-21=%u\n", 131%-21);
|
||||
printf("(UINT_MAX/2+3)/-2=%u\n", (UINT_MAX/2+3)/-2);
|
||||
printf("(UINT_MAX/2+3)%-2=%u\n", (UINT_MAX/2+3)%-2);
|
||||
|
||||
printf("-18/21=%u\n", -18/21);
|
||||
printf("-18%21=%u\n", -18%21);
|
||||
printf("-41/21=%u\n", -41/21);
|
||||
printf("-41%21=%u\n", -41%21);
|
||||
printf("-42/21=%u\n", -42/21);
|
||||
printf("-42%21=%u\n", -42%21);
|
||||
printf("-43/21=%u\n", -43/21);
|
||||
printf("-43%21=%u\n", -43%21);
|
||||
printf("-126/21=%u\n", -126/21);
|
||||
printf("-12%/21=%u\n", -126%21);
|
||||
printf("-131/21=%u\n", -131/21);
|
||||
printf("-131%21=%u\n", -131%21);
|
||||
printf("-(UINT_MAX/2+3)/2=%u\n", (0-(UINT_MAX/2+3))/2);
|
||||
printf("-(UINT_MAX/2+3)%2=%u\n", (0-(UINT_MAX/2+3))%2);
|
||||
|
||||
printf("-18/-21=%u\n", -18/-21);
|
||||
printf("-18%-21=%u\n", -18%-21);
|
||||
printf("-41/-21=%u\n", -41/-21);
|
||||
printf("-41%-21=%u\n", -41%-21);
|
||||
printf("-42/-21=%u\n", -42/-21);
|
||||
printf("-42%-21=%u\n", -42%-21);
|
||||
printf("-43/-21=%u\n", -43/-21);
|
||||
printf("-43%-21=%u\n", -43%-21);
|
||||
printf("-126/-21=%u\n", -126/-21);
|
||||
printf("-12%/-21=%u\n", -126%-21);
|
||||
printf("-131/-21=%u\n", -131/-21);
|
||||
printf("-131%-21=%u\n", -131%-21);
|
||||
printf("-(UINT_MAX/2+3)/-2=%u\n", (0-(UINT_MAX/2+3))/-2);
|
||||
printf("-(UINT_MAX/2+3)%-2=%u\n", (0-(UINT_MAX/2+3))%-2);
|
||||
}
|
||||
|
||||
void macro_test(void)
|
||||
{
|
||||
printf("macro:\n");
|
||||
@ -619,6 +685,7 @@ int main(int argc, char **argv)
|
||||
math_cmp_test();
|
||||
callsave_test();
|
||||
builtin_frame_address_test();
|
||||
intdiv_test();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1603,21 +1670,32 @@ void prefix ## fcast(type a)\
|
||||
double da;\
|
||||
LONG_DOUBLE la;\
|
||||
int ia;\
|
||||
long long llia;\
|
||||
unsigned int ua;\
|
||||
unsigned long long llua;\
|
||||
type b;\
|
||||
fa = a;\
|
||||
da = a;\
|
||||
la = a;\
|
||||
printf("ftof: %f %f %Lf\n", fa, da, la);\
|
||||
ia = (int)a;\
|
||||
llia = (long long)a;\
|
||||
a = (a >= 0) ? a : -a;\
|
||||
ua = (unsigned int)a;\
|
||||
printf("ftoi: %d %u\n", ia, ua);\
|
||||
llua = (unsigned long long)a;\
|
||||
printf("ftoi: %d %u %lld %llu\n", ia, ua, llia, llua);\
|
||||
ia = -1234;\
|
||||
ua = 0x81234500;\
|
||||
llia = -0x123456789012345LL;\
|
||||
llua = 0xf123456789012345LLU;\
|
||||
b = ia;\
|
||||
printf("itof: " fmt "\n", b);\
|
||||
b = ua;\
|
||||
printf("utof: " fmt "\n", b);\
|
||||
b = llia;\
|
||||
printf("lltof: " fmt "\n", b);\
|
||||
b = llua;\
|
||||
printf("ulltof: " fmt "\n", b);\
|
||||
}\
|
||||
\
|
||||
float prefix ## retf(type a) { return a; }\
|
||||
@ -1632,6 +1710,35 @@ void prefix ## call(void)\
|
||||
printf("strto%s: %f\n", #prefix, (double)strto ## prefix("1.2", NULL));\
|
||||
}\
|
||||
\
|
||||
void prefix ## signed_zeros(void) \
|
||||
{\
|
||||
type x = 0.0, y = -0.0, n, p;\
|
||||
if (x == y)\
|
||||
printf ("Test 1.0 / x != 1.0 / y returns %d (should be 1).\n",\
|
||||
1.0 / x != 1.0 / y);\
|
||||
else\
|
||||
printf ("x != y; this is wrong!\n");\
|
||||
\
|
||||
n = -x;\
|
||||
if (x == n)\
|
||||
printf ("Test 1.0 / x != 1.0 / -x returns %d (should be 1).\n",\
|
||||
1.0 / x != 1.0 / n);\
|
||||
else\
|
||||
printf ("x != -x; this is wrong!\n");\
|
||||
\
|
||||
p = +y;\
|
||||
if (x == p)\
|
||||
printf ("Test 1.0 / x != 1.0 / +y returns %d (should be 1).\n",\
|
||||
1.0 / x != 1.0 / p);\
|
||||
else\
|
||||
printf ("x != +y; this is wrong!\n");\
|
||||
p = -y;\
|
||||
if (x == p)\
|
||||
printf ("Test 1.0 / x != 1.0 / -y returns %d (should be 0).\n",\
|
||||
1.0 / x != 1.0 / p);\
|
||||
else\
|
||||
printf ("x != -y; this is wrong!\n");\
|
||||
}\
|
||||
void prefix ## test(void)\
|
||||
{\
|
||||
printf("testing '%s'\n", #typename);\
|
||||
@ -1641,6 +1748,7 @@ void prefix ## test(void)\
|
||||
prefix ## fcast(234.6);\
|
||||
prefix ## fcast(-2334.6);\
|
||||
prefix ## call();\
|
||||
prefix ## signed_zeros();\
|
||||
}
|
||||
|
||||
FTEST(f, float, float, "%f")
|
||||
@ -2113,7 +2221,7 @@ void old_style_function(void)
|
||||
|
||||
void alloca_test()
|
||||
{
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
#if defined __i386__ || defined __x86_64__ || defined __arm__
|
||||
char *p = alloca(16);
|
||||
strcpy(p,"123456789012345");
|
||||
printf("alloca: p is %s\n", p);
|
||||
@ -2146,7 +2254,7 @@ void c99_vla_test(int size1, int size2)
|
||||
printf("%s\n", (sizeof tab1 == size1 * size2 * 2 * sizeof(int)) ? "PASSED" : "FAILED");
|
||||
tab1_ptr = tab1;
|
||||
tab2_ptr = tab2;
|
||||
printf("Test C99 VLA 2 (ptrs substract): ");
|
||||
printf("Test C99 VLA 2 (ptrs subtract): ");
|
||||
printf("%s\n", (tab2 - tab1 == (tab2_ptr - tab1_ptr) / (sizeof(int) * 2)) ? "PASSED" : "FAILED");
|
||||
printf("Test C99 VLA 3 (ptr add): ");
|
||||
printf("%s\n", &tab1[5][1] == (tab1_ptr + (5 * 2 + 1) * sizeof(int)) ? "PASSED" : "FAILED");
|
||||
@ -2686,7 +2794,7 @@ double get100 () { return 100.0; }
|
||||
|
||||
void callsave_test(void)
|
||||
{
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
#if defined __i386__ || defined __x86_64__ || defined __arm__
|
||||
int i, s; double *d; double t;
|
||||
s = sizeof (double);
|
||||
printf ("callsavetest: %d\n", s);
|
||||
@ -2715,16 +2823,17 @@ void bfa2(ptrdiff_t str_offset)
|
||||
void bfa1(ptrdiff_t str_offset)
|
||||
{
|
||||
printf("bfa1: %s\n", (char *)__builtin_frame_address(1) + str_offset);
|
||||
#if defined(__arm__) && !defined(__GNUC__)
|
||||
bfa2(str_offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
void builtin_frame_address_test(void)
|
||||
{
|
||||
/* builtin_frame_address fails on ARM with gcc which make test3 fail */
|
||||
#ifndef __arm__
|
||||
char str[] = "__builtin_frame_address";
|
||||
char *fp0 = __builtin_frame_address(0);
|
||||
|
||||
printf("str: %s\n", str);
|
||||
bfa1(str-fp0);
|
||||
#endif
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ struct fred
|
||||
int natasha;
|
||||
};
|
||||
|
||||
void main()
|
||||
int main()
|
||||
{
|
||||
struct fred bloggs;
|
||||
|
||||
|
@ -68,7 +68,7 @@ void PrintAll()
|
||||
/* Returns the value moved (not used.) */
|
||||
int Move(int *source, int *dest)
|
||||
{
|
||||
int i,j;
|
||||
int i = 0, j = 0;
|
||||
|
||||
while (i<N && (source[i])==0) i++;
|
||||
while (j<N && (dest[j])==0) j++;
|
||||
|
@ -5,7 +5,7 @@ int main(int argc, char **argv)
|
||||
int Count;
|
||||
|
||||
printf("hello world %d\n", argc);
|
||||
for (Count = 0; Count < argc; Count++)
|
||||
for (Count = 1; Count < argc; Count++)
|
||||
printf("arg %d: %s\n", Count, argv[Count]);
|
||||
|
||||
return 0;
|
||||
|
@ -1,7 +1,6 @@
|
||||
hello world 6
|
||||
arg 0: 31_args.c
|
||||
arg 1: -
|
||||
arg 2: arg1
|
||||
arg 3: arg2
|
||||
arg 4: arg3
|
||||
arg 5: arg4
|
||||
arg 1: arg1
|
||||
arg 2: arg2
|
||||
arg 3: arg3
|
||||
arg 4: arg4
|
||||
arg 5: arg5
|
||||
|
@ -15,6 +15,7 @@
|
||||
* privileges were granted by DECUS.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* grep
|
||||
@ -25,14 +26,13 @@
|
||||
* See below for more information.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
char *documentation[] = {
|
||||
"grep searches a file for a given pattern. Execute by",
|
||||
" grep [flags] regular_expression file_list\n",
|
||||
"Flags are single characters preceeded by '-':",
|
||||
"Flags are single characters preceded by '-':",
|
||||
" -c Only a count of matching lines is printed",
|
||||
" -f Print file name for matching lines switch, see below",
|
||||
" -n Each line is preceeded by its line number",
|
||||
" -n Each line is preceded by its line number",
|
||||
" -v Only print non-matching lines\n",
|
||||
"The file_list is a list of files (wildcards are acceptable on RSX modes).",
|
||||
"\nThe file name is normally printed if there is a file given.",
|
||||
@ -54,10 +54,10 @@ char *patdoc[] = {
|
||||
"':n' \":n\" matches alphanumerics, \": \" matches spaces, tabs, and",
|
||||
"': ' other control characters, such as new-line.",
|
||||
"'*' An expression followed by an asterisk matches zero or more",
|
||||
" occurrances of that expression: \"fo*\" matches \"f\", \"fo\"",
|
||||
" occurrences of that expression: \"fo*\" matches \"f\", \"fo\"",
|
||||
" \"foo\", etc.",
|
||||
"'+' An expression followed by a plus sign matches one or more",
|
||||
" occurrances of that expression: \"fo+\" matches \"fo\", etc.",
|
||||
" occurrences of that expression: \"fo+\" matches \"fo\", etc.",
|
||||
"'-' An expression followed by a minus sign optionally matches",
|
||||
" the expression.",
|
||||
"'[]' A string enclosed in square brackets matches any character in",
|
||||
@ -70,7 +70,6 @@ char *patdoc[] = {
|
||||
" [a-z] matches alphabetics, while [z-a] never matches.",
|
||||
"The concatenation of regular expressions is a regular expression.",
|
||||
0};
|
||||
#endif
|
||||
|
||||
#define LMAX 512
|
||||
#define PMAX 256
|
||||
@ -97,6 +96,10 @@ char *pp, lbuf[LMAX], pbuf[PMAX];
|
||||
|
||||
char *cclass();
|
||||
char *pmatch();
|
||||
void store(int);
|
||||
void error(char *);
|
||||
void badpat(char *, char *, char *);
|
||||
int match(void);
|
||||
|
||||
|
||||
/*** Display a file name *******************************/
|
||||
@ -153,7 +156,7 @@ void compile(char *source)
|
||||
o == STAR ||
|
||||
o == PLUS ||
|
||||
o == MINUS)
|
||||
badpat("Illegal occurrance op.", source, s);
|
||||
badpat("Illegal occurrence op.", source, s);
|
||||
store(ENDPAT);
|
||||
store(ENDPAT);
|
||||
spp = pp; /* Save pattern end */
|
||||
@ -300,7 +303,7 @@ void badpat(char *message, char *source, char *stop)
|
||||
/* char *stop; // Pattern end */
|
||||
{
|
||||
fprintf(stderr, "-GREP-E-%s, pattern is\"%s\"\n", message, source);
|
||||
fprintf(stderr, "-GREP-E-Stopped at byte %d, '%c'\n",
|
||||
fprintf(stderr, "-GREP-E-Stopped at byte %ld, '%c'\n",
|
||||
stop-source, stop[-1]);
|
||||
error("?GREP-E-Bad pattern\n");
|
||||
}
|
||||
@ -338,7 +341,7 @@ void grep(FILE *fp, char *fn)
|
||||
}
|
||||
|
||||
/*** Match line (lbuf) with pattern (pbuf) return 1 if match ***/
|
||||
void match()
|
||||
int match()
|
||||
{
|
||||
char *l; /* Line pointer */
|
||||
|
||||
@ -368,7 +371,7 @@ char *pmatch(char *line, char *pattern)
|
||||
p = pattern;
|
||||
while ((op = *p++) != ENDPAT) {
|
||||
if (debug > 1)
|
||||
printf("byte[%d] = 0%o, '%c', op = 0%o\n",
|
||||
printf("byte[%ld] = 0%o, '%c', op = 0%o\n",
|
||||
l-line, *l, *l, op);
|
||||
switch(op) {
|
||||
|
||||
|
3
tests/tests2/46_grep.expect
Normal file
3
tests/tests2/46_grep.expect
Normal file
@ -0,0 +1,3 @@
|
||||
File 46_grep.c:
|
||||
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/
|
||||
|
1
tests/tests2/56_btype_excess-1.c
Normal file
1
tests/tests2/56_btype_excess-1.c
Normal file
@ -0,0 +1 @@
|
||||
struct A {} int i;
|
1
tests/tests2/56_btype_excess-1.expect
Normal file
1
tests/tests2/56_btype_excess-1.expect
Normal file
@ -0,0 +1 @@
|
||||
56_btype_excess-1.c:1: error: too many basic types
|
1
tests/tests2/57_btype_excess-2.c
Normal file
1
tests/tests2/57_btype_excess-2.c
Normal file
@ -0,0 +1 @@
|
||||
char int i;
|
1
tests/tests2/57_btype_excess-2.expect
Normal file
1
tests/tests2/57_btype_excess-2.expect
Normal file
@ -0,0 +1 @@
|
||||
57_btype_excess-2.c:1: error: too many basic types
|
9
tests/tests2/58_function_redefinition.c
Normal file
9
tests/tests2/58_function_redefinition.c
Normal file
@ -0,0 +1,9 @@
|
||||
int f(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int f(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
1
tests/tests2/58_function_redefinition.expect
Normal file
1
tests/tests2/58_function_redefinition.expect
Normal file
@ -0,0 +1 @@
|
||||
58_function_redefinition.c:7: error: redefinition of 'f'
|
1
tests/tests2/59_function_array.c
Normal file
1
tests/tests2/59_function_array.c
Normal file
@ -0,0 +1 @@
|
||||
int (*fct)[42](int x);
|
1
tests/tests2/59_function_array.expect
Normal file
1
tests/tests2/59_function_array.expect
Normal file
@ -0,0 +1 @@
|
||||
59_function_array.c:1: error: declaration of an array of functions
|
4
tests/tests2/60_enum_redefinition.c
Normal file
4
tests/tests2/60_enum_redefinition.c
Normal file
@ -0,0 +1,4 @@
|
||||
enum color {RED, GREEN, BLUE};
|
||||
enum color {R, G, B};
|
||||
|
||||
enum color c;
|
1
tests/tests2/60_enum_redefinition.expect
Normal file
1
tests/tests2/60_enum_redefinition.expect
Normal file
@ -0,0 +1 @@
|
||||
60_enum_redefinition.c:2: error: struct/union/enum already defined
|
1
tests/tests2/61_undefined_enum.c
Normal file
1
tests/tests2/61_undefined_enum.c
Normal file
@ -0,0 +1 @@
|
||||
enum rgb c = 42;
|
1
tests/tests2/61_undefined_enum.expect
Normal file
1
tests/tests2/61_undefined_enum.expect
Normal file
@ -0,0 +1 @@
|
||||
61_undefined_enum.c:1: error: unknown struct/union/enum
|
4
tests/tests2/62_enumerator_redefinition.c
Normal file
4
tests/tests2/62_enumerator_redefinition.c
Normal file
@ -0,0 +1,4 @@
|
||||
enum color {RED, GREEN, BLUE};
|
||||
enum rgb {RED, G, B};
|
||||
|
||||
enum color c = RED;
|
1
tests/tests2/62_enumerator_redefinition.expect
Normal file
1
tests/tests2/62_enumerator_redefinition.expect
Normal file
@ -0,0 +1 @@
|
||||
62_enumerator_redefinition.c:2: error: redefinition of enumerator 'RED'
|
14
tests/tests2/63_local_enumerator_redefinition.c
Normal file
14
tests/tests2/63_local_enumerator_redefinition.c
Normal file
@ -0,0 +1,14 @@
|
||||
enum {
|
||||
FOO,
|
||||
BAR
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
enum {
|
||||
FOO = 2,
|
||||
BAR
|
||||
};
|
||||
|
||||
return BAR - FOO;
|
||||
}
|
10
tests/tests2/64_macro_nesting.c
Normal file
10
tests/tests2/64_macro_nesting.c
Normal file
@ -0,0 +1,10 @@
|
||||
#define CAT2(a,b) a##b
|
||||
#define CAT(a,b) CAT2(a,b)
|
||||
#define AB(x) CAT(x,y)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int xy = 42;
|
||||
printf("%d\n", CAT(A,B)(x));
|
||||
return 0;
|
||||
}
|
1
tests/tests2/64_macro_nesting.expect
Normal file
1
tests/tests2/64_macro_nesting.expect
Normal file
@ -0,0 +1 @@
|
||||
42
|
2
tests/tests2/65_macro_concat_start.c
Normal file
2
tests/tests2/65_macro_concat_start.c
Normal file
@ -0,0 +1,2 @@
|
||||
#define paste(A,B) ##A B
|
||||
paste(x,y)
|
1
tests/tests2/65_macro_concat_start.expect
Normal file
1
tests/tests2/65_macro_concat_start.expect
Normal file
@ -0,0 +1 @@
|
||||
65_macro_concat_start.c:1: error: '##' invalid at start of macro
|
2
tests/tests2/66_macro_concat_end.c
Normal file
2
tests/tests2/66_macro_concat_end.c
Normal file
@ -0,0 +1,2 @@
|
||||
#define paste(A,B) A B##
|
||||
paste(x,y)
|
1
tests/tests2/66_macro_concat_end.expect
Normal file
1
tests/tests2/66_macro_concat_end.expect
Normal file
@ -0,0 +1 @@
|
||||
66_macro_concat_end.c:2: error: '##' invalid at end of macro
|
14
tests/tests2/67_macro_concat.c
Normal file
14
tests/tests2/67_macro_concat.c
Normal file
@ -0,0 +1,14 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#define P(A,B) A ## B ; bob
|
||||
#define Q(A,B) A ## B+
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int bob, jim = 21;
|
||||
bob = P(jim,) *= 2;
|
||||
printf("jim: %d, bob: %d\n", jim, bob);
|
||||
jim = 60 Q(+,)3;
|
||||
printf("jim: %d\n", jim);
|
||||
return 0;
|
||||
}
|
2
tests/tests2/67_macro_concat.expect
Normal file
2
tests/tests2/67_macro_concat.expect
Normal file
@ -0,0 +1,2 @@
|
||||
jim: 21, bob: 42
|
||||
jim: 63
|
@ -1,10 +1,10 @@
|
||||
TOP = ../..
|
||||
include $(TOP)/Makefile
|
||||
VPATH = $(top_srcdir)/tests/tests2
|
||||
|
||||
TCCFLAGS = -B$(TOP) -I$(top_srcdir)/include
|
||||
ifdef CONFIG_WIN32
|
||||
TCCFLAGS = -B$(top_srcdir)/win32 -I$(top_srcdir)/include -L$(TOP)
|
||||
else
|
||||
TCCFLAGS = -B$(TOP) -I$(top_srcdir)/include -lm
|
||||
endif
|
||||
|
||||
ifeq ($(TARGETOS),Darwin)
|
||||
@ -46,9 +46,11 @@ TESTS = \
|
||||
27_sizeof.test \
|
||||
28_strings.test \
|
||||
29_array_address.test \
|
||||
30_hanoi.test \
|
||||
31_args.test \
|
||||
32_led.test \
|
||||
33_ternary_op.test \
|
||||
34_array_assignment.test \
|
||||
35_sizeof.test \
|
||||
36_array_initialisers.test \
|
||||
37_sprintf.test \
|
||||
@ -60,6 +62,7 @@ TESTS = \
|
||||
43_void_param.test \
|
||||
44_scoped_declarations.test \
|
||||
45_empty_for.test \
|
||||
46_grep.test \
|
||||
47_switch_return.test \
|
||||
48_nested_break.test \
|
||||
49_bracket_evaluation.test \
|
||||
@ -67,35 +70,48 @@ TESTS = \
|
||||
51_static.test \
|
||||
52_unnamed_enum.test \
|
||||
54_goto.test \
|
||||
55_lshift_type.test
|
||||
55_lshift_type.test \
|
||||
56_btype_excess-1.test \
|
||||
57_btype_excess-2.test \
|
||||
58_function_redefinition.test \
|
||||
59_function_array.test \
|
||||
60_enum_redefinition.test \
|
||||
61_undefined_enum.test \
|
||||
62_enumerator_redefinition.test \
|
||||
63_local_enumerator_redefinition.test \
|
||||
64_macro_nesting.test \
|
||||
65_macro_concat_start.test \
|
||||
66_macro_concat_end.test \
|
||||
67_macro_concat.test
|
||||
|
||||
# 30_hanoi.test -- seg fault in the code, gcc as well
|
||||
# 34_array_assignment.test -- array assignment is not in C standard
|
||||
# 46_grep.test -- does not compile even with gcc
|
||||
|
||||
SKIP = 34_array_assignment.test
|
||||
|
||||
# some tests do not pass on all platforms, remove them for now
|
||||
ifeq ($(TARGETOS),Darwin)
|
||||
TESTS := $(filter-out 40_stdio.test,$(TESTS))
|
||||
SKIP += 40_stdio.test
|
||||
endif
|
||||
ifdef CONFIG_WIN32
|
||||
TESTS := $(filter-out 24_math_library.test 28_strings.test,$(TESTS))
|
||||
SKIP += 24_math_library.test # don't have round()
|
||||
SKIP += 28_strings.test # don't have r/index() / strings.h
|
||||
endif
|
||||
|
||||
# Some tests might need arguments
|
||||
ARGS =
|
||||
31_args.test : ARGS = arg1 arg2 arg3 arg4 arg5
|
||||
46_grep.test : ARGS = '[^* ]*[:a:d: ]+\:\*-/: $$' 46_grep.c
|
||||
|
||||
all test: $(filter-out $(SKIP),$(TESTS))
|
||||
|
||||
%.test: %.c %.expect
|
||||
@echo Test: $*...
|
||||
@if [ "x`echo $* | grep args`" != "x" ]; \
|
||||
then $(TCC) $< -norunsrc -run $(notdir $<) - arg1 arg2 arg3 arg4 >$*.output; \
|
||||
else $(TCC) -run $< >$*.output; \
|
||||
fi
|
||||
@if diff -bu $(<:.c=.expect) $*.output ; \
|
||||
then rm -f $*.output; \
|
||||
else exit 1; \
|
||||
fi
|
||||
|
||||
all test: $(TESTS)
|
||||
@$(TCC) -run $< $(ARGS) >$*.output 2>&1 || true
|
||||
@diff -bu $*.expect $*.output && rm -f $*.output
|
||||
|
||||
@($(TCC) $< -o $*.exe && ./$*.exe $(ARGS)) >$*.output2 2>&1 || true
|
||||
@diff -bu $*.expect $*.output2 && rm -f $*.output2 $*.exe
|
||||
|
||||
clean:
|
||||
rm -vf fred.txt *.output
|
||||
|
||||
Makefile: $(top_srcdir)/tests/tests2/Makefile
|
||||
cp $< $@
|
||||
rm -vf fred.txt *.output* *.exe
|
||||
|
@ -5,7 +5,7 @@
|
||||
@set /p VERSION= < ..\VERSION
|
||||
echo>..\config.h #define TCC_VERSION "%VERSION%"
|
||||
|
||||
@if _%PROCESSOR_ARCHITEW6432%_==_AMD64_ goto x86_64
|
||||
@rem @if _%PROCESSOR_ARCHITEW6432%_==_AMD64_ goto x86_64
|
||||
@if _%PROCESSOR_ARCHITECTURE%_==_AMD64_ goto x86_64
|
||||
|
||||
@set target=-DTCC_TARGET_PE -DTCC_TARGET_I386
|
||||
@ -25,7 +25,7 @@ echo>..\config.h #define TCC_VERSION "%VERSION%"
|
||||
%CC% %target% tools/tiny_libmaker.c -o tiny_libmaker.exe
|
||||
|
||||
:libtcc
|
||||
if not exist libtcc\nul mkdir libtcc
|
||||
if not exist libtcc mkdir libtcc
|
||||
copy ..\libtcc.h libtcc\libtcc.h
|
||||
%CC% %target% -shared -DLIBTCC_AS_DLL -DONE_SOURCE ../libtcc.c -o libtcc.dll -Wl,-out-implib,libtcc/libtcc.a
|
||||
tiny_impdef libtcc.dll -o libtcc/libtcc.def
|
||||
@ -58,3 +58,10 @@ tiny_libmaker lib/libtcc1.a libtcc1.o alloca86_64.o crt1.o wincrt1.o dllcrt1.o d
|
||||
|
||||
:the_end
|
||||
del *.o
|
||||
|
||||
:makedoc
|
||||
echo>..\config.texi @set VERSION %VERSION%
|
||||
if not exist doc md doc
|
||||
makeinfo --html --no-split -o doc\tcc-doc.html ../tcc-doc.texi
|
||||
copy tcc-win32.txt doc
|
||||
copy ..\tests\libtcc_test.c examples
|
||||
|
@ -666,6 +666,7 @@ extern "C" {
|
||||
extern long double __cdecl fmal (long double, long double, long double);
|
||||
|
||||
|
||||
#if 0 // gr: duplicate, see below
|
||||
/* 7.12.14 */
|
||||
/*
|
||||
* With these functions, comparisons involving quiet NaNs set the FP
|
||||
@ -708,6 +709,7 @@ extern "C" {
|
||||
& 0x4500) == 0x4500)
|
||||
|
||||
#endif
|
||||
#endif //0
|
||||
|
||||
|
||||
#endif /* __STDC_VERSION__ >= 199901L */
|
||||
|
@ -153,20 +153,20 @@ extern "C" {
|
||||
stupid warnings, define them in POSIX way. This is save, because those
|
||||
methods do not return in success case, so that the return value is not
|
||||
really dependent to its scalar width. */
|
||||
int __cdecl execv(const char *_Filename,char *const _ArgList[]);
|
||||
int __cdecl execve(const char *_Filename,char *const _ArgList[],char *const _Env[]);
|
||||
int __cdecl execvp(const char *_Filename,char *const _ArgList[]);
|
||||
int __cdecl execvpe(const char *_Filename,char *const _ArgList[],char *const _Env[]);
|
||||
int __cdecl execv(const char *_Filename,const char *const _ArgList[]);
|
||||
int __cdecl execve(const char *_Filename,const char *const _ArgList[],const char *const _Env[]);
|
||||
int __cdecl execvp(const char *_Filename,const char *const _ArgList[]);
|
||||
int __cdecl execvpe(const char *_Filename,const char *const _ArgList[],const char *const _Env[]);
|
||||
#else
|
||||
intptr_t __cdecl execv(const char *_Filename,char *const _ArgList[]);
|
||||
intptr_t __cdecl execve(const char *_Filename,char *const _ArgList[],char *const _Env[]);
|
||||
intptr_t __cdecl execvp(const char *_Filename,char *const _ArgList[]);
|
||||
intptr_t __cdecl execvpe(const char *_Filename,char *const _ArgList[],char *const _Env[]);
|
||||
intptr_t __cdecl execv(const char *_Filename,const char *const _ArgList[]);
|
||||
intptr_t __cdecl execve(const char *_Filename,const char *const _ArgList[],const char *const _Env[]);
|
||||
intptr_t __cdecl execvp(const char *_Filename,const char *const _ArgList[]);
|
||||
intptr_t __cdecl execvpe(const char *_Filename,const char *const _ArgList[],const char *const _Env[]);
|
||||
#endif
|
||||
intptr_t __cdecl spawnv(int,const char *_Filename,char *const _ArgList[]);
|
||||
intptr_t __cdecl spawnve(int,const char *_Filename,char *const _ArgList[],char *const _Env[]);
|
||||
intptr_t __cdecl spawnvp(int,const char *_Filename,char *const _ArgList[]);
|
||||
intptr_t __cdecl spawnvpe(int,const char *_Filename,char *const _ArgList[],char *const _Env[]);
|
||||
intptr_t __cdecl spawnv(int,const char *_Filename,const char *const _ArgList[]);
|
||||
intptr_t __cdecl spawnve(int,const char *_Filename,const char *const _ArgList[],const char *const _Env[]);
|
||||
intptr_t __cdecl spawnvp(int,const char *_Filename,const char *const _ArgList[]);
|
||||
intptr_t __cdecl spawnvpe(int,const char *_Filename,const char *const _ArgList[],char *const _Env[]);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -968,15 +968,15 @@ extern "C" {
|
||||
LONG64 InterlockedExchangeAdd64(LONG64 volatile *Addend,LONG64 Value);
|
||||
LONG64 InterlockedCompareExchange64(LONG64 volatile *Destination,LONG64 ExChange,LONG64 Comperand);
|
||||
#else
|
||||
LONG InterlockedIncrement(LONG volatile *lpAddend);
|
||||
LONG InterlockedDecrement(LONG volatile *lpAddend);
|
||||
LONG InterlockedExchange(LONG volatile *Target,LONG Value);
|
||||
LONG WINAPI InterlockedIncrement(LONG volatile *lpAddend);
|
||||
LONG WINAPI InterlockedDecrement(LONG volatile *lpAddend);
|
||||
LONG WINAPI InterlockedExchange(LONG volatile *Target,LONG Value);
|
||||
|
||||
#define InterlockedExchangePointer(Target,Value) (PVOID)InterlockedExchange((PLONG)(Target),(LONG)(Value))
|
||||
|
||||
LONG InterlockedExchangeAdd(LONG volatile *Addend,LONG Value);
|
||||
LONG InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange,LONG Comperand);
|
||||
LONGLONG InterlockedCompareExchange64(LONGLONG volatile *Destination,LONGLONG Exchange,LONGLONG Comperand);
|
||||
LONG WINAPI InterlockedExchangeAdd(LONG volatile *Addend,LONG Value);
|
||||
LONG WINAPI InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange,LONG Comperand);
|
||||
LONGLONG WINAPI InterlockedCompareExchange64(LONGLONG volatile *Destination,LONGLONG Exchange,LONGLONG Comperand);
|
||||
|
||||
__CRT_INLINE LONGLONG InterlockedAnd64 (LONGLONG volatile *Destination,LONGLONG Value) {
|
||||
LONGLONG Old;
|
||||
|
@ -59,6 +59,6 @@ int _runwinmain(int argc, char **argv)
|
||||
szCmd = "";
|
||||
else if (szCmd > p && szCmd[-1] == '\"')
|
||||
--szCmd;
|
||||
_controlfp(0x10000, 0x30000);
|
||||
return WinMain(GetModuleHandle(NULL), NULL, szCmd, SW_SHOWDEFAULT);
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,12 @@
|
||||
system PATH.
|
||||
|
||||
|
||||
Include and library search paths
|
||||
--------------------------------
|
||||
On windows, the standard "include" and "lib" directories are searched
|
||||
relatively from the location of the executables (tcc.exe, libtcc.dll).
|
||||
|
||||
|
||||
Examples:
|
||||
---------
|
||||
Open a console window (DOS box) and 'cd' to the examples directory.
|
||||
|
@ -226,7 +226,7 @@ found:
|
||||
for (l = 0;;) {
|
||||
if (n+1 >= n0)
|
||||
p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
|
||||
if (!read_mem(fd, ptr - ref + l, p + n, 1) || ++l >= 80) {
|
||||
if (!read_mem(fd, ptr - ref + l++, p + n, 1)) {
|
||||
tcc_free(p), p = NULL;
|
||||
goto the_end;
|
||||
}
|
||||
|
@ -438,7 +438,7 @@ ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
|
||||
DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
|
||||
DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
|
||||
DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
|
||||
DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
|
||||
DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) /* must be last !OP0 */
|
||||
|
||||
#undef ALT
|
||||
#undef DEF_ASM_OP0
|
||||
|
104
x86_64-gen.c
104
x86_64-gen.c
@ -112,8 +112,8 @@ enum {
|
||||
#define R_JMP_SLOT R_X86_64_JUMP_SLOT
|
||||
#define R_COPY R_X86_64_COPY
|
||||
|
||||
#define ELF_START_ADDR 0x08048000
|
||||
#define ELF_PAGE_SIZE 0x1000
|
||||
#define ELF_START_ADDR 0x400000
|
||||
#define ELF_PAGE_SIZE 0x200000
|
||||
|
||||
/******************************************************/
|
||||
#else /* ! TARGET_DEFS_ONLY */
|
||||
@ -239,13 +239,6 @@ static int is64_type(int t)
|
||||
(t & VT_BTYPE) == VT_LLONG);
|
||||
}
|
||||
|
||||
static int is_sse_float(int t) {
|
||||
int bt;
|
||||
bt = t & VT_BTYPE;
|
||||
return bt == VT_DOUBLE || bt == VT_FLOAT;
|
||||
}
|
||||
|
||||
|
||||
/* instruction + 4 bytes data. Return the address of the data */
|
||||
ST_FUNC int oad(int c, int s)
|
||||
{
|
||||
@ -373,7 +366,7 @@ void load(int r, SValue *sv)
|
||||
#endif
|
||||
|
||||
fr = sv->r;
|
||||
ft = sv->type.t;
|
||||
ft = sv->type.t & ~VT_DEFSIGN;
|
||||
fc = sv->c.ul;
|
||||
|
||||
#ifndef TCC_TARGET_PE
|
||||
@ -508,7 +501,7 @@ void load(int r, SValue *sv)
|
||||
o(0xc0 + REG_VALUE(v) + REG_VALUE(r)*8);
|
||||
}
|
||||
} else if (r == TREG_ST0) {
|
||||
assert((v >= TREG_XMM0) || (v <= TREG_XMM7));
|
||||
assert((v >= TREG_XMM0) && (v <= TREG_XMM7));
|
||||
/* gen_cvt_ftof(VT_LDOUBLE); */
|
||||
/* movsd %xmmN,-0x10(%rsp) */
|
||||
o(0x110ff2);
|
||||
@ -611,7 +604,7 @@ static void gcall_or_jmp(int is_jmp)
|
||||
if (vtop->r & VT_SYM) {
|
||||
/* relocation case */
|
||||
greloc(cur_text_section, vtop->sym,
|
||||
ind + 1, R_X86_64_PC32);
|
||||
ind + 1, R_X86_64_PLT32);
|
||||
} else {
|
||||
/* put an empty PC32 relocation */
|
||||
put_elf_reloc(symtab_section, cur_text_section,
|
||||
@ -663,30 +656,37 @@ void gen_offs_sp(int b, int r, int d)
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 1 if this function returns via an sret pointer, 0 otherwise */
|
||||
ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align)
|
||||
/* Return the number of registers needed to return the struct, or 0 if
|
||||
returning via struct pointer. */
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align)
|
||||
{
|
||||
int size, align;
|
||||
*ret_align = 1; // Never have to re-align return values for x86-64
|
||||
size = type_size(vt, &align);
|
||||
ret->ref = NULL;
|
||||
if (size > 8) {
|
||||
return 1;
|
||||
return 0;
|
||||
} else if (size > 4) {
|
||||
ret->t = VT_LLONG;
|
||||
return 0;
|
||||
return 1;
|
||||
} else if (size > 2) {
|
||||
ret->t = VT_INT;
|
||||
return 0;
|
||||
return 1;
|
||||
} else if (size > 1) {
|
||||
ret->t = VT_SHORT;
|
||||
return 0;
|
||||
return 1;
|
||||
} else {
|
||||
ret->t = VT_BYTE;
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int is_sse_float(int t) {
|
||||
int bt;
|
||||
bt = t & VT_BTYPE;
|
||||
return bt == VT_DOUBLE || bt == VT_FLOAT;
|
||||
}
|
||||
|
||||
int gfunc_arg_size(CType *type) {
|
||||
int align;
|
||||
if (type->t & (VT_ARRAY|VT_BITFIELD))
|
||||
@ -833,6 +833,7 @@ void gfunc_prolog(CType *func_type)
|
||||
/* if the function returns a structure, then add an
|
||||
implicit pointer parameter */
|
||||
func_vt = sym->type;
|
||||
func_var = (sym->c == FUNC_ELLIPSIS);
|
||||
size = gfunc_arg_size(&func_vt);
|
||||
if (size > 8) {
|
||||
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
|
||||
@ -932,7 +933,8 @@ typedef enum X86_64_Mode {
|
||||
x86_64_mode_x87
|
||||
} X86_64_Mode;
|
||||
|
||||
static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) {
|
||||
static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b)
|
||||
{
|
||||
if (a == b)
|
||||
return a;
|
||||
else if (a == x86_64_mode_none)
|
||||
@ -949,7 +951,8 @@ static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) {
|
||||
return x86_64_mode_sse;
|
||||
}
|
||||
|
||||
static X86_64_Mode classify_x86_64_inner(CType *ty) {
|
||||
static X86_64_Mode classify_x86_64_inner(CType *ty)
|
||||
{
|
||||
X86_64_Mode mode;
|
||||
Sym *f;
|
||||
|
||||
@ -978,7 +981,7 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) {
|
||||
return x86_64_mode_memory;
|
||||
|
||||
mode = x86_64_mode_none;
|
||||
for (; f; f = f->next)
|
||||
for (f = f->next; f; f = f->next)
|
||||
mode = classify_x86_64_merge(mode, classify_x86_64_inner(&f->type));
|
||||
|
||||
return mode;
|
||||
@ -987,12 +990,14 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count) {
|
||||
static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count)
|
||||
{
|
||||
X86_64_Mode mode;
|
||||
int size, align, ret_t;
|
||||
int size, align, ret_t = 0;
|
||||
|
||||
if (ty->t & (VT_BITFIELD|VT_ARRAY)) {
|
||||
*psize = 8;
|
||||
*palign = 8;
|
||||
*reg_count = 1;
|
||||
ret_t = ty->t;
|
||||
mode = x86_64_mode_integer;
|
||||
@ -1030,6 +1035,7 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p
|
||||
ret_t = (size > 4) ? VT_DOUBLE : VT_FLOAT;
|
||||
}
|
||||
break;
|
||||
default: break; /* nothing to be done for x86_64_mode_memory and x86_64_mode_none*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1042,7 +1048,8 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p
|
||||
return mode;
|
||||
}
|
||||
|
||||
ST_FUNC int classify_x86_64_va_arg(CType *ty) {
|
||||
ST_FUNC int classify_x86_64_va_arg(CType *ty)
|
||||
{
|
||||
/* This definition must be synced with stdarg.h */
|
||||
enum __va_arg_type {
|
||||
__va_gen_reg, __va_float_reg, __va_stack
|
||||
@ -1056,11 +1063,13 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 1 if this function returns via an sret pointer, 0 otherwise */
|
||||
int gfunc_sret(CType *vt, CType *ret, int *ret_align) {
|
||||
/* Return the number of registers needed to return the struct, or 0 if
|
||||
returning via struct pointer. */
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align)
|
||||
{
|
||||
int size, align, reg_count;
|
||||
*ret_align = 1; // Never have to re-align return values for x86-64
|
||||
return (classify_x86_64_arg(vt, ret, &size, &align, ®_count) == x86_64_mode_memory);
|
||||
return (classify_x86_64_arg(vt, ret, &size, &align, ®_count) != x86_64_mode_memory);
|
||||
}
|
||||
|
||||
#define REGN 6
|
||||
@ -1083,7 +1092,7 @@ void gfunc_call(int nb_args)
|
||||
{
|
||||
X86_64_Mode mode;
|
||||
CType type;
|
||||
int size, align, r, args_size, stack_adjust, run_start, run_end, i, j, reg_count;
|
||||
int size, align, r, args_size, stack_adjust, run_start, run_end, i, reg_count;
|
||||
int nb_reg_args = 0;
|
||||
int nb_sse_args = 0;
|
||||
int sse_reg, gen_reg;
|
||||
@ -1133,6 +1142,7 @@ void gfunc_call(int nb_args)
|
||||
gen_reg -= reg_count;
|
||||
if (gen_reg + reg_count > REGN) goto stack_arg;
|
||||
break;
|
||||
default: break; /* nothing to be done for x86_64_mode_none */
|
||||
}
|
||||
}
|
||||
|
||||
@ -1262,7 +1272,7 @@ void gfunc_call(int nb_args)
|
||||
g(0x00);
|
||||
args_size += size;
|
||||
} else {
|
||||
assert(mode == x86_64_mode_memory);
|
||||
//assert(mode == x86_64_mode_memory);
|
||||
|
||||
/* allocate the necessary size on stack */
|
||||
o(0x48);
|
||||
@ -1366,7 +1376,7 @@ void gfunc_prolog(CType *func_type)
|
||||
{
|
||||
X86_64_Mode mode;
|
||||
int i, addr, align, size, reg_count;
|
||||
int param_addr, reg_param_index, sse_param_index;
|
||||
int param_addr = 0, reg_param_index, sse_param_index;
|
||||
Sym *sym;
|
||||
CType *type;
|
||||
|
||||
@ -1499,6 +1509,7 @@ void gfunc_prolog(CType *func_type)
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break; /* nothing to be done for x86_64_mode_none */
|
||||
}
|
||||
sym_push(sym->v & ~SYM_FIELD, type,
|
||||
VT_LOCAL | VT_LVAL, param_addr);
|
||||
@ -1577,7 +1588,7 @@ int gtst(int inv, int t)
|
||||
}
|
||||
g(0x0f);
|
||||
t = psym((vtop->c.i - 16) ^ inv, t);
|
||||
} else if (v == VT_JMP || v == VT_JMPI) {
|
||||
} else { /* VT_JMP || VT_JMPI */
|
||||
/* && or || optimization */
|
||||
if ((v & 1) == inv) {
|
||||
/* insert vtop->c jump list in t */
|
||||
@ -1590,23 +1601,6 @@ int gtst(int inv, int t)
|
||||
t = gjmp(t);
|
||||
gsym(vtop->c.i);
|
||||
}
|
||||
} else {
|
||||
if (is_float(vtop->type.t) ||
|
||||
(vtop->type.t & VT_BTYPE) == VT_LLONG) {
|
||||
vpushi(0);
|
||||
gen_op(TOK_NE);
|
||||
}
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
|
||||
/* constant jmp optimization */
|
||||
if ((vtop->c.i != 0) != inv)
|
||||
t = gjmp(t);
|
||||
} else {
|
||||
v = gv(RC_INT);
|
||||
orex(0,v,v,0x85);
|
||||
o(0xc0 + REG_VALUE(v) * 9);
|
||||
g(0x0f);
|
||||
t = psym(0x85 ^ inv, t);
|
||||
}
|
||||
}
|
||||
vtop--;
|
||||
return t;
|
||||
@ -1788,7 +1782,10 @@ void gen_opf(int op)
|
||||
swapped = 0;
|
||||
if (swapped)
|
||||
o(0xc9d9); /* fxch %st(1) */
|
||||
o(0xe9da); /* fucompp */
|
||||
if (op == TOK_EQ || op == TOK_NE)
|
||||
o(0xe9da); /* fucompp */
|
||||
else
|
||||
o(0xd9de); /* fcompp */
|
||||
o(0xe0df); /* fnstsw %ax */
|
||||
if (op == TOK_EQ) {
|
||||
o(0x45e480); /* and $0x45, %ah */
|
||||
@ -1872,8 +1869,11 @@ void gen_opf(int op)
|
||||
|
||||
if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
|
||||
o(0x66);
|
||||
o(0x2e0f); /* ucomisd */
|
||||
|
||||
if (op == TOK_EQ || op == TOK_NE)
|
||||
o(0x2e0f); /* ucomisd */
|
||||
else
|
||||
o(0x2f0f); /* comisd */
|
||||
|
||||
if (vtop->r & VT_LVAL) {
|
||||
gen_modrm(vtop[-1].r, r, vtop->sym, fc);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user