From 89ad24e7d63f7488c2796b30d41303f52663a8c4 Mon Sep 17 00:00:00 2001 From: gus knight Date: Wed, 29 Jul 2015 16:53:57 -0400 Subject: [PATCH] Revert all of my changes to directories & codingstyle. --- .gitignore | 4 +- CMakeLists.txt | 57 +- docs/Changelog => Changelog | 0 docs/CodingStyle.md => CodingStyle | 6 +- Makefile | 423 ++++- docs/TODO => TODO | 0 arm-gen.c | 2123 ++++++++++++++++++++++++ src/arm/arm64-gen.c => arm64-gen.c | 2 +- src/tms320c67/c67-gen.c => c67-gen.c | 116 +- src/coff.h => coff.h | 14 +- src/config.h.in => config.h.in | 0 docs/config.texi.in => config.texi.in | 0 configure | 10 +- src/conftest.c => conftest.c | 0 src/elf.h => elf.h | 0 src/x86/i386-asm.c => i386-asm.c | 4 +- src/x86/i386-asm.h => i386-asm.h | 10 +- src/x86/i386-gen.c => i386-gen.c | 26 +- src/x86/i386-tok.h => i386-tok.h | 0 src/cil/il-gen.c => il-gen.c | 14 +- src/cil/il-opcodes.h => il-opcodes.h | 2 +- lib/Makefile | 16 +- lib/bcheck.c | 56 +- lib/libtcc1.c | 26 +- src/libtcc.c => libtcc.c | 32 +- src/libtcc.h => libtcc.h | 0 src/Makefile | 421 ----- src/arm/arm-gen.c | 2162 ------------------------- src/tcccoff.c | 924 ----------- src/stab.def => stab.def | 0 src/stab.h => stab.h | 0 docs/tcc-doc.texi => tcc-doc.texi | 46 +- src/tcc.c => tcc.c | 2 +- src/tcc.h => tcc.h | 18 +- src/tccasm.c => tccasm.c | 104 +- tcccoff.c | 948 +++++++++++ src/tccelf.c => tccelf.c | 310 ++-- src/tccgen.c => tccgen.c | 565 +++---- src/tcclib.h => tcclib.h | 6 +- src/tccpe.c => tccpe.c | 50 +- src/tccpp.c => tccpp.c | 80 +- src/tccrun.c => tccrun.c | 18 +- src/tcctok.h => tcctok.h | 4 +- tests/Makefile | 10 +- tests/abitest.c | 30 +- tests/pp/Makefile | 2 +- tests/tcctest.c | 116 +- tests/tests2/Makefile | 6 +- docs/texi2pod.pl => texi2pod.pl | 2 +- win32/tools/tiny_libmaker.c | 2 +- src/x86/x86_64-asm.h => x86_64-asm.h | 0 src/x86/x86_64-gen.c => x86_64-gen.c | 132 +- 52 files changed, 4438 insertions(+), 4461 deletions(-) rename docs/Changelog => Changelog (100%) rename docs/CodingStyle.md => CodingStyle (57%) rename docs/TODO => TODO (100%) create mode 100644 arm-gen.c rename src/arm/arm64-gen.c => arm64-gen.c (99%) rename src/tms320c67/c67-gen.c => c67-gen.c (97%) rename src/coff.h => coff.h (99%) rename src/config.h.in => config.h.in (100%) rename docs/config.texi.in => config.texi.in (100%) rename src/conftest.c => conftest.c (100%) rename src/elf.h => elf.h (100%) rename src/x86/i386-asm.c => i386-asm.c (99%) rename src/x86/i386-asm.h => i386-asm.h (99%) rename src/x86/i386-gen.c => i386-gen.c (98%) rename src/x86/i386-tok.h => i386-tok.h (100%) rename src/cil/il-gen.c => il-gen.c (99%) rename src/cil/il-opcodes.h => il-opcodes.h (99%) rename src/libtcc.c => libtcc.c (99%) rename src/libtcc.h => libtcc.h (100%) delete mode 100644 src/Makefile delete mode 100644 src/arm/arm-gen.c delete mode 100644 src/tcccoff.c rename src/stab.def => stab.def (100%) rename src/stab.h => stab.h (100%) rename docs/tcc-doc.texi => tcc-doc.texi (98%) rename src/tcc.c => tcc.c (99%) rename src/tcc.h => tcc.h (99%) rename src/tccasm.c => tccasm.c (95%) create mode 100644 tcccoff.c rename src/tccelf.c => tccelf.c (93%) rename src/tccgen.c => tccgen.c (95%) rename src/tcclib.h => tcclib.h (96%) rename src/tccpe.c => tccpe.c (98%) rename src/tccpp.c => tccpp.c (99%) rename src/tccrun.c => tccrun.c (98%) rename src/tcctok.h => tcctok.h (99%) rename docs/texi2pod.pl => texi2pod.pl (99%) mode change 100644 => 100755 rename src/x86/x86_64-asm.h => x86_64-asm.h (100%) rename src/x86/x86_64-gen.c => x86_64-gen.c (97%) diff --git a/.gitignore b/.gitignore index 48f59c4..1aff332 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ a.out *.log tcc_g tcc -/src/*-tcc +/*-tcc tc2.c doc tc3s.c @@ -63,7 +63,7 @@ lib/i386-win32 lib/arm lib/arm64 tcc-doc.info -conftest*!conftest.c +conftest* tiny_libmaker *.dSYM *~ diff --git a/CMakeLists.txt b/CMakeLists.txt index 50a9f84..df3c831 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,14 +85,14 @@ endif() file(STRINGS "VERSION" TCC_VERSION) list(GET TCC_VERSION 0 TCC_VERSION) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/) -configure_file(src/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/src/config.h) -configure_file(docs/config.texi.in ${CMAKE_CURRENT_SOURCE_DIR}/docs/config.texi) +include_directories(${CMAKE_BINARY_DIR}) +configure_file(config.h.in config.h) +configure_file(config.texi.in config.texi) # Utility variables -set(I386_SOURCES src/x86/i386-gen.c src/x86/i386-asm.c src/x86/i386-asm.h src/x86/i386-tok.h) -set(X86_64_SOURCES src/x86/x86_64-gen.c src/x86/i386-asm.c src/x86/x86_64-asm.h) -set(ARM_SOURCES src/arm/arm_gen.c) +set(I386_SOURCES i386-gen.c i386-asm.c i386-asm.h i386-tok.h) +set(X86_64_SOURCES x86_64-gen.c i386-asm.c x86_64-asm.h) +set(ARM_SOURCES arm_gen.c) set(LIBTCC1_I386_SOURCES lib/alloca86.S lib/alloca86-bt.S) set(LIBTCC1_WIN_SOURCES win32/lib/crt1.c win32/lib/wincrt1.c win32/lib/dllcrt1.c win32/lib/dllmain.c win32/lib/chkstk.S) @@ -154,41 +154,41 @@ macro(make_tcc native_name cross_name cross_enabled definitions tcc_sources libt foreach(make_tcc_def ${TCC_NATIVE_DEFINITIONS}) set(TCC_NATIVE_FLAGS ${TCC_NATIVE_FLAGS} -D${make_tcc_def}) endforeach() - + if (TCC_BUILD_NATIVE) add_library(libtcc - src/libtcc.c - src/tccpp.c - src/tccgen.c - src/tccelf.c - src/tccasm.c - src/tccrun.c - src/tcc.h - src/libtcc.h - src/tcctok.h + libtcc.c + tccpp.c + tccgen.c + tccelf.c + tccasm.c + tccrun.c + tcc.h + libtcc.h + tcctok.h ${tcc_sources} ) set_target_properties(libtcc PROPERTIES OUTPUT_NAME tcc PREFIX lib) if(WIN32) set_target_properties(libtcc PROPERTIES LINK_FLAGS "-Wl,--output-def,libtcc.def") endif() - add_executable(tcc src/tcc.c) + add_executable(tcc tcc.c) target_link_libraries(tcc libtcc) if(NOT WIN32) target_link_libraries(tcc dl) endif() install(TARGETS tcc libtcc RUNTIME DESTINATION ${EXE_PATH} LIBRARY DESTINATION ${NATIVE_LIB_PATH} ARCHIVE DESTINATION ${NATIVE_LIB_PATH}) set_target_properties(tcc libtcc PROPERTIES COMPILE_DEFINITIONS "${TCC_NATIVE_DEFINITIONS}") - + if("${libtcc_sources}" STRGREATER "") make_libtcc1("" tcc "${libtcc_ar}" "${TCC_NATIVE_DEFINITIONS}" "${libtcc_includes}" "${libtcc_sources}") endif() endif() elseif(${cross_enabled}) - add_executable(${cross_name}-tcc src/tcc.c) + add_executable(${cross_name}-tcc tcc.c) set_target_properties(${cross_name}-tcc PROPERTIES COMPILE_DEFINITIONS "ONE_SOURCE;${definitions}") install(TARGETS ${cross_name}-tcc RUNTIME DESTINATION ${EXE_PATH}) - + if("${libtcc_sources}" STRGREATER "") make_libtcc1(${cross_name} "${cross_name}-tcc" "${libtcc_ar}" "${definitions}" "${libtcc_includes}" "${libtcc_sources}") endif() @@ -197,17 +197,17 @@ endmacro() make_tcc("Win32" i386-w64-mingw32 TCC_BUILD_WIN32 "TCC_TARGET_I386;TCC_TARGET_PE" - "${I386_SOURCES};src/tccpe.c" + "${I386_SOURCES};tccpe.c" tiny_libmaker_32 "${LIBTCC1_I386_SOURCES};${LIBTCC1_WIN_SOURCES}" "win32/include;win32/include/winapi" ) make_tcc("Win64" x86_64-w64-mingw32 TCC_BUILD_WIN64 "TCC_TARGET_X86_64;TCC_TARGET_PE" - "${X86_64_SOURCES};src/tccpe.c" + "${X86_64_SOURCES};tccpe.c" tiny_libmaker_64 "lib/alloca86_64.S;${LIBTCC1_WIN_SOURCES}" "win32/include;win32/include/winapi" ) make_tcc("WinCE" arm-wince-mingw32ce TCC_BUILD_WINCE "TCC_TARGET_ARM;TCC_ARM_VERSION=${TCC_ARM_VERSION};TCC_TARGET_PE" - "${ARM_SOURCES};src/tccpe.c" + "${ARM_SOURCES};tccpe.c" "" "" "" ) make_tcc("i386" i386-linux-gnu TCC_BUILD_I386 @@ -248,7 +248,7 @@ make_tcc("" arm-linux-gnu TCC_BUILD_ARM_VFP ) make_tcc("" c67 TCC_BUILD_C67 TCC_TARGET_C67 - "c67-gen.c;src/tcccoff.c" + "c67-gen.c;tcccoff.c" "" "" "" ) @@ -257,14 +257,14 @@ add_subdirectory(tests) find_program(MAKEINFO NAMES makeinfo PATHS C:/MinGW/MSYS/1.0/bin) if(MAKEINFO) add_custom_command(OUTPUT tcc-doc.html - COMMAND ${MAKEINFO} --no-split --html -o tcc-doc.html ${CMAKE_CURRENT_SOURCE_DIR}/docs/tcc-doc.texi - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/docs/tcc-doc.texi + COMMAND ${MAKEINFO} --no-split --html -o tcc-doc.html ${CMAKE_CURRENT_SOURCE_DIR}/tcc-doc.texi + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tcc-doc.texi ) set(TCC_DOC_FILES tcc-doc.html) if(NOT WIN32) add_custom_command(OUTPUT tcc-doc.info - COMMAND ${MAKEINFO} -o tcc-doc.info ${CMAKE_CURRENT_SOURCE_DIR}/docs/tcc-doc.texi - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/docs/tcc-doc.texi + COMMAND ${MAKEINFO} -o tcc-doc.info ${CMAKE_CURRENT_SOURCE_DIR}/tcc-doc.texi + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tcc-doc.texi ) set(TCC_DOC_FILES ${TCC_DOC_FILES} tcc-doc.info) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/tcc-doc.info DESTINATION share/info) @@ -290,3 +290,4 @@ else() install(DIRECTORY win32/include/ DESTINATION lib/tcc/win32/include) install(DIRECTORY include/ DESTINATION lib/tcc/win32/include) endif() + diff --git a/docs/Changelog b/Changelog similarity index 100% rename from docs/Changelog rename to Changelog diff --git a/docs/CodingStyle.md b/CodingStyle similarity index 57% rename from docs/CodingStyle.md rename to CodingStyle index 303c1fb..832536e 100644 --- a/docs/CodingStyle.md +++ b/CodingStyle @@ -1,9 +1,5 @@ -TinyCC Coding Style -========================== -Lines should be no more than 80 columns long. + Indentation -Indentation --------------------------------------- Turn on a "fill tabs with spaces" option in your editor. Be also careful that some files are indented with 2 spaces (when they diff --git a/Makefile b/Makefile index 1e8e63d..2045978 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,421 @@ -SRC_DIR = src +# +# Tiny C Compiler Makefile +# -.PHONY: default -default: - $(MAKE) -C $(SRC_DIR) +TOP ?= . +include $(TOP)/config.mak +VPATH = $(top_srcdir) + +CPPFLAGS += -I$(TOP) # for config.h + +ifneq (-$(findstring gcc,$(CC))-,-gcc-) +ifeq (-$(findstring clang,$(CC))-,-clang-) +# make clang accept gnuisms in libtcc1.c +CFLAGS+=-fheinous-gnu-extensions +endif +endif + +CPPFLAGS_P=$(CPPFLAGS) -DCONFIG_TCC_STATIC +CFLAGS_P=$(CFLAGS) -pg -static +LIBS_P= +LDFLAGS_P=$(LDFLAGS) + +ifdef CONFIG_WIN64 +CONFIG_WIN32=yes +endif + +ifndef CONFIG_WIN32 +LIBS=-lm +ifndef CONFIG_NOLDL +LIBS+=-ldl +endif +endif + +# make libtcc as static or dynamic library? +ifdef DISABLE_STATIC +ifndef CONFIG_WIN32 +LIBTCC=libtcc.so.1.0 +else +LIBTCC=libtcc.dll +LIBTCC_DLL=yes +LIBTCC_EXTRA=libtcc.def libtcc.a +endif +LINK_LIBTCC=-Wl,-rpath,"$(libdir)" +ifdef DISABLE_RPATH +LINK_LIBTCC= +endif +else +LIBTCC=libtcc.a +LINK_LIBTCC= +endif + +CONFIG_$(ARCH) = yes +NATIVE_DEFINES_$(CONFIG_i386) += -DTCC_TARGET_I386 +NATIVE_DEFINES_$(CONFIG_x86-64) += -DTCC_TARGET_X86_64 +NATIVE_DEFINES_$(CONFIG_WIN32) += -DTCC_TARGET_PE +NATIVE_DEFINES_$(CONFIG_uClibc) += -DTCC_UCLIBC +NATIVE_DEFINES_$(CONFIG_arm) += -DTCC_TARGET_ARM +NATIVE_DEFINES_$(CONFIG_arm_eabihf) += -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT +NATIVE_DEFINES_$(CONFIG_arm_eabi) += -DTCC_ARM_EABI +NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP +NATIVE_DEFINES_$(CONFIG_arm64) += -DTCC_TARGET_ARM64 +NATIVE_DEFINES += $(NATIVE_DEFINES_yes) + +ifeq ($(TOP),.) + +PROGS=tcc$(EXESUF) +I386_CROSS = i386-linux-gnu-tcc$(EXESUF) +WIN32_CROSS = i386-win-mingw32-tcc$(EXESUF) +WIN64_CROSS = x86_64-win-mingw32-tcc$(EXESUF) +WINCE_CROSS = arm-win-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) +ARM64_CROSS = arm64-tcc$(EXESUF) +C67_CROSS = c67-tcc$(EXESUF) + +# Legacy symlinks for cross compilers +$(I386_CROSS)_LINK = i386-tcc$(EXESUF) +$(WIN32_CROSS)_LINK = i386-win-tcc$(EXESUF) +$(WIN64_CROSS)_LINK = x86_64-win-tcc$(EXESUF) +$(WINCE_CROSS)_LINK = arm-win-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) + +ifeq ($(TARGETOS),Windows) +ifeq ($(ARCH),i386) +PROGS:=$($(WIN32_CROSS)_LINK) +$($(WIN32_CROSS)_LINK)_TCC = yes +endif +ifeq ($(ARCH),x86-64) +PROGS:=$($(WIN64_CROSS)_LINK) +$($(WIN64_CROSS)_LINK)_TCC = yes +endif +endif + +ifeq ($(TARGETOS),Linux) +ifeq ($(ARCH),i386) +PROGS:=$($(I386_CROSS)_LINK) +$($(I386_CROSS)_LINK)_TCC = yes +endif +ifeq ($(ARCH),x86-64) +PROGS:=$($(X64_CROSS)_LINK) +$($(X64_CROSS)_LINK)_TCC = yes +endif +endif + +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 +WIN32_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h tccpe.c +WIN64_FILES = $(CORE_FILES) x86_64-gen.c i386-asm.c x86_64-asm.h tccpe.c +WINCE_FILES = $(CORE_FILES) arm-gen.c tccpe.c +X86_64_FILES = $(CORE_FILES) x86_64-gen.c i386-asm.c x86_64-asm.h +ARM_FILES = $(CORE_FILES) arm-gen.c +ARM64_FILES = $(CORE_FILES) arm64-gen.c +C67_FILES = $(CORE_FILES) c67-gen.c tcccoff.c + +ifdef CONFIG_WIN64 +PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF) +NATIVE_FILES=$(WIN64_FILES) +PROGS_CROSS=$(WIN32_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) +LIBTCC1_CROSS=lib/i386-win/libtcc1.a +LIBTCC1=libtcc1.a +else ifdef CONFIG_WIN32 +PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF) +NATIVE_FILES=$(WIN32_FILES) +PROGS_CROSS=$(WIN64_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) +LIBTCC1_CROSS=lib/x86_64-win/libtcc1.a +LIBTCC1=libtcc1.a +else ifeq ($(ARCH),i386) +NATIVE_FILES=$(I386_FILES) +PROGS_CROSS=$($(X64_CROSS)_LINK) $($(WIN32_CROSS)_LINK) $($(WIN64_CROSS)_LINK) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) +LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/libtcc1.a lib/i386/libtcc1.a lib/x86_64/libtcc1.a \ + lib/arm64/libtcc1.a +LIBTCC1=libtcc1.a +else ifeq ($(ARCH),x86-64) +ifeq ($(TARGETOS),Darwin) +NATIVE_FILES=$(X86_64_FILES) +PROGS_CROSS=$($(I386_CROSS)_LINK) $($(WIN32_CROSS)_LINK) $($(WIN64_CROSS)_LINK) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS) +LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/libtcc1.a lib/i386/libtcc1.a lib/x86_64/libtcc1.a +LIBTCC1=libtcc1.a +else +NATIVE_FILES=$(X86_64_FILES) +PROGS_CROSS=$($(I386_CROSS)_LINK) $($(WIN32_CROSS)_LINK) $($(WIN64_CROSS)_LINK) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) +LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/libtcc1.a lib/i386/libtcc1.a lib/x86_64/libtcc1.a \ + lib/arm64/libtcc1.a +LIBTCC1=libtcc1.a +endif +else ifeq ($(ARCH),arm) +NATIVE_FILES=$(ARM_FILES) +PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) +LIBTCC1=libtcc1.a +LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/libtcc1.a lib/i386/libtcc1.a +else ifeq ($(ARCH),arm64) +NATIVE_FILES=$(ARM64_FILES) +PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS) +LIBTCC1=libtcc1.a +LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/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 + +TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCC_EXTRA) +TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info + +ifdef CONFIG_CROSS +PROGS+=$(PROGS_CROSS) +TCCLIBS+=$(LIBTCC1_CROSS) +endif + +all: $(PROGS) $(TCCLIBS) $(TCCDOCS) + +# Host Tiny C Compiler +tcc$(EXESUF): tcc.o $(LIBTCC) + $(CC) -o $@ $^ $(LIBS) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LINK_LIBTCC) + +# Cross Tiny C Compilers +%-tcc$(EXESUF): tcc.c + $(CC) -o $@ $< -DONE_SOURCE $(if $($@_TCC),$(NATIVE_DEFINES),$(DEFINES)) $(CPPFLAGS) $(CFLAGS) $(LIBS) $(LDFLAGS) + $(if $($@_LINK),ln -sf $@ $($@_LINK)) + $(if $($@_TCC),ln -sf $@ tcc$(EXESUF)) + +# profiling version +tcc_p$(EXESUF): $(NATIVE_FILES) + $(CC) -o $@ $< -DONE_SOURCE $(NATIVE_DEFINES) $(CPPFLAGS_P) $(CFLAGS_P) $(LIBS_P) $(LDFLAGS_P) + +$(I386_CROSS) $($(I386_CROSS)_LINK): DEFINES = -DTCC_TARGET_I386 +$(X64_CROSS) $($(X64_CROSS)_LINK): DEFINES = -DTCC_TARGET_X86_64 +$(WIN32_CROSS) $($(WIN32_CROSS)_LINK): DEFINES = -DTCC_TARGET_I386 -DTCC_TARGET_PE \ + -DCONFIG_TCCDIR="\"$(tccdir)/win32\"" \ + -DCONFIG_TCC_LIBPATHS="\"{B}/lib/32;{B}/lib\"" +$(WIN64_CROSS) $($(WIN64_CROSS)_LINK): DEFINES = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE \ + -DCONFIG_TCCDIR="\"$(tccdir)/win32\"" \ + -DCONFIG_TCC_LIBPATHS="\"{B}/lib/64;{B}/lib\"" +$(WINCE_CROSS): DEFINES = -DTCC_TARGET_PE +$(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 -DTCC_ARM_VFP +$(ARM64_CROSS): DEFINES = -DTCC_TARGET_ARM64 + +$(I386_CROSS) $($(I386_CROSS)_LINK): $(I386_FILES) +$(X64_CROSS) $($(X64_CROSS)_LINK): $(X86_64_FILES) +$(WIN32_CROSS) $($(WIN32_CROSS)_LINK): $(WIN32_FILES) +$(WIN64_CROSS) $($(WIN64_CROSS)_LINK): $(WIN64_FILES) +$(WINCE_CROSS) $($(WINCE_CROSS)_LINK): $(WINCE_FILES) +$(C67_CROSS) $($(C67_CROSS)_LINK): $(C67_FILES) +$(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CROSS): $(ARM_FILES) +$($(ARM_FPA_CROSS)_LINK) $($(ARM_FPA_LD_CROSS)_LINK) $($(ARM_VFP_CROSS)_LINK) $($(ARM_EABI_CROSS)_LINK): $(ARM_FILES) +$(ARM64_CROSS): $(ARM64_FILES) + +# libtcc generation and test +ifndef ONE_SOURCE +LIBTCC_OBJ = $(filter-out tcc.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES)))) +LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES),$(NATIVE_FILES)) +else +LIBTCC_OBJ = libtcc.o +LIBTCC_INC = $(NATIVE_FILES) +libtcc.o : NATIVE_DEFINES += -DONE_SOURCE +endif + +$(LIBTCC_OBJ) tcc.o : %.o : %.c $(LIBTCC_INC) + $(CC) -o $@ -c $< $(NATIVE_DEFINES) $(CPPFLAGS) $(CFLAGS) + +ifndef LIBTCC_DLL +libtcc.a: $(LIBTCC_OBJ) + $(AR) rcs $@ $^ +endif + +libtcc.so.1.0: $(LIBTCC_OBJ) + $(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDFLAGS) + +libtcc.so.1.0: CFLAGS+=-fPIC + +ifdef LIBTCC_DLL +libtcc.dll libtcc.def libtcc.a: $(LIBTCC_OBJ) + $(CC) -shared $^ -o $@ $(LDFLAGS) -Wl,--output-def,libtcc.def,--out-implib,libtcc.a +endif + +# windows utilities +tiny_impdef$(EXESUF): win32/tools/tiny_impdef.c + $(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) +tiny_libmaker$(EXESUF): win32/tools/tiny_libmaker.c + $(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) + +# TinyCC runtime libraries +libtcc1.a : FORCE + $(MAKE) -C lib native + if test ! -d $(ARCH); then mkdir $(ARCH); fi + if test ! -L $(ARCH)/$@; then ln -sf ../$@ $(ARCH)/$@; fi +lib/%/libtcc1.a : FORCE $(PROGS_CROSS) + $(MAKE) -C lib cross TARGET=$* + +FORCE: + +# install +TCC_INCLUDES = stdarg.h stddef.h stdbool.h float.h varargs.h +INSTALL=install +ifdef STRIP_BINARIES +INSTALLBIN=$(INSTALL) -s +else +INSTALLBIN=$(INSTALL) +endif + +install-strip: install + strip $(foreach PROG,$(PROGS),"$(bindir)"/$(PROG)) + +ifndef CONFIG_WIN32 +install: $(PROGS) $(TCCLIBS) $(TCCDOCS) + mkdir -p "$(bindir)" + $(INSTALLBIN) -m755 $(PROGS) "$(bindir)" + cp -P tcc$(EXESUF) "$(bindir)" + mkdir -p "$(mandir)/man1" + -$(INSTALL) -m644 tcc.1 "$(mandir)/man1" + mkdir -p "$(infodir)" + -$(INSTALL) -m644 tcc-doc.info "$(infodir)" + mkdir -p "$(tccdir)" + mkdir -p "$(tccdir)/include" +ifneq ($(LIBTCC1),) + mkdir -p "$(tccdir)/$(ARCH)" + $(INSTALL) -m644 $(LIBTCC1) "$(tccdir)/$(ARCH)" +endif + $(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) $(top_srcdir)/tcclib.h "$(tccdir)/include" + mkdir -p "$(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" +endif + mkdir -p "$(includedir)" + $(INSTALL) -m644 $(top_srcdir)/libtcc.h "$(includedir)" + mkdir -p "$(docdir)" + -$(INSTALL) -m644 tcc-doc.html "$(docdir)" +ifdef CONFIG_CROSS + mkdir -p "$(tccdir)/win32/lib/32" + mkdir -p "$(tccdir)/win32/lib/64" + mkdir -p "$(tccdir)/i386" + mkdir -p "$(tccdir)/x86-64" +ifneq ($(HOST_OS),Darwin) + mkdir -p "$(tccdir)/arm64" + $(INSTALL) -m644 lib/arm64/libtcc1.a "$(tccdir)/arm64" +endif + $(INSTALL) -m644 lib/i386/libtcc1.a "$(tccdir)/i386" + $(INSTALL) -m644 lib/x86_64/libtcc1.a "$(tccdir)/x86-64" + $(INSTALL) -m644 $(top_srcdir)/win32/lib/*.def "$(tccdir)/win32/lib" + $(INSTALL) -m644 lib/i386-win/libtcc1.a "$(tccdir)/win32/lib/32" + $(INSTALL) -m644 lib/x86_64-win/libtcc1.a "$(tccdir)/win32/lib/64" + cp -r $(top_srcdir)/win32/include/. "$(tccdir)/win32/include" + cp -r "$(tccdir)/include" "$(tccdir)/win32" +endif + +uninstall: + rm -fv $(foreach P,$(PROGS),"$(bindir)/$P") + rm -fv "$(bindir)/tcc$(EXESUF)" + rm -fv $(foreach P,$(LIBTCC1),"$(tccdir)/$P") + rm -fv $(foreach P,$(TCC_INCLUDES),"$(tccdir)/include/$P") + rm -fv "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info" + rm -fv "$(libdir)/$(LIBTCC)" "$(includedir)/libtcc.h" + rm -fv "$(libdir)/libtcc.so*" + rm -rv "$(tccdir)" + rm -rv "$(docdir)" +else +# on windows +install: $(PROGS) $(TCCLIBS) $(TCCDOCS) + mkdir -p "$(tccdir)" + mkdir -p "$(tccdir)/lib" + mkdir -p "$(tccdir)/include" + mkdir -p "$(tccdir)/examples" + mkdir -p "$(tccdir)/doc" + mkdir -p "$(tccdir)/libtcc" + $(INSTALLBIN) -m755 $(PROGS) "$(tccdir)" + $(INSTALLBIN) -m755 tcc.exe "$(tccdir)" + $(INSTALL) -m644 $(LIBTCC1) $(top_srcdir)/win32/lib/*.def "$(tccdir)/lib" + cp -r $(top_srcdir)/win32/include/. "$(tccdir)/include" + cp -r $(top_srcdir)/win32/examples/. "$(tccdir)/examples" + $(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) $(top_srcdir)/tcclib.h "$(tccdir)/include" + $(INSTALL) -m644 tcc-doc.html $(top_srcdir)/win32/tcc-win32.txt "$(tccdir)/doc" + $(INSTALL) -m644 $(top_srcdir)/libtcc.h $(LIBTCC_EXTRA) "$(tccdir)/libtcc" + $(INSTALL) -m644 $(LIBTCC) "$(tccdir)" +ifdef CONFIG_CROSS + mkdir -p "$(tccdir)/lib/32" + mkdir -p "$(tccdir)/lib/64" + -$(INSTALL) -m644 lib/i386-win/libtcc1.a "$(tccdir)/lib/32" + -$(INSTALL) -m644 lib/x86_64-win/libtcc1.a "$(tccdir)/lib/64" +endif + +uninstall: + rm -rfv "$(tccdir)/*" +endif + +# documentation and man page +tcc-doc.html: tcc-doc.texi + -makeinfo --no-split --html --number-sections -o $@ $< + +tcc.1: tcc-doc.texi + -$(top_srcdir)/texi2pod.pl $< tcc.pod + -pod2man --section=1 --center="Tiny C Compiler" --release=`cat $(top_srcdir)/VERSION` tcc.pod > $@ + +tcc-doc.info: tcc-doc.texi + -makeinfo $< + +# in tests subdir +export LIBTCC1 + +%est: + $(MAKE) -C tests $@ 'PROGS_CROSS=$(PROGS_CROSS)' clean: - $(MAKE) -C $(SRC_DIR) clean + rm -vf $(PROGS) tcc_p$(EXESUF) tcc.pod *~ *.o *.a *.so* *.out *.log \ + *.exe a.out tags TAGS libtcc_test$(EXESUF) tcc$(EXESUF) + -rm -r $(ARCH) arm64 +ifeq ($(HOST_OS),Linux) + -rm -r ./C: +endif + -rm *-tcc$(EXESUF) + $(MAKE) -C tests $@ +ifneq ($(LIBTCC1),) + $(MAKE) -C lib $@ +endif + +distclean: clean + rm -vf config.h config.mak config.texi tcc.1 tcc-doc.info tcc-doc.html + +config.mak: + @echo "Please run ./configure." + @exit 1 + +tags: + ctags $(top_srcdir)/*.[ch] $(top_srcdir)/include/*.h $(top_srcdir)/lib/*.[chS] + +TAGS: + ctags -e $(top_srcdir)/*.[ch] $(top_srcdir)/include/*.h $(top_srcdir)/lib/*.[chS] + +# create release tarball from *current* git branch (including tcc-doc.html +# and converting two files to CRLF) +TCC-VERSION := tcc-$(shell cat $(top_srcdir)/VERSION) +tar: tcc-doc.html + mkdir $(TCC-VERSION) + ( cd $(TCC-VERSION) && git --git-dir ../.git checkout -f ) + cp tcc-doc.html $(TCC-VERSION) + for f in tcc-win32.txt build-tcc.bat ; do \ + cat win32/$$f | sed 's,\(.*\),\1\r,g' > $(TCC-VERSION)/win32/$$f ; \ + done + tar cjf $(TCC-VERSION).tar.bz2 $(TCC-VERSION) + rm -rf $(TCC-VERSION) + git reset + +.PHONY: all clean tar tags TAGS distclean install uninstall FORCE + +endif # ifeq ($(TOP),.) diff --git a/docs/TODO b/TODO similarity index 100% rename from docs/TODO rename to TODO diff --git a/arm-gen.c b/arm-gen.c new file mode 100644 index 0000000..39185d2 --- /dev/null +++ b/arm-gen.c @@ -0,0 +1,2123 @@ +/* + * ARMv4 code generator for TCC + * + * Copyright (c) 2003 Daniel Glöckner + * Copyright (c) 2012 Thomas Preud'homme + * + * Based on i386-gen.c by Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef TARGET_DEFS_ONLY + +#if defined(TCC_ARM_EABI) && !defined(TCC_ARM_VFP) +#error "Currently TinyCC only supports float computation with VFP instructions" +#endif + +/* number of available registers */ +#ifdef TCC_ARM_VFP +#define NB_REGS 13 +#else +#define NB_REGS 9 +#endif + +typedef int RegArgs; + +#ifndef TCC_ARM_VERSION +# define TCC_ARM_VERSION 5 +#endif + +/* a register can belong to several classes. The classes must be + sorted from more general to more precise (see gv2() code which does + assumptions on it). */ +#define RC_INT 0x0001 /* generic integer register */ +#define RC_FLOAT 0x0002 /* generic float register */ +#define RC_R0 0x0004 +#define RC_R1 0x0008 +#define RC_R2 0x0010 +#define RC_R3 0x0020 +#define RC_R12 0x0040 +#define RC_F0 0x0080 +#define RC_F1 0x0100 +#define RC_F2 0x0200 +#define RC_F3 0x0400 +#ifdef TCC_ARM_VFP +#define RC_F4 0x0800 +#define RC_F5 0x1000 +#define RC_F6 0x2000 +#define RC_F7 0x4000 +#endif +#define RC_IRET RC_R0 /* function return: integer register */ +#define RC_LRET RC_R1 /* function return: second integer register */ +#define RC_FRET RC_F0 /* function return: float register */ + +/* pretty names for the registers */ +enum { + TREG_R0 = 0, + TREG_R1, + TREG_R2, + TREG_R3, + TREG_R12, + TREG_F0, + TREG_F1, + TREG_F2, + TREG_F3, +#ifdef TCC_ARM_VFP + TREG_F4, + TREG_F5, + TREG_F6, + TREG_F7, +#endif +}; + +#ifdef TCC_ARM_VFP +#define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0) +#endif + +/* return registers for function */ +#define REG_IRET TREG_R0 /* single word int return register */ +#define REG_LRET TREG_R1 /* second word return register (for long long) */ +#define REG_FRET TREG_F0 /* float return register */ + +#ifdef TCC_ARM_EABI +#define TOK___divdi3 TOK___aeabi_ldivmod +#define TOK___moddi3 TOK___aeabi_ldivmod +#define TOK___udivdi3 TOK___aeabi_uldivmod +#define TOK___umoddi3 TOK___aeabi_uldivmod +#endif + +/* defined if function parameters must be evaluated in reverse order */ +#define INVERT_FUNC_PARAMS + +/* defined if structures are passed as pointers. Otherwise structures + are directly pushed on stack. */ +/* #define FUNC_STRUCT_PARAM_AS_PTR */ + +/* pointer size, in bytes */ +#define PTR_SIZE 4 + +/* long double size and alignment, in bytes */ +#ifdef TCC_ARM_VFP +#define LDOUBLE_SIZE 8 +#endif + +#ifndef LDOUBLE_SIZE +#define LDOUBLE_SIZE 8 +#endif + +#ifdef TCC_ARM_EABI +#define LDOUBLE_ALIGN 8 +#else +#define LDOUBLE_ALIGN 4 +#endif + +/* maximum alignment (for aligned attribute support) */ +#define MAX_ALIGN 8 + +#define CHAR_IS_UNSIGNED + +/******************************************************/ +/* ELF defines */ + +#define EM_TCC_TARGET EM_ARM + +/* relocation type for 32 bit data relocation */ +#define R_DATA_32 R_ARM_ABS32 +#define R_DATA_PTR R_ARM_ABS32 +#define R_JMP_SLOT R_ARM_JUMP_SLOT +#define R_COPY R_ARM_COPY + +#define ELF_START_ADDR 0x00008000 +#define ELF_PAGE_SIZE 0x1000 + +enum float_abi { + ARM_SOFTFP_FLOAT, + ARM_HARD_FLOAT, +}; + +/******************************************************/ +#else /* ! TARGET_DEFS_ONLY */ +/******************************************************/ +#include "tcc.h" + +enum float_abi float_abi; + +ST_DATA const int reg_classes[NB_REGS] = { + /* r0 */ RC_INT | RC_R0, + /* r1 */ RC_INT | RC_R1, + /* r2 */ RC_INT | RC_R2, + /* r3 */ RC_INT | RC_R3, + /* r12 */ RC_INT | RC_R12, + /* f0 */ RC_FLOAT | RC_F0, + /* f1 */ RC_FLOAT | RC_F1, + /* f2 */ RC_FLOAT | RC_F2, + /* f3 */ RC_FLOAT | RC_F3, +#ifdef TCC_ARM_VFP + /* d4/s8 */ RC_FLOAT | RC_F4, +/* d5/s10 */ RC_FLOAT | RC_F5, +/* d6/s12 */ RC_FLOAT | RC_F6, +/* d7/s14 */ RC_FLOAT | RC_F7, +#endif +}; + +static int func_sub_sp_offset, last_itod_magic; +static int leaffunc; + +#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) +static CType float_type, double_type, func_float_type, func_double_type; +ST_FUNC void arm_init(struct TCCState *s) +{ + float_type.t = VT_FLOAT; + double_type.t = VT_DOUBLE; + func_float_type.t = VT_FUNC; + func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD); + func_double_type.t = VT_FUNC; + func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD); + + float_abi = s->float_abi; +#ifndef TCC_ARM_HARDFLOAT + tcc_warning("soft float ABI currently not supported: default to softfp"); +#endif +} +#else +#define func_float_type func_old_type +#define func_double_type func_old_type +#define func_ldouble_type func_old_type +ST_FUNC void arm_init(struct TCCState *s) +{ +#if !defined (TCC_ARM_VFP) + tcc_warning("Support for FPA is deprecated and will be removed in next" + " release"); +#endif +#if !defined (TCC_ARM_EABI) + tcc_warning("Support for OABI is deprecated and will be removed in next" + " release"); +#endif +} +#endif + +static int two2mask(int a,int b) { + return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT); +} + +static int regmask(int r) { + return reg_classes[r]&~(RC_INT|RC_FLOAT); +} + +/******************************************************/ + +#if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP) +char *default_elfinterp(struct TCCState *s) +{ + if (s->float_abi == ARM_HARD_FLOAT) + return "/lib/ld-linux-armhf.so.3"; + else + return "/lib/ld-linux.so.3"; +} +#endif + +void o(uint32_t i) +{ + /* this is a good place to start adding big-endian support*/ + int ind1; + + ind1 = ind + 4; + if (!cur_text_section) + tcc_error("compiler error! This happens f.ex. if the compiler\n" + "can't evaluate constant expressions outside of a function."); + if (ind1 > cur_text_section->data_allocated) + section_realloc(cur_text_section, ind1); + cur_text_section->data[ind++] = i&255; + i>>=8; + cur_text_section->data[ind++] = i&255; + i>>=8; + cur_text_section->data[ind++] = i&255; + i>>=8; + cur_text_section->data[ind++] = i; +} + +static uint32_t stuff_const(uint32_t op, uint32_t c) +{ + int try_neg=0; + uint32_t nc = 0, negop = 0; + + switch(op&0x1F00000) + { + case 0x800000: //add + case 0x400000: //sub + try_neg=1; + negop=op^0xC00000; + nc=-c; + break; + case 0x1A00000: //mov + case 0x1E00000: //mvn + try_neg=1; + negop=op^0x400000; + nc=~c; + break; + case 0x200000: //xor + if(c==~0) + return (op&0xF010F000)|((op>>16)&0xF)|0x1E00000; + break; + case 0x0: //and + if(c==~0) + return (op&0xF010F000)|((op>>16)&0xF)|0x1A00000; + case 0x1C00000: //bic + try_neg=1; + negop=op^0x1C00000; + nc=~c; + break; + case 0x1800000: //orr + if(c==~0) + return (op&0xFFF0FFFF)|0x1E00000; + break; + } + do { + uint32_t m; + int i; + if(c<256) /* catch undefined <<32 */ + return op|c; + for(i=2;i<32;i+=2) { + m=(0xff>>i)|(0xff<<(32-i)); + if(!(c&~m)) + return op|(i<<7)|(c<>(32-i)); + } + op=negop; + c=nc; + } while(try_neg--); + return 0; +} + + +//only add,sub +void stuff_const_harder(uint32_t op, uint32_t v) { + uint32_t x; + x=stuff_const(op,v); + if(x) + o(x); + else { + uint32_t a[16], nv, no, o2, n2; + int i,j,k; + a[0]=0xff; + o2=(op&0xfff0ffff)|((op&0xf000)<<4);; + for(i=1;i<16;i++) + a[i]=(a[i-1]>>2)|(a[i-1]<<30); + for(i=0;i<12;i++) + for(j=i<4?i+12:15;j>=i+4;j--) + if((v&(a[i]|a[j]))==v) { + o(stuff_const(op,v&a[i])); + o(stuff_const(o2,v&a[j])); + return; + } + no=op^0xC00000; + n2=o2^0xC00000; + nv=-v; + for(i=0;i<12;i++) + for(j=i<4?i+12:15;j>=i+4;j--) + if((nv&(a[i]|a[j]))==nv) { + o(stuff_const(no,nv&a[i])); + o(stuff_const(n2,nv&a[j])); + return; + } + for(i=0;i<8;i++) + for(j=i+4;j<12;j++) + for(k=i<4?i+12:15;k>=j+4;k--) + if((v&(a[i]|a[j]|a[k]))==v) { + o(stuff_const(op,v&a[i])); + o(stuff_const(o2,v&a[j])); + o(stuff_const(o2,v&a[k])); + return; + } + no=op^0xC00000; + nv=-v; + for(i=0;i<8;i++) + for(j=i+4;j<12;j++) + for(k=i<4?i+12:15;k>=j+4;k--) + if((nv&(a[i]|a[j]|a[k]))==nv) { + o(stuff_const(no,nv&a[i])); + o(stuff_const(n2,nv&a[j])); + o(stuff_const(n2,nv&a[k])); + return; + } + o(stuff_const(op,v&a[0])); + o(stuff_const(o2,v&a[4])); + o(stuff_const(o2,v&a[8])); + o(stuff_const(o2,v&a[12])); + } +} + +ST_FUNC uint32_t encbranch(int pos, int addr, int fail) +{ + addr-=pos+8; + addr/=4; + if(addr>=0x1000000 || addr<-0x1000000) { + if(fail) + tcc_error("FIXME: function bigger than 32MB"); + return 0; + } + return 0x0A000000|(addr&0xffffff); +} + +int decbranch(int pos) +{ + int x; + x=*(uint32_t *)(cur_text_section->data + pos); + x&=0x00ffffff; + if(x&0x800000) + x-=0x1000000; + return x*4+pos+8; +} + +/* output a symbol and patch all calls to it */ +void gsym_addr(int t, int a) +{ + uint32_t *x; + int lt; + while(t) { + x=(uint32_t *)(cur_text_section->data + t); + t=decbranch(lt=t); + if(a==lt+4) + *x=0xE1A00000; // nop + else { + *x &= 0xff000000; + *x |= encbranch(lt,a,1); + } + } +} + +void gsym(int t) +{ + gsym_addr(t, ind); +} + +#ifdef TCC_ARM_VFP +static uint32_t vfpr(int r) +{ + if(rTREG_F7) + tcc_error("compiler error! register %i is no vfp register",r); + return r-5; +} +#else +static uint32_t fpr(int r) +{ + if(rTREG_F3) + tcc_error("compiler error! register %i is no fpa register",r); + return r-5; +} +#endif + +static uint32_t intr(int r) +{ + if(r==4) + return 12; + if((r<0 || r>4) && r!=14) + tcc_error("compiler error! register %i is no int register",r); + return r; +} + +static void calcaddr(uint32_t *base, int *off, int *sgn, int maxoff, unsigned shift) +{ + if(*off>maxoff || *off&((1<r; + ft = sv->type.t; + fc = sv->c.ul; + + if(fc>=0) + sign=0; + else { + sign=1; + fc=-fc; + } + + v = fr & VT_VALMASK; + if (fr & VT_LVAL) { + uint32_t base = 0xB; // fp + if(v == VT_LLOCAL) { + v1.type.t = VT_PTR; + v1.r = VT_LOCAL | VT_LVAL; + v1.c.ul = sv->c.ul; + load(base=14 /* lr */, &v1); + fc=sign=0; + v=VT_LOCAL; + } else if(v == VT_CONST) { + v1.type.t = VT_PTR; + v1.r = fr&~VT_LVAL; + v1.c.ul = sv->c.ul; + v1.sym=sv->sym; + load(base=14, &v1); + fc=sign=0; + v=VT_LOCAL; + } else if(v < VT_CONST) { + base=intr(v); + fc=sign=0; + v=VT_LOCAL; + } + if(v == VT_LOCAL) { + if(is_float(ft)) { + calcaddr(&base,&fc,&sign,1020,2); +#ifdef TCC_ARM_VFP + op=0xED100A00; /* flds */ + if(!sign) + op|=0x800000; + if ((ft & VT_BTYPE) != VT_FLOAT) + op|=0x100; /* flds -> fldd */ + o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16)); +#else + op=0xED100100; + if(!sign) + op|=0x800000; +#if LDOUBLE_SIZE == 8 + if ((ft & VT_BTYPE) != VT_FLOAT) + op|=0x8000; +#else + if ((ft & VT_BTYPE) == VT_DOUBLE) + op|=0x8000; + else if ((ft & VT_BTYPE) == VT_LDOUBLE) + op|=0x400000; +#endif + o(op|(fpr(r)<<12)|(fc>>2)|(base<<16)); +#endif + } else if((ft & (VT_BTYPE|VT_UNSIGNED)) == VT_BYTE + || (ft & VT_BTYPE) == VT_SHORT) { + calcaddr(&base,&fc,&sign,255,0); + op=0xE1500090; + if ((ft & VT_BTYPE) == VT_SHORT) + op|=0x20; + if ((ft & VT_UNSIGNED) == 0) + op|=0x40; + if(!sign) + op|=0x800000; + o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf)); + } else { + calcaddr(&base,&fc,&sign,4095,0); + op=0xE5100000; + if(!sign) + op|=0x800000; + if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) + op|=0x400000; + o(op|(intr(r)<<12)|fc|(base<<16)); + } + return; + } + } else { + if (v == VT_CONST) { + op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.ul); + if (fr & VT_SYM || !op) { + o(0xE59F0000|(intr(r)<<12)); + o(0xEA000000); + if(fr & VT_SYM) + greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); + o(sv->c.ul); + } else + o(op); + return; + } else if (v == VT_LOCAL) { + op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.ul); + if (fr & VT_SYM || !op) { + o(0xE59F0000|(intr(r)<<12)); + o(0xEA000000); + if(fr & VT_SYM) // needed ? + greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); + o(sv->c.ul); + o(0xE08B0000|(intr(r)<<12)|intr(r)); + } else + o(op); + return; + } else if(v == VT_CMP) { + o(mapcc(sv->c.ul)|0x3A00001|(intr(r)<<12)); + o(mapcc(negcc(sv->c.ul))|0x3A00000|(intr(r)<<12)); + return; + } else if (v == VT_JMP || v == VT_JMPI) { + int t; + t = v & 1; + o(0xE3A00000|(intr(r)<<12)|t); + o(0xEA000000); + gsym(sv->c.ul); + o(0xE3A00000|(intr(r)<<12)|(t^1)); + return; + } else if (v < VT_CONST) { + if(is_float(ft)) +#ifdef TCC_ARM_VFP + o(0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft)); /* fcpyX */ +#else + o(0xEE008180|(fpr(r)<<12)|fpr(v)); +#endif + else + o(0xE1A00000|(intr(r)<<12)|intr(v)); + return; + } + } + tcc_error("load unimplemented!"); +} + +/* store register 'r' in lvalue 'v' */ +void store(int r, SValue *sv) +{ + SValue v1; + int v, ft, fc, fr, sign; + uint32_t op; + + fr = sv->r; + ft = sv->type.t; + fc = sv->c.ul; + + if(fc>=0) + sign=0; + else { + sign=1; + fc=-fc; + } + + v = fr & VT_VALMASK; + if (fr & VT_LVAL || fr == VT_LOCAL) { + uint32_t base = 0xb; + if(v < VT_CONST) { + base=intr(v); + v=VT_LOCAL; + fc=sign=0; + } else if(v == VT_CONST) { + v1.type.t = ft; + v1.r = fr&~VT_LVAL; + v1.c.ul = sv->c.ul; + v1.sym=sv->sym; + load(base=14, &v1); + fc=sign=0; + v=VT_LOCAL; + } + if(v == VT_LOCAL) { + if(is_float(ft)) { + calcaddr(&base,&fc,&sign,1020,2); +#ifdef TCC_ARM_VFP + op=0xED000A00; /* fsts */ + if(!sign) + op|=0x800000; + if ((ft & VT_BTYPE) != VT_FLOAT) + op|=0x100; /* fsts -> fstd */ + o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16)); +#else + op=0xED000100; + if(!sign) + op|=0x800000; +#if LDOUBLE_SIZE == 8 + if ((ft & VT_BTYPE) != VT_FLOAT) + op|=0x8000; +#else + if ((ft & VT_BTYPE) == VT_DOUBLE) + op|=0x8000; + if ((ft & VT_BTYPE) == VT_LDOUBLE) + op|=0x400000; +#endif + o(op|(fpr(r)<<12)|(fc>>2)|(base<<16)); +#endif + return; + } else if((ft & VT_BTYPE) == VT_SHORT) { + calcaddr(&base,&fc,&sign,255,0); + op=0xE14000B0; + if(!sign) + op|=0x800000; + o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf)); + } else { + calcaddr(&base,&fc,&sign,4095,0); + op=0xE5000000; + if(!sign) + op|=0x800000; + if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) + op|=0x400000; + o(op|(intr(r)<<12)|fc|(base<<16)); + } + return; + } + } + tcc_error("store unimplemented"); +} + +static void gadd_sp(int val) +{ + stuff_const_harder(0xE28DD000,val); +} + +/* 'is_jmp' is '1' if it is a jump */ +static void gcall_or_jmp(int is_jmp) +{ + int r; + if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { + uint32_t x; + /* constant case */ + x=encbranch(ind,ind+vtop->c.ul,0); + if(x) { + if (vtop->r & VT_SYM) { + /* relocation case */ + greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24); + } else + put_elf_reloc(symtab_section, cur_text_section, ind, R_ARM_PC24, 0); + o(x|(is_jmp?0xE0000000:0xE1000000)); + } else { + if(!is_jmp) + o(0xE28FE004); // add lr,pc,#4 + o(0xE51FF004); // ldr pc,[pc,#-4] + if (vtop->r & VT_SYM) + greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32); + o(vtop->c.ul); + } + } else { + /* otherwise, indirect call */ + r = gv(RC_INT); + if(!is_jmp) + o(0xE1A0E00F); // mov lr,pc + o(0xE1A0F000|intr(r)); // mov pc,r + } +} + +/* Return whether a structure is an homogeneous float aggregate or not. + The answer is true if all the elements of the structure are of the same + primitive float type and there is less than 4 elements. + + type: the type corresponding to the structure to be tested */ +static int is_hgen_float_aggr(CType *type) +{ + if ((type->t & VT_BTYPE) == VT_STRUCT) { + struct Sym *ref; + int btype, nb_fields = 0; + + ref = type->ref->next; + btype = ref->type.t & VT_BTYPE; + if (btype == VT_FLOAT || btype == VT_DOUBLE) { + for(; ref && btype == (ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++); + return !ref && nb_fields <= 4; + } + } + return 0; +} + +struct avail_regs { + signed char avail[3]; /* 3 holes max with only float and double alignments */ + int first_hole; /* first available hole */ + int last_hole; /* last available hole (none if equal to first_hole) */ + int first_free_reg; /* next free register in the sequence, hole excluded */ +}; + +#define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 } + +/* Find suitable registers for a VFP Co-Processor Register Candidate (VFP CPRC + param) according to the rules described in the procedure call standard for + the ARM architecture (AAPCS). If found, the registers are assigned to this + VFP CPRC parameter. Registers are allocated in sequence unless a hole exists + and the parameter is a single float. + + avregs: opaque structure to keep track of available VFP co-processor regs + align: alignment contraints for the param, as returned by type_size() + size: size of the parameter, as returned by type_size() */ +int assign_vfpreg(struct avail_regs *avregs, int align, int size) +{ + int first_reg = 0; + + if (avregs->first_free_reg == -1) + return -1; + if (align >> 3) { /* double alignment */ + first_reg = avregs->first_free_reg; + /* alignment contraint not respected so use next reg and record hole */ + if (first_reg & 1) + avregs->avail[avregs->last_hole++] = first_reg++; + } else { /* no special alignment (float or array of float) */ + /* if single float and a hole is available, assign the param to it */ + if (size == 4 && avregs->first_hole != avregs->last_hole) + return avregs->avail[avregs->first_hole++]; + else + first_reg = avregs->first_free_reg; + } + if (first_reg + size / 4 <= 16) { + avregs->first_free_reg = first_reg + size / 4; + return first_reg; + } + avregs->first_free_reg = -1; + return -1; +} + +/* Returns whether all params need to be passed in core registers or not. + This is the case for function part of the runtime ABI. */ +int floats_in_core_regs(SValue *sval) +{ + if (!sval->sym) + return 0; + + switch (sval->sym->v) { + case TOK___floatundisf: + case TOK___floatundidf: + case TOK___fixunssfdi: + case TOK___fixunsdfdi: +#ifndef TCC_ARM_VFP + case TOK___fixunsxfdi: +#endif + case TOK___floatdisf: + case TOK___floatdidf: + case TOK___fixsfdi: + case TOK___fixdfdi: + return 1; + + default: + return 0; + } +} + +ST_FUNC int regargs_nregs(RegArgs *args) +{ + return *args; +} + +/* 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 *regsize, RegArgs *args) { +#ifdef TCC_ARM_EABI + int size, align; + size = type_size(vt, &align); + if (float_abi == ARM_HARD_FLOAT && !variadic && + (is_float(vt->t) || is_hgen_float_aggr(vt))) { + *ret_align = 8; + *regsize = 8; + ret->ref = NULL; + ret->t = VT_DOUBLE; + *args = (size + 7) >> 3; + } else if (size <= 4) { + *ret_align = 4; + *regsize = 4; + ret->ref = NULL; + ret->t = VT_INT; + *args = 1; + } else + *args = 0; +#else + *args = 0; +#endif + + return *args != 0; +} + +/* Parameters are classified according to how they are copied to their final + destination for the function call. Because the copying is performed class + after class according to the order in the union below, it is important that + some constraints about the order of the members of this union are respected: + - CORE_STRUCT_CLASS must come after STACK_CLASS; + - CORE_CLASS must come after STACK_CLASS, CORE_STRUCT_CLASS and + VFP_STRUCT_CLASS; + - VFP_STRUCT_CLASS must come after VFP_CLASS. + See the comment for the main loop in copy_params() for the reason. */ +enum reg_class { + STACK_CLASS = 0, + CORE_STRUCT_CLASS, + VFP_CLASS, + VFP_STRUCT_CLASS, + CORE_CLASS, + NB_CLASSES +}; + +struct param_plan { + int start; /* first reg or addr used depending on the class */ + int end; /* last reg used or next free addr depending on the class */ + SValue *sval; /* pointer to SValue on the value stack */ + struct param_plan *prev; /* previous element in this class */ +}; + +struct plan { + struct param_plan *pplans; /* array of all the param plans */ + struct param_plan *clsplans[NB_CLASSES]; /* per class lists of param plans */ +}; + +#define add_param_plan(plan,pplan,class) \ + do { \ + pplan.prev = plan->clsplans[class]; \ + plan->pplans[plan ## _nb] = pplan; \ + plan->clsplans[class] = &plan->pplans[plan ## _nb++]; \ + } while(0) + +/* Assign parameters to registers and stack with alignment according to the + rules in the procedure call standard for the ARM architecture (AAPCS). + The overall assignment is recorded in an array of per parameter structures + called parameter plans. The parameter plans are also further organized in a + number of linked lists, one per class of parameter (see the comment for the + definition of union reg_class). + + nb_args: number of parameters of the function for which a call is generated + float_abi: float ABI in use for this function call + plan: the structure where the overall assignment is recorded + todo: a bitmap that record which core registers hold a parameter + + Returns the amount of stack space needed for parameter passing + + Note: this function allocated an array in plan->pplans with tcc_malloc. It + is the responsibility of the caller to free this array once used (ie not + before copy_params). */ +static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo) +{ + int i, size, align; + int ncrn /* next core register number */, nsaa /* next stacked argument address*/; + int plan_nb = 0; + struct param_plan pplan; + struct avail_regs avregs = AVAIL_REGS_INITIALIZER; + + ncrn = nsaa = 0; + *todo = 0; + plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans)); + memset(plan->clsplans, 0, sizeof(plan->clsplans)); + for(i = nb_args; i-- ;) { + int j, start_vfpreg = 0; + CType type = vtop[-i].type; + type.t &= ~VT_ARRAY; + size = type_size(&type, &align); + size = (size + 3) & ~3; + align = (align + 3) & ~3; + switch(vtop[-i].type.t & VT_BTYPE) { + case VT_STRUCT: + case VT_FLOAT: + case VT_DOUBLE: + case VT_LDOUBLE: + if (float_abi == ARM_HARD_FLOAT) { + int is_hfa = 0; /* Homogeneous float aggregate */ + + if (is_float(vtop[-i].type.t) + || (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) { + int end_vfpreg; + + start_vfpreg = assign_vfpreg(&avregs, align, size); + end_vfpreg = start_vfpreg + ((size - 1) >> 2); + if (start_vfpreg >= 0) { + pplan = (struct param_plan) {start_vfpreg, end_vfpreg, &vtop[-i]}; + if (is_hfa) + add_param_plan(plan, pplan, VFP_STRUCT_CLASS); + else + add_param_plan(plan, pplan, VFP_CLASS); + continue; + } else + break; + } + } + ncrn = (ncrn + (align-1)/4) & ~((align/4) - 1); + if (ncrn + size/4 <= 4 || (ncrn < 4 && start_vfpreg != -1)) { + /* The parameter is allocated both in core register and on stack. As + * such, it can be of either class: it would either be the last of + * CORE_STRUCT_CLASS or the first of STACK_CLASS. */ + for (j = ncrn; j < 4 && j < ncrn + size / 4; j++) + *todo|=(1< 4) + nsaa = (ncrn - 4) * 4; + } else { + ncrn = 4; + break; + } + continue; + default: + if (ncrn < 4) { + int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG; + + if (is_long) { + ncrn = (ncrn + 1) & -2; + if (ncrn == 4) + break; + } + pplan = (struct param_plan) {ncrn, ncrn, &vtop[-i]}; + ncrn++; + if (is_long) + pplan.end = ncrn++; + add_param_plan(plan, pplan, CORE_CLASS); + continue; + } + } + nsaa = (nsaa + (align - 1)) & ~(align - 1); + pplan = (struct param_plan) {nsaa, nsaa + size, &vtop[-i]}; + add_param_plan(plan, pplan, STACK_CLASS); + nsaa += size; /* size already rounded up before */ + } + return nsaa; +} + +#undef add_param_plan + +/* Copy parameters to their final destination (core reg, VFP reg or stack) for + function call. + + nb_args: number of parameters the function take + plan: the overall assignment plan for parameters + todo: a bitmap indicating what core reg will hold a parameter + + Returns the number of SValue added by this function on the value stack */ +static int copy_params(int nb_args, struct plan *plan, int todo) +{ + int size, align, r, i, nb_extra_sval = 0; + struct param_plan *pplan; + + /* Several constraints require parameters to be copied in a specific order: + - structures are copied to the stack before being loaded in a reg; + - floats loaded to an odd numbered VFP reg are first copied to the + preceding even numbered VFP reg and then moved to the next VFP reg. + + It is thus important that: + - structures assigned to core regs must be copied after parameters + assigned to the stack but before structures assigned to VFP regs because + a structure can lie partly in core registers and partly on the stack; + - parameters assigned to the stack and all structures be copied before + parameters assigned to a core reg since copying a parameter to the stack + require using a core reg; + - parameters assigned to VFP regs be copied before structures assigned to + VFP regs as the copy might use an even numbered VFP reg that already + holds part of a structure. */ + for(i = 0; i < NB_CLASSES; i++) { + for(pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) { + vpushv(pplan->sval); + pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */ + switch(i) { + case STACK_CLASS: + case CORE_STRUCT_CLASS: + case VFP_STRUCT_CLASS: + if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) { + int padding = 0; + size = type_size(&pplan->sval->type, &align); + /* align to stack align size */ + size = (size + 3) & ~3; + if (i == STACK_CLASS && pplan->prev) + padding = pplan->start - pplan->prev->end; + size += padding; /* Add padding if any */ + /* allocate the necessary size on stack */ + gadd_sp(-size); + /* generate structure store */ + r = get_reg(RC_INT); + o(0xE28D0000|(intr(r)<<12)|padding); /* add r, sp, padding */ + vset(&vtop->type, r | VT_LVAL, 0); + vswap(); + vstore(); /* memcpy to current sp + potential padding */ + + /* Homogeneous float aggregate are loaded to VFP registers + immediately since there is no way of loading data in multiple + non consecutive VFP registers as what is done for other + structures (see the use of todo). */ + if (i == VFP_STRUCT_CLASS) { + int first = pplan->start, nb = pplan->end - first + 1; + /* vpop.32 {pplan->start, ..., pplan->end} */ + o(0xECBD0A00|(first&1)<<22|(first>>1)<<12|nb); + /* No need to write the register used to a SValue since VFP regs + cannot be used for gcall_or_jmp */ + } + } else { + if (is_float(pplan->sval->type.t)) { +#ifdef TCC_ARM_VFP + r = vfpr(gv(RC_FLOAT)) << 12; + if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) + size = 4; + else { + size = 8; + r |= 0x101; /* vpush.32 -> vpush.64 */ + } + o(0xED2D0A01 + r); /* vpush */ +#else + r = fpr(gv(RC_FLOAT)) << 12; + if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) + size = 4; + else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE) + size = 8; + else + size = LDOUBLE_SIZE; + + if (size == 12) + r |= 0x400000; + else if(size == 8) + r|=0x8000; + + o(0xED2D0100|r|(size>>2)); /* some kind of vpush for FPA */ +#endif + } else { + /* simple type (currently always same size) */ + /* XXX: implicit cast ? */ + size=4; + if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { + lexpand_nr(); + size = 8; + r = gv(RC_INT); + o(0xE52D0004|(intr(r)<<12)); /* push r */ + vtop--; + } + r = gv(RC_INT); + o(0xE52D0004|(intr(r)<<12)); /* push r */ + } + if (i == STACK_CLASS && pplan->prev) + gadd_sp(pplan->prev->end - pplan->start); /* Add padding if any */ + } + break; + + case VFP_CLASS: + gv(regmask(TREG_F0 + (pplan->start >> 1))); + if (pplan->start & 1) { /* Must be in upper part of double register */ + o(0xEEF00A40|((pplan->start>>1)<<12)|(pplan->start>>1)); /* vmov.f32 s(n+1), sn */ + vtop->r = VT_CONST; /* avoid being saved on stack by gv for next float */ + } + break; + + case CORE_CLASS: + if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { + lexpand_nr(); + gv(regmask(pplan->end)); + pplan->sval->r2 = vtop->r; + vtop--; + } + gv(regmask(pplan->start)); + /* Mark register as used so that gcall_or_jmp use another one + (regs >=4 are free as never used to pass parameters) */ + pplan->sval->r = vtop->r; + break; + } + vtop--; + } + } + + /* Manually free remaining registers since next parameters are loaded + * manually, without the help of gv(int). */ + save_regs(nb_args); + + if(todo) { + o(0xE8BD0000|todo); /* pop {todo} */ + for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) { + int r; + pplan->sval->r = pplan->start; + /* An SValue can only pin 2 registers at best (r and r2) but a structure + can occupy more than 2 registers. Thus, we need to push on the value + stack some fake parameter to have on SValue for each registers used + by a structure (r2 is not used). */ + for (r = pplan->start + 1; r <= pplan->end; r++) { + if (todo & (1 << r)) { + nb_extra_sval++; + vpushi(0); + vtop->r = r; + } + } + } + } + return nb_extra_sval; +} + +/* Generate function call. The function address is pushed first, then + all the parameters in call order. This functions pops all the + parameters and the function address. */ +void gfunc_call(int nb_args) +{ + int r, args_size; + int def_float_abi = float_abi; + int todo; + struct plan plan; + +#ifdef TCC_ARM_EABI + int variadic; + + if (float_abi == ARM_HARD_FLOAT) { + variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); + if (variadic || floats_in_core_regs(&vtop[-nb_args])) + float_abi = ARM_SOFTFP_FLOAT; + } +#endif + /* cannot let cpu flags if other instruction are generated. Also avoid leaving + VT_JMP anywhere except on the top of the stack because it would complicate + the code generator. */ + r = vtop->r & VT_VALMASK; + if (r == VT_CMP || (r & ~1) == VT_JMP) + gv(RC_INT); + + args_size = assign_regs(nb_args, float_abi, &plan, &todo); + +#ifdef TCC_ARM_EABI + if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */ + args_size = (args_size + 7) & ~7; + o(0xE24DD004); /* sub sp, sp, #4 */ + } +#endif + + nb_args += copy_params(nb_args, &plan, todo); + tcc_free(plan.pplans); + + /* Move fct SValue on top as required by gcall_or_jmp */ + vrotb(nb_args + 1); + gcall_or_jmp(0); + if (args_size) + gadd_sp(args_size); /* pop all parameters passed on the stack */ +#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) + if(float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) { + if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) { + o(0xEE000A10); /*vmov s0, r0 */ + } else { + o(0xEE000B10); /* vmov.32 d0[0], r0 */ + o(0xEE201B10); /* vmov.32 d0[1], r1 */ + } + } +#endif + vtop -= nb_args + 1; /* Pop all params and fct address from value stack */ + leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */ + float_abi = def_float_abi; +} + +/* generate function prolog of type 't' */ +void gfunc_prolog(CType *func_type) +{ + Sym *sym,*sym2; + int n, nf, size, align, rs, struct_ret = 0; + int addr, pn, sn; /* pn=core, sn=stack */ + CType ret_type; + RegArgs dummy; + +#ifdef TCC_ARM_EABI + struct avail_regs avregs = AVAIL_REGS_INITIALIZER; +#endif + + sym = func_type->ref; + func_vt = sym->type; + func_var = (func_type->ref->c == FUNC_ELLIPSIS); + + n = nf = 0; + if ((func_vt.t & VT_BTYPE) == VT_STRUCT && + !gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs, &dummy)) + { + n++; + struct_ret = 1; + func_vc = 12; /* Offset from fp of the place to store the result */ + } + for(sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) { + size = type_size(&sym2->type, &align); +#ifdef TCC_ARM_EABI + if (float_abi == ARM_HARD_FLOAT && !func_var && + (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) { + int tmpnf = assign_vfpreg(&avregs, align, size); + tmpnf += (size + 3) / 4; + nf = (tmpnf > nf) ? tmpnf : nf; + } else +#endif + if (n < 4) + n += (size + 3) / 4; + } + o(0xE1A0C00D); /* mov ip,sp */ + if (func_var) + n=4; + if (n) { + if(n>4) + n=4; +#ifdef TCC_ARM_EABI + n=(n+1)&-2; +#endif + o(0xE92D0000|((1<16) + nf=16; + nf=(nf+1)&-2; /* nf => HARDFLOAT => EABI */ + o(0xED2D0A00|nf); /* save s0-s15 on stack if needed */ + } + o(0xE92D5800); /* save fp, ip, lr */ + o(0xE1A0B00D); /* mov fp, sp */ + func_sub_sp_offset = ind; + o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */ + +#ifdef TCC_ARM_EABI + if (float_abi == ARM_HARD_FLOAT) { + func_vc += nf * 4; + avregs = AVAIL_REGS_INITIALIZER; + } +#endif + pn = struct_ret, sn = 0; + while ((sym = sym->next)) { + CType *type; + type = &sym->type; + size = type_size(type, &align); + size = (size + 3) >> 2; + align = (align + 3) & ~3; +#ifdef TCC_ARM_EABI + if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym->type.t) + || is_hgen_float_aggr(&sym->type))) { + int fpn = assign_vfpreg(&avregs, align, size << 2); + if (fpn >= 0) + addr = fpn * 4; + else + goto from_stack; + } else +#endif + if (pn < 4) { +#ifdef TCC_ARM_EABI + pn = (pn + (align-1)/4) & -(align/4); +#endif + addr = (nf + pn) * 4; + pn += size; + if (!sn && pn > 4) + sn = (pn - 4); + } else { +#ifdef TCC_ARM_EABI +from_stack: + sn = (sn + (align-1)/4) & -(align/4); +#endif + addr = (n + nf + sn) * 4; + sn += size; + } + sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), + addr + 12); + } + last_itod_magic=0; + leaffunc = 1; + loc = 0; +} + +/* generate function epilog */ +void gfunc_epilog(void) +{ + uint32_t x; + int diff; + /* Copy float return value to core register if base standard is used and + float computation is made with VFP */ +#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) + if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) { + if((func_vt.t & VT_BTYPE) == VT_FLOAT) + o(0xEE100A10); /* fmrs r0, s0 */ + else { + o(0xEE100B10); /* fmrdl r0, d0 */ + o(0xEE301B10); /* fmrdh r1, d0 */ + } + } +#endif + o(0xE89BA800); /* restore fp, sp, pc */ + diff = (-loc + 3) & -4; +#ifdef TCC_ARM_EABI + if(!leaffunc) + diff = ((diff + 11) & -8) - 4; +#endif + if(diff > 0) { + x=stuff_const(0xE24BD000, diff); /* sub sp,fp,# */ + if(x) + *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = x; + else { + int addr; + addr=ind; + o(0xE59FC004); /* ldr ip,[pc+4] */ + o(0xE04BD00C); /* sub sp,fp,ip */ + o(0xE1A0F00E); /* mov pc,lr */ + o(diff); + *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = 0xE1000000|encbranch(func_sub_sp_offset,addr,1); + } + } +} + +/* generate a jump to a label */ +int gjmp(int t) +{ + int r; + r=ind; + o(0xE0000000|encbranch(r,t,1)); + return r; +} + +/* generate a jump to a fixed address */ +void gjmp_addr(int a) +{ + gjmp(a); +} + +/* generate a test. set 'inv' to invert test. Stack entry is popped */ +int gtst(int inv, int t) +{ + int v, r; + uint32_t op; + v = vtop->r & VT_VALMASK; + r=ind; + if (v == VT_CMP) { + op=mapcc(inv?negcc(vtop->c.i):vtop->c.i); + op|=encbranch(r,t,1); + o(op); + t=r; + } else if (v == VT_JMP || v == VT_JMPI) { + if ((v & 1) == inv) { + if(!vtop->c.i) + vtop->c.i=t; + else { + uint32_t *x; + int p,lp; + if(t) { + p = vtop->c.i; + do { + p = decbranch(lp=p); + } while(p); + x = (uint32_t *)(cur_text_section->data + lp); + *x &= 0xff000000; + *x |= encbranch(lp,t,1); + } + t = vtop->c.i; + } + } else { + t = gjmp(t); + gsym(vtop->c.i); + } + } + vtop--; + return t; +} + +/* generate an integer binary operation */ +void gen_opi(int op) +{ + int c, func = 0; + uint32_t opc = 0, r, fr; + unsigned short retreg = REG_IRET; + + c=0; + switch(op) { + case '+': + opc = 0x8; + c=1; + break; + case TOK_ADDC1: /* add with carry generation */ + opc = 0x9; + c=1; + break; + case '-': + opc = 0x4; + c=1; + break; + case TOK_SUBC1: /* sub with carry generation */ + opc = 0x5; + c=1; + break; + case TOK_ADDC2: /* add with carry use */ + opc = 0xA; + c=1; + break; + case TOK_SUBC2: /* sub with carry use */ + opc = 0xC; + c=1; + break; + case '&': + opc = 0x0; + c=1; + break; + case '^': + opc = 0x2; + c=1; + break; + case '|': + opc = 0x18; + c=1; + break; + case '*': + gv2(RC_INT, RC_INT); + r = vtop[-1].r; + fr = vtop[0].r; + vtop--; + o(0xE0000090|(intr(r)<<16)|(intr(r)<<8)|intr(fr)); + return; + case TOK_SHL: + opc = 0; + c=2; + break; + case TOK_SHR: + opc = 1; + c=2; + break; + case TOK_SAR: + opc = 2; + c=2; + break; + case '/': + case TOK_PDIV: + func=TOK___divsi3; + c=3; + break; + case TOK_UDIV: + func=TOK___udivsi3; + c=3; + break; + case '%': +#ifdef TCC_ARM_EABI + func=TOK___aeabi_idivmod; + retreg=REG_LRET; +#else + func=TOK___modsi3; +#endif + c=3; + break; + case TOK_UMOD: +#ifdef TCC_ARM_EABI + func=TOK___aeabi_uidivmod; + retreg=REG_LRET; +#else + func=TOK___umodsi3; +#endif + c=3; + break; + case TOK_UMULL: + gv2(RC_INT, RC_INT); + r=intr(vtop[-1].r2=get_reg(RC_INT)); + c=vtop[-1].r; + vtop[-1].r=get_reg_ex(RC_INT,regmask(c)); + vtop--; + o(0xE0800090|(r<<16)|(intr(vtop->r)<<12)|(intr(c)<<8)|intr(vtop[1].r)); + return; + default: + opc = 0x15; + c=1; + break; + } + switch(c) { + case 1: + if((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + if(opc == 4 || opc == 5 || opc == 0xc) { + vswap(); + opc|=2; // sub -> rsb + } + } + if ((vtop->r & VT_VALMASK) == VT_CMP || + (vtop->r & (VT_VALMASK & ~1)) == VT_JMP) + gv(RC_INT); + vswap(); + c=intr(gv(RC_INT)); + vswap(); + opc=0xE0000000|(opc<<20)|(c<<16); + if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + uint32_t x; + x=stuff_const(opc|0x2000000,vtop->c.i); + if(x) { + r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r))); + o(x|(r<<12)); + goto done; + } + } + fr=intr(gv(RC_INT)); + r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r))); + o(opc|(r<<12)|fr); +done: + vtop--; + if (op >= TOK_ULT && op <= TOK_GT) { + vtop->r = VT_CMP; + vtop->c.i = op; + } + break; + case 2: + opc=0xE1A00000|(opc<<5); + if ((vtop->r & VT_VALMASK) == VT_CMP || + (vtop->r & (VT_VALMASK & ~1)) == VT_JMP) + gv(RC_INT); + vswap(); + r=intr(gv(RC_INT)); + vswap(); + opc|=r; + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + fr=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r))); + c = vtop->c.i & 0x1f; + o(opc|(c<<7)|(fr<<12)); + } else { + fr=intr(gv(RC_INT)); + c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r))); + o(opc|(c<<12)|(fr<<8)|0x10); + } + vtop--; + break; + case 3: + vpush_global_sym(&func_old_type, func); + vrott(3); + gfunc_call(2); + vpushi(0); + vtop->r = retreg; + break; + default: + tcc_error("gen_opi %i unimplemented!",op); + } +} + +#ifdef TCC_ARM_VFP +static int is_zero(int i) +{ + if((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) + return 0; + if (vtop[i].type.t == VT_FLOAT) + return (vtop[i].c.f == 0.f); + else if (vtop[i].type.t == VT_DOUBLE) + return (vtop[i].c.d == 0.0); + return (vtop[i].c.ld == 0.l); +} + +/* generate a floating point operation 'v = t1 op t2' instruction. The + * two operands are guaranted to have the same floating point type */ +void gen_opf(int op) +{ + uint32_t x; + int fneg=0,r; + x=0xEE000A00|T2CPR(vtop->type.t); + switch(op) { + case '+': + if(is_zero(-1)) + vswap(); + if(is_zero(0)) { + vtop--; + return; + } + x|=0x300000; + break; + case '-': + x|=0x300040; + if(is_zero(0)) { + vtop--; + return; + } + if(is_zero(-1)) { + x|=0x810000; /* fsubX -> fnegX */ + vswap(); + vtop--; + fneg=1; + } + break; + case '*': + x|=0x200000; + break; + case '/': + x|=0x800000; + break; + default: + if(op < TOK_ULT || op > TOK_GT) { + tcc_error("unknown fp op %x!",op); + return; + } + if(is_zero(-1)) { + vswap(); + switch(op) { + case TOK_LT: op=TOK_GT; break; + case TOK_GE: op=TOK_ULE; break; + case TOK_LE: op=TOK_GE; break; + case TOK_GT: op=TOK_ULT; break; + } + } + x|=0xB40040; /* fcmpX */ + if(op!=TOK_EQ && op!=TOK_NE) + x|=0x80; /* fcmpX -> fcmpeX */ + if(is_zero(0)) { + vtop--; + o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */ + } else { + x|=vfpr(gv(RC_FLOAT)); + vswap(); + o(x|(vfpr(gv(RC_FLOAT))<<12)); + vtop--; + } + o(0xEEF1FA10); /* fmstat */ + + switch(op) { + case TOK_LE: op=TOK_ULE; break; + case TOK_LT: op=TOK_ULT; break; + case TOK_UGE: op=TOK_GE; break; + case TOK_UGT: op=TOK_GT; break; + } + + vtop->r = VT_CMP; + vtop->c.i = op; + return; + } + r=gv(RC_FLOAT); + x|=vfpr(r); + r=regmask(r); + if(!fneg) { + int r2; + vswap(); + r2=gv(RC_FLOAT); + x|=vfpr(r2)<<16; + r|=regmask(r2); + } + vtop->r=get_reg_ex(RC_FLOAT,r); + if(!fneg) + vtop--; + o(x|(vfpr(vtop->r)<<12)); +} + +#else +static uint32_t is_fconst() +{ + long double f; + uint32_t r; + if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) + return 0; + if (vtop->type.t == VT_FLOAT) + f = vtop->c.f; + else if (vtop->type.t == VT_DOUBLE) + f = vtop->c.d; + else + f = vtop->c.ld; + if(!ieee_finite(f)) + return 0; + r=0x8; + if(f<0.0) { + r=0x18; + f=-f; + } + if(f==0.0) + return r; + if(f==1.0) + return r|1; + if(f==2.0) + return r|2; + if(f==3.0) + return r|3; + if(f==4.0) + return r|4; + if(f==5.0) + return r|5; + if(f==0.5) + return r|6; + if(f==10.0) + return r|7; + return 0; +} + +/* generate a floating point operation 'v = t1 op t2' instruction. The + two operands are guaranted to have the same floating point type */ +void gen_opf(int op) +{ + uint32_t x, r, r2, c1, c2; + //fputs("gen_opf\n",stderr); + vswap(); + c1 = is_fconst(); + vswap(); + c2 = is_fconst(); + x=0xEE000100; +#if LDOUBLE_SIZE == 8 + if ((vtop->type.t & VT_BTYPE) != VT_FLOAT) + x|=0x80; +#else + if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) + x|=0x80; + else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) + x|=0x80000; +#endif + switch(op) + { + case '+': + if(!c2) { + vswap(); + c2=c1; + } + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); + if(c2) { + if(c2>0xf) + x|=0x200000; // suf + r2=c2&0xf; + } else { + r2=fpr(gv(RC_FLOAT)); + } + break; + case '-': + if(c2) { + if(c2<=0xf) + x|=0x200000; // suf + r2=c2&0xf; + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); + } else if(c1 && c1<=0xf) { + x|=0x300000; // rsf + r2=c1; + r=fpr(gv(RC_FLOAT)); + vswap(); + } else { + x|=0x200000; // suf + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); + r2=fpr(gv(RC_FLOAT)); + } + break; + case '*': + if(!c2 || c2>0xf) { + vswap(); + c2=c1; + } + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); + if(c2 && c2<=0xf) + r2=c2; + else + r2=fpr(gv(RC_FLOAT)); + x|=0x100000; // muf + break; + case '/': + if(c2 && c2<=0xf) { + x|=0x400000; // dvf + r2=c2; + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); + } else if(c1 && c1<=0xf) { + x|=0x500000; // rdf + r2=c1; + r=fpr(gv(RC_FLOAT)); + vswap(); + } else { + x|=0x400000; // dvf + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); + r2=fpr(gv(RC_FLOAT)); + } + break; + default: + if(op >= TOK_ULT && op <= TOK_GT) { + x|=0xd0f110; // cmfe +/* bug (intention?) in Linux FPU emulator + doesn't set carry if equal */ + switch(op) { + case TOK_ULT: + case TOK_UGE: + case TOK_ULE: + case TOK_UGT: + tcc_error("unsigned comparison on floats?"); + break; + case TOK_LT: + op=TOK_Nset; + break; + case TOK_LE: + op=TOK_ULE; /* correct in unordered case only if AC bit in FPSR set */ + break; + case TOK_EQ: + case TOK_NE: + x&=~0x400000; // cmfe -> cmf + break; + } + if(c1 && !c2) { + c2=c1; + vswap(); + switch(op) { + case TOK_Nset: + op=TOK_GT; + break; + case TOK_GE: + op=TOK_ULE; + break; + case TOK_ULE: + op=TOK_GE; + break; + case TOK_GT: + op=TOK_Nset; + break; + } + } + vswap(); + r=fpr(gv(RC_FLOAT)); + vswap(); + if(c2) { + if(c2>0xf) + x|=0x200000; + r2=c2&0xf; + } else { + r2=fpr(gv(RC_FLOAT)); + } + vtop[-1].r = VT_CMP; + vtop[-1].c.i = op; + } else { + tcc_error("unknown fp op %x!",op); + return; + } + } + if(vtop[-1].r == VT_CMP) + c1=15; + else { + c1=vtop->r; + if(r2&0x8) + c1=vtop[-1].r; + vtop[-1].r=get_reg_ex(RC_FLOAT,two2mask(vtop[-1].r,c1)); + c1=fpr(vtop[-1].r); + } + vtop--; + o(x|(r<<16)|(c1<<12)|r2); +} +#endif + +/* convert integers to fp 't' type. Must handle 'int', 'unsigned int' + and 'long long' cases. */ +ST_FUNC void gen_cvt_itof1(int t) +{ + uint32_t r, r2; + int bt; + bt=vtop->type.t & VT_BTYPE; + if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) { +#ifndef TCC_ARM_VFP + uint32_t dsize = 0; +#endif + r=intr(gv(RC_INT)); +#ifdef TCC_ARM_VFP + r2=vfpr(vtop->r=get_reg(RC_FLOAT)); + o(0xEE000A10|(r<<12)|(r2<<16)); /* fmsr */ + r2|=r2<<12; + if(!(vtop->type.t & VT_UNSIGNED)) + r2|=0x80; /* fuitoX -> fsituX */ + o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/ +#else + r2=fpr(vtop->r=get_reg(RC_FLOAT)); + if((t & VT_BTYPE) != VT_FLOAT) + dsize=0x80; /* flts -> fltd */ + o(0xEE000110|dsize|(r2<<16)|(r<<12)); /* flts */ + if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) { + uint32_t off = 0; + o(0xE3500000|(r<<12)); /* cmp */ + r=fpr(get_reg(RC_FLOAT)); + if(last_itod_magic) { + off=ind+8-last_itod_magic; + off/=4; + if(off>255) + off=0; + } + o(0xBD1F0100|(r<<12)|off); /* ldflts */ + if(!off) { + o(0xEA000000); /* b */ + last_itod_magic=ind; + o(0x4F800000); /* 4294967296.0f */ + } + o(0xBE000100|dsize|(r2<<16)|(r2<<12)|r); /* adflt */ + } +#endif + return; + } else if(bt == VT_LLONG) { + int func; + CType *func_type = 0; + if((t & VT_BTYPE) == VT_FLOAT) { + func_type = &func_float_type; + if(vtop->type.t & VT_UNSIGNED) + func=TOK___floatundisf; + else + func=TOK___floatdisf; +#if LDOUBLE_SIZE != 8 + } else if((t & VT_BTYPE) == VT_LDOUBLE) { + func_type = &func_ldouble_type; + if(vtop->type.t & VT_UNSIGNED) + func=TOK___floatundixf; + else + func=TOK___floatdixf; + } else if((t & VT_BTYPE) == VT_DOUBLE) { +#else + } else if((t & VT_BTYPE) == VT_DOUBLE || (t & VT_BTYPE) == VT_LDOUBLE) { +#endif + func_type = &func_double_type; + if(vtop->type.t & VT_UNSIGNED) + func=TOK___floatundidf; + else + func=TOK___floatdidf; + } + if(func_type) { + vpush_global_sym(func_type, func); + vswap(); + gfunc_call(1); + vpushi(0); + vtop->r=TREG_F0; + return; + } + } + tcc_error("unimplemented gen_cvt_itof %x!",vtop->type.t); +} + +/* convert fp to int 't' type */ +void gen_cvt_ftoi(int t) +{ + uint32_t r, r2; + int u, func = 0; + u=t&VT_UNSIGNED; + t&=VT_BTYPE; + r2=vtop->type.t & VT_BTYPE; + if(t==VT_INT) { +#ifdef TCC_ARM_VFP + r=vfpr(gv(RC_FLOAT)); + u=u?0:0x10000; + o(0xEEBC0AC0|(r<<12)|r|T2CPR(r2)|u); /* ftoXizY */ + r2=intr(vtop->r=get_reg(RC_INT)); + o(0xEE100A10|(r<<16)|(r2<<12)); + return; +#else + if(u) { + if(r2 == VT_FLOAT) + func=TOK___fixunssfsi; +#if LDOUBLE_SIZE != 8 + else if(r2 == VT_LDOUBLE) + func=TOK___fixunsxfsi; + else if(r2 == VT_DOUBLE) +#else + else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE) +#endif + func=TOK___fixunsdfsi; + } else { + r=fpr(gv(RC_FLOAT)); + r2=intr(vtop->r=get_reg(RC_INT)); + o(0xEE100170|(r2<<12)|r); + return; + } +#endif + } else if(t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1 + if(r2 == VT_FLOAT) + func=TOK___fixsfdi; +#if LDOUBLE_SIZE != 8 + else if(r2 == VT_LDOUBLE) + func=TOK___fixxfdi; + else if(r2 == VT_DOUBLE) +#else + else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE) +#endif + func=TOK___fixdfdi; + } + if(func) { + vpush_global_sym(&func_old_type, func); + vswap(); + gfunc_call(1); + vpushi(0); + if(t == VT_LLONG) + vtop->r2 = REG_LRET; + vtop->r = REG_IRET; + return; + } + tcc_error("unimplemented gen_cvt_ftoi!"); +} + +/* convert from one floating point type to another */ +void gen_cvt_ftof(int t) +{ +#ifdef TCC_ARM_VFP + if(((vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) { + uint32_t r = vfpr(gv(RC_FLOAT)); + o(0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t)); + } +#else + /* all we have to do on i386 and FPA ARM is to put the float in a register */ + gv(RC_FLOAT); +#endif +} + +/* computed goto support */ +void ggoto(void) +{ + gcall_or_jmp(1); + vtop--; +} + +/* Save the stack pointer onto the stack and return the location of its address */ +ST_FUNC void gen_vla_sp_save(int addr) { + tcc_error("variable length arrays unsupported for this target"); +} + +/* Restore the SP from a location on the stack */ +ST_FUNC void gen_vla_sp_restore(int addr) { + tcc_error("variable length arrays unsupported for this target"); +} + +/* Subtract from the stack pointer, and push the resulting value onto the stack */ +ST_FUNC void gen_vla_alloc(CType *type, int align) { + tcc_error("variable length arrays unsupported for this target"); +} + +/* end of ARM code generator */ +/*************************************************************/ +#endif +/*************************************************************/ diff --git a/src/arm/arm64-gen.c b/arm64-gen.c similarity index 99% rename from src/arm/arm64-gen.c rename to arm64-gen.c index fe3d7aa..62447e7 100644 --- a/src/arm/arm64-gen.c +++ b/arm64-gen.c @@ -58,7 +58,7 @@ typedef int RegArgs; /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ -#include "../tcc.h" +#include "tcc.h" #include ST_DATA const int reg_classes[NB_REGS] = { diff --git a/src/tms320c67/c67-gen.c b/c67-gen.c similarity index 97% rename from src/tms320c67/c67-gen.c rename to c67-gen.c index 9548dca..70da2ad 100644 --- a/src/tms320c67/c67-gen.c +++ b/c67-gen.c @@ -1,6 +1,6 @@ /* * TMS320C67xx code generator for TCC - * + * * Copyright (c) 2001, 2002 Fabrice Bellard * * This library is free software; you can redistribute it and/or @@ -127,10 +127,10 @@ enum { /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ -#include "../tcc.h" +#include "tcc.h" ST_DATA const int reg_classes[NB_REGS] = { - /* eax */ RC_INT | RC_FLOAT | RC_EAX, + /* eax */ RC_INT | RC_FLOAT | RC_EAX, // only allow even regs for floats (allow for doubles) /* ecx */ RC_INT | RC_ECX, /* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX, @@ -161,7 +161,7 @@ ST_DATA const int reg_classes[NB_REGS] = { // although tcc thinks it is passing parameters on the stack, // the C67 really passes up to the first 10 params in special // regs or regs pairs (for 64 bit params). So keep track of -// the stack offsets so we can translate to the appropriate +// the stack offsets so we can translate to the appropriate // reg (pair) #define NoCallArgsPassedOnStack 10 @@ -204,7 +204,7 @@ void C67_g(int c) #endif ind1 = ind + 4; if (ind1 > (int) cur_text_section->data_allocated) - section_realloc(cur_text_section, ind1); + section_realloc(cur_text_section, ind1); cur_text_section->data[ind] = c & 0xff; cur_text_section->data[ind + 1] = (c >> 8) & 0xff; cur_text_section->data[ind + 2] = (c >> 16) & 0xff; @@ -218,26 +218,26 @@ void gsym_addr(int t, int a) { int n, *ptr; while (t) { - ptr = (int *) (cur_text_section->data + t); - { - Sym *sym; + ptr = (int *) (cur_text_section->data + t); + { + Sym *sym; - // extract 32 bit address from MVKH/MVKL - n = ((*ptr >> 7) & 0xffff); - n |= ((*(ptr + 1) >> 7) & 0xffff) << 16; + // extract 32 bit address from MVKH/MVKL + n = ((*ptr >> 7) & 0xffff); + n |= ((*(ptr + 1) >> 7) & 0xffff) << 16; - // define a label that will be relocated + // define a label that will be relocated - sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0); - greloc(cur_text_section, sym, t, R_C60LO16); - greloc(cur_text_section, sym, t + 4, R_C60HI16); + sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0); + greloc(cur_text_section, sym, t, R_C60LO16); + greloc(cur_text_section, sym, t + 4, R_C60HI16); - // clear out where the pointer was + // clear out where the pointer was - *ptr &= ~(0xffff << 7); - *(ptr + 1) &= ~(0xffff << 7); - } - t = n; + *ptr &= ~(0xffff << 7); + *(ptr + 1) &= ~(0xffff << 7); + } + t = n; } } @@ -246,7 +246,7 @@ void gsym(int t) gsym_addr(t, ind); } -// these are regs that tcc doesn't really know about, +// these are regs that tcc doesn't really know about, // but assign them unique values so the mapping routines // can distinguish them @@ -298,7 +298,7 @@ int C67_map_regn(int r) return 0; } -// mapping from tcc reg number to +// mapping from tcc reg number to // C67 register to condition code field // // valid condition code regs are: @@ -343,15 +343,15 @@ int C67_map_regs(int r) else if (r >= TREG_C67_A4 && r <= TREG_C67_B13) // these form a pattern of alt pairs return (r & 2) >> 1; else if (r == C67_A0) - return 0; // set to A side + return 0; // set to A side else if (r == C67_B2) - return 1; // set to B side + return 1; // set to B side else if (r == C67_B3) return 1; // set to B side else if (r == C67_SP) - return 0x1; // set to SP (B15) B side + return 0x1; // set to SP (B15) B side else if (r == C67_FP) - return 0x0; // set to FP (A15) A side + return 0x0; // set to FP (A15) A side else ALWAYS_ASSERT(FALSE); @@ -420,7 +420,7 @@ void C67_asm(char *s, int a, int b, int c) (5 << 9) | //mode 5 = pos offset, base reg + off reg (0 << 8) | //r (LDDW bit 0) (0 << 7) | //y D1/D2 A side - (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU + (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU (1 << 2) | //opcode (C67_map_regs(a) << 1) | //side of src (0 << 0)); //parallel @@ -442,7 +442,7 @@ void C67_asm(char *s, int a, int b, int c) (5 << 9) | //mode 5 = pos offset, base reg + off reg (0 << 8) | //r (LDDW bit 0) (0 << 7) | //y D1/D2 A side - (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU + (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU (1 << 2) | //opcode (C67_map_regs(a) << 1) | //side of src (0 << 0)); //parallel @@ -464,7 +464,7 @@ void C67_asm(char *s, int a, int b, int c) (5 << 9) | //mode 5 = pos offset, base reg + off reg (0 << 8) | //r (LDDW bit 0) (0 << 7) | //y D1/D2 A side - (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU + (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU (1 << 2) | //opcode (C67_map_regs(a) << 1) | //side of src (0 << 0)); //parallel @@ -475,7 +475,7 @@ void C67_asm(char *s, int a, int b, int c) (1 << 9) | //mode 1 = pos cst offset (0 << 8) | //r (LDDW bit 0) (C67_map_regs(b) << 7) | //y D1/D2 base reg side - (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU + (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU (1 << 2) | //opcode (C67_map_regs(a) << 1) | //side of src (0 << 0)); //parallel @@ -486,7 +486,7 @@ void C67_asm(char *s, int a, int b, int c) (1 << 9) | //mode 1 = pos cst offset (0 << 8) | //r (LDDW bit 0) (C67_map_regs(b) << 7) | //y D1/D2 base reg side - (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU + (5 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU (1 << 2) | //opcode (C67_map_regs(a) << 1) | //side of src (0 << 0)); //parallel @@ -497,7 +497,7 @@ void C67_asm(char *s, int a, int b, int c) (1 << 9) | //mode 1 = pos cst offset (0 << 8) | //r (LDDW bit 0) (C67_map_regs(b) << 7) | //y D1/D2 base reg side - (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU + (3 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU (1 << 2) | //opcode (C67_map_regs(a) << 1) | //side of src (0 << 0)); //parallel @@ -509,7 +509,7 @@ void C67_asm(char *s, int a, int b, int c) (1 << 9) | //mode 1 = pos cst offset (0 << 8) | //r (LDDW bit 0) (C67_map_regs(b) << 7) | //y D1/D2 base reg side - (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU + (7 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU (1 << 2) | //opcode (C67_map_regs(a) << 1) | //side of src (0 << 0)); //parallel @@ -641,7 +641,7 @@ void C67_asm(char *s, int a, int b, int c) (1 << 9) | //mode 1 = pos cst offset (0 << 8) | //r (LDDW bit 0) (C67_map_regs(a) << 7) | //y D1/D2 src side - (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU + (2 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU (1 << 2) | //opcode (C67_map_regs(b) << 1) | //side of dst (0 << 0)); //parallel @@ -652,7 +652,7 @@ void C67_asm(char *s, int a, int b, int c) (1 << 9) | //mode 1 = pos cst offset (0 << 8) | //r (LDDW bit 0) (C67_map_regs(a) << 7) | //y D1/D2 src side - (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU + (0 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU (1 << 2) | //opcode (C67_map_regs(b) << 1) | //side of dst (0 << 0)); //parallel @@ -674,7 +674,7 @@ void C67_asm(char *s, int a, int b, int c) (1 << 9) | //mode 1 = pos cst offset (0 << 8) | //r (LDDW bit 0) (C67_map_regs(a) << 7) | //y D1/D2 src side - (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU + (6 << 4) | //ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU (1 << 2) | //opcode (C67_map_regs(b) << 1) | //side of dst (0 << 0)); //parallel @@ -877,7 +877,7 @@ void C67_asm(char *s, int a, int b, int c) C67_g((0 << 29) | //creg (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst - (C67_map_regn(b) << 18) | //src2 + (C67_map_regn(b) << 18) | //src2 (0 << 13) | //src1 NA (xpath << 12) | //x cross path if opposite sides (0x4a << 5) | //opcode @@ -890,7 +890,7 @@ void C67_asm(char *s, int a, int b, int c) C67_g((0 << 29) | //creg (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst - (C67_map_regn(b) << 18) | //src2 + (C67_map_regn(b) << 18) | //src2 (0 << 13) | //src1 NA (xpath << 12) | //x cross path if opposite sides (0x49 << 5) | //opcode @@ -903,7 +903,7 @@ void C67_asm(char *s, int a, int b, int c) C67_g((0 << 29) | //creg (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst - (C67_map_regn(b) << 18) | //src2 + (C67_map_regn(b) << 18) | //src2 (0 << 13) | //src1 NA (xpath << 12) | //x cross path if opposite sides (0x39 << 5) | //opcode @@ -958,7 +958,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 (possible x path) - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x3 << 5) | //opcode (0x6 << 2) | //opcode fixed @@ -973,7 +973,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 (possible x path) - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x7 << 5) | //opcode (0x6 << 2) | //opcode fixed @@ -988,7 +988,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 (possible x path) - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x7f << 5) | //opcode (0x6 << 2) | //opcode fixed @@ -1003,7 +1003,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 (possible x path) - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x7b << 5) | //opcode (0x6 << 2) | //opcode fixed @@ -1018,7 +1018,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 (possible x path) - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x6f << 5) | //opcode (0x6 << 2) | //opcode fixed @@ -1033,7 +1033,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 (possible x path) - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x10 << 5) | //opcode (0x6 << 2) | //opcode fixed @@ -1048,7 +1048,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 (possible x path) - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x18 << 5) | //opcode (0x6 << 2) | //opcode fixed @@ -1063,7 +1063,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 (possible x path) - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x11 << 5) | //opcode (0x6 << 2) | //opcode fixed @@ -1078,7 +1078,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 (possible x path) - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x19 << 5) | //opcode (0x6 << 2) | //opcode fixed @@ -1093,7 +1093,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 (possible x path) - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x1c << 7) | //opcode (0x0 << 2) | //opcode fixed @@ -1108,7 +1108,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 (possible x path) - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x0e << 7) | //opcode (0x0 << 2) | //opcode fixed @@ -1138,7 +1138,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x37 << 6) | //opcode (0x8 << 2) | //opcode fixed @@ -1153,7 +1153,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x27 << 6) | //opcode (0x8 << 2) | //opcode fixed @@ -1168,7 +1168,7 @@ void C67_asm(char *s, int a, int b, int c) (0 << 28) | //inv (C67_map_regn(c) << 23) | //dst (C67_map_regn(b) << 18) | //src2 - (C67_map_regn(a) << 13) | //src1 + (C67_map_regn(a) << 13) | //src1 (xpath << 12) | //x cross path if opposite sides (0x33 << 6) | //opcode (0x8 << 2) | //opcode fixed @@ -1597,7 +1597,7 @@ void load(int r, SValue * sv) size = 4; } - // check if fc is a positive reference on the stack, + // check if fc is a positive reference on the stack, // if it is tcc is referencing what it thinks is a parameter // on the stack, so check if it is really in a register. @@ -1962,7 +1962,7 @@ void gfunc_call(int nb_args) // ending with B12:B13. // // When a call is made, if the caller has its parameters -// in regs A4-B13 these must be saved before/as the call +// in regs A4-B13 these must be saved before/as the call // parameters are loaded and restored upon return (or if/when needed). /* generate function prolog of type 't' */ @@ -2033,7 +2033,7 @@ void gfunc_prolog(CType * func_type) TotalBytesPushedOnStack = -loc; - func_sub_sp_offset = ind; // remember where we put the stack instruction + func_sub_sp_offset = ind; // remember where we put the stack instruction C67_ADDK(0, C67_SP); // ADDK.L2 loc,SP (just put zero temporarily) C67_PUSH(C67_A0); @@ -2049,11 +2049,11 @@ void gfunc_epilog(void) C67_NOP(4); // NOP wait for load C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3); // B.S2 B3 C67_POP(C67_FP); - C67_ADDK(local, C67_SP); // ADDK.L2 loc,SP + C67_ADDK(local, C67_SP); // ADDK.L2 loc,SP C67_Adjust_ADDK((int *) (cur_text_section->data + func_sub_sp_offset), -local + TotalBytesPushedOnStack); - C67_NOP(3); // NOP + C67_NOP(3); // NOP } } diff --git a/src/coff.h b/coff.h similarity index 99% rename from src/coff.h rename to coff.h index 63edfe2..ea871a7 100644 --- a/src/coff.h +++ b/coff.h @@ -31,9 +31,9 @@ struct filehdr { #define F_LITTLE 0x100 /* byte ordering of an AR32WR (vax) */ #define F_BIG 0x200 /* byte ordering of an AR32W (3B, maxi) */ #define F_PATCH 0x400 /* contains "patch" list in optional header */ -#define F_NODF 0x400 +#define F_NODF 0x400 -#define F_VERSION (F_GSP10 | F_GSP20) +#define F_VERSION (F_GSP10 | F_GSP20) #define F_BYTE_ORDER (F_LITTLE | F_BIG) #define FILHDR struct filehdr @@ -68,7 +68,7 @@ typedef struct aouthdr { /*----------------------------------------------------------------------*/ /* When a UNIX aout header is to be built in the optional header, */ -/* the following magic numbers can appear in that header: */ +/* the following magic numbers can appear in that header: */ /* */ /* AOUT1MAGIC : default : readonly sharable text segment */ /* AOUT2MAGIC: : writable text segment */ @@ -164,7 +164,7 @@ struct scnhdr { #define STYP_NOLOAD 0x02 /* "noload" : allocated, relocated, not loaded */ #define STYP_GROUP 0x04 /* "grouped" : formed of input sections */ #define STYP_PAD 0x08 /* "padding" : not allocated, not relocated, loaded */ -#define STYP_COPY 0x10 /* "copy" : used for C init tables - +#define STYP_COPY 0x10 /* "copy" : used for C init tables - not allocated, relocated, loaded; reloc & lineno entries processed normally */ @@ -358,11 +358,11 @@ struct syment #define N_BTSHFT_COFF 4 #define N_TSHIFT_COFF 2 -#define BTYPE_COFF(x) ((x) & N_BTMASK_COFF) +#define BTYPE_COFF(x) ((x) & N_BTMASK_COFF) #define ISINT(x) (((x) >= T_CHAR && (x) <= T_LONG) || \ ((x) >= T_UCHAR && (x) <= T_ULONG) || (x) == T_ENUM) #define ISFLT_COFF(x) ((x) == T_DOUBLE || (x) == T_FLOAT) -#define ISPTR_COFF(x) (((x) & N_TMASK_COFF) == (DT_PTR << N_BTSHFT_COFF)) +#define ISPTR_COFF(x) (((x) & N_TMASK_COFF) == (DT_PTR << N_BTSHFT_COFF)) #define ISFCN_COFF(x) (((x) & N_TMASK_COFF) == (DT_FCN << N_BTSHFT_COFF)) #define ISARY_COFF(x) (((x) & N_TMASK_COFF) == (DT_ARY << N_BTSHFT_COFF)) #define ISTAG_COFF(x) ((x)==C_STRTAG || (x)==C_UNTAG || (x)==C_ENTAG) @@ -370,7 +370,7 @@ struct syment #define INCREF_COFF(x) ((((x)&~N_BTMASK_COFF)<>N_TSHIFT_COFF)&~N_BTMASK_COFF)|((x)&N_BTMASK_COFF)) - + /*------------------------------------------------------------------------*/ /* AUXILIARY SYMBOL ENTRY */ /*------------------------------------------------------------------------*/ diff --git a/src/config.h.in b/config.h.in similarity index 100% rename from src/config.h.in rename to config.h.in diff --git a/docs/config.texi.in b/config.texi.in similarity index 100% rename from docs/config.texi.in rename to config.texi.in diff --git a/configure b/configure index f00a6b6..6a796f3 100755 --- a/configure +++ b/configure @@ -66,7 +66,7 @@ case $targetos in esac # find source path -# XXX: we assume an absolute path is given when launching configure, +# XXX: we assume an absolute path is given when launching configure, # except in './configure' case. source_path=${0%configure} source_path=${source_path%/} @@ -337,7 +337,7 @@ strip="${cross_prefix}${strip}" CONFTEST=./conftest$EXESUF if test -z "$cross_prefix" ; then - if ! $cc -o $CONFTEST $source_path/src/conftest.c 2>/dev/null ; then + if ! $cc -o $CONFTEST $source_path/conftest.c 2>/dev/null ; then echo "configure: error: '$cc' failed to compile conftest.c." else bigendian="$($CONFTEST bigendian)" @@ -560,7 +560,7 @@ fi version=`head $source_path/VERSION` echo "VERSION=$version" >>config.mak echo "#define TCC_VERSION \"$version\"" >> $TMPH -echo "@set VERSION $version" >docs/config.texi +echo "@set VERSION $version" > config.texi echo "SRC_PATH=$source_path" >>config.mak if test "$source_path_used" = "yes" ; then @@ -573,9 +573,9 @@ else fi echo 'top_builddir=$(TOP)' >>config.mak -diff $TMPH src/config.h >/dev/null 2>&1 +diff $TMPH config.h >/dev/null 2>&1 if test $? -ne 0 ; then - mv -f $TMPH src/config.h + mv -f $TMPH config.h else echo "config.h is unchanged" fi diff --git a/src/conftest.c b/conftest.c similarity index 100% rename from src/conftest.c rename to conftest.c diff --git a/src/elf.h b/elf.h similarity index 100% rename from src/elf.h rename to elf.h diff --git a/src/x86/i386-asm.c b/i386-asm.c similarity index 99% rename from src/x86/i386-asm.c rename to i386-asm.c index adc40b2..840a971 100644 --- a/src/x86/i386-asm.c +++ b/i386-asm.c @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../tcc.h" +#include "tcc.h" /* #define NB_ASM_REGS 8 */ #define MAX_OPERANDS 3 @@ -712,7 +712,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) a32 = addr32 = 1; } #endif - if (b & 0xff00) + if (b & 0xff00) g(b >> 8); g(b); return; diff --git a/src/x86/i386-asm.h b/i386-asm.h similarity index 99% rename from src/x86/i386-asm.h rename to i386-asm.h index 2e82e0d..43c8867 100644 --- a/src/x86/i386-asm.h +++ b/i386-asm.h @@ -57,7 +57,7 @@ ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL)) ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL)) /* bits */ - + ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW)) ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW)) @@ -91,7 +91,7 @@ ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA) DEF_ASM_OP0(repz, 0xf3) DEF_ASM_OP0(repne, 0xf2) DEF_ASM_OP0(repnz, 0xf2) - + DEF_ASM_OP0(invd, 0x0f08) DEF_ASM_OP0(wbinvd, 0x0f09) DEF_ASM_OP0(cpuid, 0x0fa2) @@ -236,7 +236,7 @@ ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR)) DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR) DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR) DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR) - + /* float */ /* specific fcomp handling */ ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0)) @@ -298,7 +298,7 @@ ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA)) DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA) DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA) DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA) - + /* fp store */ DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST) DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST) @@ -380,7 +380,7 @@ ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT /* pentium */ DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA ) - + /* pentium pro */ ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) #ifdef I386_ASM_16 diff --git a/src/x86/i386-gen.c b/i386-gen.c similarity index 98% rename from src/x86/i386-gen.c rename to i386-gen.c index b8b12aa..f268c2b 100644 --- a/src/x86/i386-gen.c +++ b/i386-gen.c @@ -1,6 +1,6 @@ /* * X86 code generator for TCC - * + * * Copyright (c) 2001-2004 Fabrice Bellard * * This library is free software; you can redistribute it and/or @@ -32,7 +32,7 @@ typedef int RegArgs; #define RC_INT 0x0001 /* generic integer register */ #define RC_FLOAT 0x0002 /* generic float register */ #define RC_EAX 0x0004 -#define RC_ST0 0x0008 +#define RC_ST0 0x0008 #define RC_ECX 0x0010 #define RC_EDX 0x0020 #define RC_IRET RC_EAX /* function return: integer register */ @@ -89,7 +89,7 @@ enum { /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ -#include "../tcc.h" +#include "tcc.h" ST_DATA const int reg_classes[NB_REGS] = { /* eax */ RC_INT | RC_EAX, @@ -357,11 +357,11 @@ static void gcall_or_jmp(int is_jmp) /* constant case */ if (vtop->r & VT_SYM) { /* relocation case */ - greloc(cur_text_section, vtop->sym, + greloc(cur_text_section, vtop->sym, ind + 1, R_386_PC32); } else { /* put an empty PC32 relocation */ - put_elf_reloc(symtab_section, cur_text_section, + put_elf_reloc(symtab_section, cur_text_section, ind + 1, R_386_PC32, 0); } oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */ @@ -417,7 +417,7 @@ ST_FUNC void gfunc_call(int nb_args) { int size, align, r, args_size, i, func_call; Sym *func_sym; - + args_size = 0; for(i = 0;i < nb_args; i++) { if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { @@ -610,7 +610,7 @@ ST_FUNC void gfunc_epilog(void) /* generate bound local allocation */ saved_ind = ind; ind = func_sub_sp_offset; - sym_data = get_sym_ref(&char_pointer_type, lbounds_section, + sym_data = get_sym_ref(&char_pointer_type, lbounds_section, func_bound_offset, lbounds_section->data_offset); greloc(cur_text_section, sym_data, ind + 1, R_386_32); @@ -637,8 +637,8 @@ ST_FUNC void gfunc_epilog(void) g(func_ret_sub >> 8); } /* align local size to word & save local variables */ - - v = (-loc + 3) & -4; + + v = (-loc + 3) & -4; saved_ind = ind; ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; #ifdef TCC_TARGET_PE @@ -741,7 +741,7 @@ ST_FUNC void gen_opi(int op) r = vtop[-1].r; fr = vtop[0].r; o((opc << 3) | 0x01); - o(0xc0 + r + fr * 8); + o(0xc0 + r + fr * 8); } vtop--; if (op >= TOK_ULT && op <= TOK_GT) { @@ -911,7 +911,7 @@ ST_FUNC void gen_opf(int op) load(TREG_ST0, vtop); swapped = !swapped; } - + switch(op) { default: case '+': @@ -972,7 +972,7 @@ ST_FUNC void gen_cvt_itof(int t) o(0x50 + (vtop->r & VT_VALMASK)); /* push r */ o(0x242cdf); /* fildll (%esp) */ o(0x08c483); /* add $8, %esp */ - } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == + } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) { /* unsigned int to float/double/long double */ o(0x6a); /* push $0 */ @@ -1060,7 +1060,7 @@ ST_FUNC void gen_bounded_ptr_add(void) vtop++; vtop->r = TREG_EAX | VT_BOUNDED; /* address of bounding function call point */ - vtop->c.ul = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel)); + vtop->c.ul = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel)); } /* patch pointer addition in vtop so that pointer dereferencing is diff --git a/src/x86/i386-tok.h b/i386-tok.h similarity index 100% rename from src/x86/i386-tok.h rename to i386-tok.h diff --git a/src/cil/il-gen.c b/il-gen.c similarity index 99% rename from src/cil/il-gen.c rename to il-gen.c index a4170b0..cf3aff5 100644 --- a/src/cil/il-gen.c +++ b/il-gen.c @@ -1,6 +1,6 @@ /* * CIL code generator for TCC - * + * * Copyright (c) 2002 Fabrice Bellard * * This library is free software; you can redistribute it and/or @@ -112,7 +112,7 @@ static void init_outfile(void) { if (!il_outfile) { il_outfile = stdout; - fprintf(il_outfile, + fprintf(il_outfile, ".assembly extern mscorlib\n" "{\n" ".ver 1:0:2411:0\n" @@ -149,7 +149,7 @@ static void out_opi(int op, int c) } /* XXX: not complete */ -static void il_type_to_str(char *buf, int buf_size, +static void il_type_to_str(char *buf, int buf_size, int t, const char *varstr) { int bt; @@ -301,12 +301,12 @@ void load(int r, SValue *sv) out_op(IL_OP_LDIND_U2); else out_op(IL_OP_LDIND_I4); - } + } } else { if (v == VT_CONST) { /* XXX: handle globals */ if (fc >= -1 && fc <= 8) { - out_op(IL_OP_LDC_I4_M1 + fc + 1); + out_op(IL_OP_LDC_I4_M1 + fc + 1); } else { out_opi(IL_OP_LDC_I4, fc); } @@ -430,10 +430,10 @@ void gfunc_prolog(int t) /* XXX: cannot do better now */ fprintf(il_outfile, " .maxstack %d\n", NB_REGS); fprintf(il_outfile, " .locals (int32, int32, int32, int32, int32, int32, int32, int32)\n"); - + if (!strcmp(funcname, "main")) fprintf(il_outfile, " .entrypoint\n"); - + sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT); func_call = sym->r; diff --git a/src/cil/il-opcodes.h b/il-opcodes.h similarity index 99% rename from src/cil/il-opcodes.h rename to il-opcodes.h index adf35cf..d53ffb2 100644 --- a/src/cil/il-opcodes.h +++ b/il-opcodes.h @@ -1,6 +1,6 @@ /* * CIL opcode definition - * + * * Copyright (c) 2002 Fabrice Bellard * * This program is free software; you can redistribute it and/or modify diff --git a/lib/Makefile b/lib/Makefile index e747b98..348cb72 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -2,9 +2,9 @@ # Tiny C Compiler Makefile for libtcc1.a # -TOP = ../src +TOP = .. include $(TOP)/Makefile -VPATH = $(top_srcdir)/../lib $(top_srcdir)/../win32/lib +VPATH = $(top_srcdir)/lib $(top_srcdir)/win32/lib ifndef TARGET # native library ifdef CONFIG_WIN64 @@ -37,7 +37,7 @@ endif BCHECK_O = bcheck.o DIR = $(TARGET) -native : $(DIR)/libtcc1.a +native : ../libtcc1.a cross : $(DIR)/libtcc1.a native : TCC = $(TOP)/tcc$(EXESUF) @@ -61,26 +61,26 @@ CFLAGS := $(filter-out -fstack-protector-strong,$(CFLAGS)) ifeq "$(TARGET)" "i386-win" OBJ = $(addprefix $(DIR)/,$(WIN32_O)) TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE - XCC ?= $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/../include + XCC ?= $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include XAR ?= $(DIR)/tiny_libmaker$(EXESUF) PICFLAGS = else ifeq "$(TARGET)" "x86_64-win" OBJ = $(addprefix $(DIR)/,$(WIN64_O)) TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE - XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/../include + 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)) TGT = -DTCC_TARGET_I386 - XCC ?= $(TCC) -B$(TOP) -I$(top_srcdir)/../include + XCC ?= $(TCC) -B$(TOP) else ifeq "$(TARGET)" "x86_64" OBJ = $(addprefix $(DIR)/,$(X86_64_O)) TGT = -DTCC_TARGET_X86_64 - XCC ?= $(TCC) -B$(TOP) -I$(top_srcdir)/../include + XCC ?= $(TCC) -B$(TOP) else ifeq "$(TARGET)" "arm" OBJ = $(addprefix $(DIR)/,$(ARM_O)) @@ -110,7 +110,7 @@ endif XAR ?= $(AR) -$(DIR)/libtcc1.a : $(OBJ) $(XAR) +$(DIR)/libtcc1.a ../libtcc1.a : $(OBJ) $(XAR) $(XAR) rcs $@ $(OBJ) $(DIR)/%.o : %.c $(XCC) -c $< -o $@ $(XFLAGS) diff --git a/lib/bcheck.c b/lib/bcheck.c index d21880e..829e33d 100644 --- a/lib/bcheck.c +++ b/lib/bcheck.c @@ -1,6 +1,6 @@ /* * Tiny C Memory and bounds checker - * + * * Copyright (c) 2002 Fabrice Bellard * * This library is free software; you can redistribute it and/or @@ -88,7 +88,7 @@ int __bound_delete_region(void *p); #ifdef __attribute__ /* an __attribute__ macro is defined in the system headers */ - #undef __attribute__ + #undef __attribute__ #endif #define FASTCALL __attribute__((regparm(3))) @@ -177,8 +177,8 @@ void * FASTCALL __bound_ptr_add(void *p, size_t offset) dprintf(stderr, "%s %s: %p %p\n", __FILE__, __FUNCTION__, p, offset); e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; - e = (BoundEntry *)((char *)e + - ((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) & + e = (BoundEntry *)((char *)e + + ((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) & ((BOUND_T2_SIZE - 1) << BOUND_E_BITS))); addr -= e->start; if (addr > e->size) { @@ -236,7 +236,7 @@ BOUND_PTR_INDIR(16) } /* called when entering a function to add all the local regions */ -void FASTCALL __bound_local_new(void *p1) +void FASTCALL __bound_local_new(void *p1) { size_t addr, size, fp, *p = p1; @@ -255,7 +255,7 @@ void FASTCALL __bound_local_new(void *p1) } /* called when leaving a function to delete all the local regions */ -void FASTCALL __bound_local_delete(void *p1) +void FASTCALL __bound_local_delete(void *p1) { size_t addr, fp, *p = p1; GET_CALLER_FP(fp); @@ -331,14 +331,14 @@ static void mark_invalid(size_t addr, size_t size) #if 0 dprintf(stderr, "mark_invalid: start = %x %x\n", t2_start, t2_end); #endif - + /* first we handle full pages */ t1_start = (t2_start + BOUND_T2_SIZE - 1) >> BOUND_T2_BITS; t1_end = t2_end >> BOUND_T2_BITS; i = t2_start & (BOUND_T2_SIZE - 1); j = t2_end & (BOUND_T2_SIZE - 1); - + if (t1_start == t1_end) { page = get_page(t2_start >> BOUND_T2_BITS); for(; i < j; i++) { @@ -456,7 +456,7 @@ void __bound_main_arg(void **p) void *start = p; while (*p++); - dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", + dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", __FILE__, __FUNCTION__, (void *) p - start); __bound_new_region(start, (void *) p - start); @@ -467,7 +467,7 @@ void __bound_exit(void) restore_malloc_hooks(); } -static inline void add_region(BoundEntry *e, +static inline void add_region(BoundEntry *e, size_t start, size_t size) { BoundEntry *e1; @@ -496,7 +496,7 @@ void __bound_new_region(void *p, size_t size) __bound_init(); - dprintf(stderr, "%s, %s(%p, %p) start\n", + dprintf(stderr, "%s, %s(%p, %p) start\n", __FILE__, __FUNCTION__, p, size); start = (size_t)p; @@ -506,9 +506,9 @@ void __bound_new_region(void *p, size_t size) /* start */ page = get_page(t1_start); - t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) & + t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) & ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); - t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) & + t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) & ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); @@ -557,7 +557,7 @@ void __bound_new_region(void *p, size_t size) } /* delete a region */ -static inline void delete_region(BoundEntry *e, +static inline void delete_region(BoundEntry *e, void *p, size_t empty_size) { size_t addr; @@ -612,9 +612,9 @@ int __bound_delete_region(void *p) start = (size_t)p; t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); - t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) & + t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) & ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); - + /* find region size */ page = __bound_t1[t1_start]; e = (BoundEntry *)((char *)page + t2_start); @@ -622,7 +622,7 @@ int __bound_delete_region(void *p) if (addr > e->size) e = __bound_find_region(e, p); /* test if invalid region */ - if (e->size == EMPTY_SIZE || (size_t)p != e->start) + if (e->size == EMPTY_SIZE || (size_t)p != e->start) return -1; /* compute the size we put in invalid regions */ if (e->is_invalid) @@ -634,7 +634,7 @@ int __bound_delete_region(void *p) /* now we can free each entry */ t1_end = end >> (BOUND_T2_BITS + BOUND_T3_BITS); - t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) & + t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) & ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); delete_region(e, p, empty_size); @@ -690,8 +690,8 @@ static size_t get_region_size(void *p) BoundEntry *e; e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; - e = (BoundEntry *)((char *)e + - ((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) & + e = (BoundEntry *)((char *)e + + ((addr >> (BOUND_T3_BITS - BOUND_E_BITS)) & ((BOUND_T2_SIZE - 1) << BOUND_E_BITS))); addr -= e->start; if (addr > e->size) @@ -756,16 +756,16 @@ static void libc_free(void *ptr) void *__bound_malloc(size_t size, const void *caller) { void *ptr; - + /* we allocate one more byte to ensure the regions will be separated by at least one byte. With the glibc malloc, it may be in fact not necessary */ ptr = libc_malloc(size + 1); - + if (!ptr) return NULL; - dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", + dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", __FILE__, __FUNCTION__, ptr, size); __bound_new_region(ptr, size); @@ -792,13 +792,13 @@ void *__bound_memalign(size_t size, size_t align, const void *caller) be in fact not necessary */ ptr = memalign(size + 1, align); #endif - + install_malloc_hooks(); - + if (!ptr) return NULL; - dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", + dprintf(stderr, "%s, %s calling __bound_new_region(%p, %p)\n", __FILE__, __FUNCTION__, ptr, size); __bound_new_region(ptr, size); @@ -862,8 +862,8 @@ static void bound_dump(void) e = page + j; /* do not print invalid or empty entries */ if (e->size != EMPTY_SIZE && e->start != 0) { - fprintf(stderr, "%08x:", - (i << (BOUND_T2_BITS + BOUND_T3_BITS)) + + fprintf(stderr, "%08x:", + (i << (BOUND_T2_BITS + BOUND_T3_BITS)) + (j << BOUND_T3_BITS)); do { fprintf(stderr, " %08lx:%08lx", e->start, e->start + e->size); diff --git a/lib/libtcc1.c b/lib/libtcc1.c index 69d111b..ece6413 100644 --- a/lib/libtcc1.c +++ b/lib/libtcc1.c @@ -1,5 +1,5 @@ -/* TCC runtime library. - Parts of this code are (c) 2002 Fabrice Bellard +/* TCC runtime library. + Parts of this code are (c) 2002 Fabrice Bellard Copyright (C) 1987, 1988, 1992, 1994, 1995 Free Software Foundation, Inc. @@ -25,7 +25,7 @@ General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. +Boston, MA 02111-1307, USA. */ #include @@ -370,10 +370,10 @@ long long __divdi3(long long u, long long v) int c = 0; DWunion uu, vv; DWtype w; - + uu.ll = u; vv.ll = v; - + if (uu.s.high < 0) { c = ~c; uu.ll = __negdi2 (uu.ll); @@ -393,17 +393,17 @@ long long __moddi3(long long u, long long v) int c = 0; DWunion uu, vv; DWtype w; - + uu.ll = u; vv.ll = v; - + if (uu.s.high < 0) { c = ~c; uu.ll = __negdi2 (uu.ll); } if (vv.s.high < 0) vv.ll = __negdi2 (vv.ll); - + __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) &w); if (c) w = __negdi2 (w); @@ -418,7 +418,7 @@ unsigned long long __udivdi3(unsigned long long u, unsigned long long v) unsigned long long __umoddi3(unsigned long long u, unsigned long long v) { UDWtype w; - + __udivmoddi4 (u, v, &w); return w; } @@ -499,7 +499,7 @@ long long __tcc_cvt_ftol(long double x) /* XXX: fix tcc's code generator to do this instead */ float __floatundisf(unsigned long long a) { - DWunion uu; + DWunion uu; XFtype r; uu.ll = a; @@ -514,7 +514,7 @@ float __floatundisf(unsigned long long a) double __floatundidf(unsigned long long a) { - DWunion uu; + DWunion uu; XFtype r; uu.ll = a; @@ -529,7 +529,7 @@ double __floatundidf(unsigned long long a) long double __floatundixf(unsigned long long a) { - DWunion uu; + DWunion uu; XFtype r; uu.ll = a; @@ -608,7 +608,7 @@ unsigned long long __fixunsxfdi (long double a1) if (exp > 0) return (unsigned long long)-1; - else if (exp >= -63) + else if (exp >= -63) return l >> -exp; else return 0; diff --git a/src/libtcc.c b/libtcc.c similarity index 99% rename from src/libtcc.c rename to libtcc.c index 1497637..df98bb0 100644 --- a/src/libtcc.c +++ b/libtcc.c @@ -40,24 +40,24 @@ ST_DATA struct TCCState *tcc_state; #include "tccelf.c" #include "tccrun.c" #ifdef TCC_TARGET_I386 -#include "x86/i386-gen.c" +#include "i386-gen.c" #endif #ifdef TCC_TARGET_ARM -#include "arm/arm-gen.c" +#include "arm-gen.c" #endif #ifdef TCC_TARGET_ARM64 -#include "arm/arm64-gen.c" +#include "arm64-gen.c" #endif #ifdef TCC_TARGET_C67 -#include "tms320c67/c67-gen.c" +#include "c67-gen.c" #endif #ifdef TCC_TARGET_X86_64 -#include "x86/x86_64-gen.c" +#include "x86_64-gen.c" #endif #ifdef CONFIG_TCC_ASM #include "tccasm.c" #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 -#include "x86/i386-asm.c" +#include "i386-asm.c" #endif #endif #ifdef TCC_TARGET_COFF @@ -318,7 +318,7 @@ PUB_FUNC void tcc_free_debug(void *ptr) mem_cur_size -= header->size; header->size = (size_t)-1; - + if (header->next) header->next->prev = header->prev; @@ -672,7 +672,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, } #else if (! (sym->type.t & VT_STATIC)) - other = (sym->type.t & VT_VIS_MASK) >> VT_VIS_SHIFT; + other = (sym->type.t & VT_VIS_MASK) >> VT_VIS_SHIFT; #endif if (tcc_state->leading_underscore && can_add_underscore) { buf1[0] = '_'; @@ -2101,11 +2101,11 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) s->static_link = 1; break; case TCC_OPTION_std: - /* silently ignore, a current purpose: - allow to use a tcc as a reference compiler for "make test" */ + /* silently ignore, a current purpose: + allow to use a tcc as a reference compiler for "make test" */ break; case TCC_OPTION_shared: - if (s->output_type) + if (s->output_type) tcc_warning("-shared: some compiler action already specified (%d)", s->output_type); s->output_type = TCC_OUTPUT_DLL; break; @@ -2124,7 +2124,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) break; case TCC_OPTION_r: /* generate a .o merging several output files */ - if (s->output_type) + if (s->output_type) tcc_warning("-r: some compiler action already specified (%d)", s->output_type); s->option_r = 1; s->output_type = TCC_OUTPUT_OBJ; @@ -2163,7 +2163,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) s->print_search_dirs = 1; break; case TCC_OPTION_run: - if (s->output_type) + if (s->output_type) tcc_warning("-run: some compiler action already specified (%d)", s->output_type); s->output_type = TCC_OUTPUT_MEMORY; tcc_set_options(s, optarg); @@ -2194,7 +2194,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) cstr_ccat(&linker_arg, '\0'); break; case TCC_OPTION_E: - if (s->output_type) + if (s->output_type) tcc_warning("-E: some compiler action already specified (%d)", s->output_type); s->output_type = TCC_OUTPUT_PREPROCESS; break; @@ -2251,13 +2251,13 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) } if (s->output_type == 0) - s->output_type = TCC_OUTPUT_EXE; + s->output_type = TCC_OUTPUT_EXE; if (pthread && s->output_type != TCC_OUTPUT_OBJ) tcc_set_options(s, "-lpthread"); if (s->output_type == TCC_OUTPUT_EXE) - tcc_set_linker(s, (const char *)linker_arg.data); + tcc_set_linker(s, (const char *)linker_arg.data); cstr_free(&linker_arg); return optind; diff --git a/src/libtcc.h b/libtcc.h similarity index 100% rename from src/libtcc.h rename to libtcc.h diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index 1352bfd..0000000 --- a/src/Makefile +++ /dev/null @@ -1,421 +0,0 @@ -# -# Tiny C Compiler Makefile -# - -TOP ?= . -include $(TOP)/../config.mak -VPATH = $(top_srcdir) - -CPPFLAGS += -I$(TOP) # for config.h - -ifneq (-$(findstring gcc,$(CC))-,-gcc-) -ifeq (-$(findstring clang,$(CC))-,-clang-) -# make clang accept gnuisms in libtcc1.c -CFLAGS+=-fheinous-gnu-extensions -endif -endif - -CPPFLAGS_P=$(CPPFLAGS) -DCONFIG_TCC_STATIC -CFLAGS_P=$(CFLAGS) -pg -static -LIBS_P= -LDFLAGS_P=$(LDFLAGS) - -ifdef CONFIG_WIN64 -CONFIG_WIN32=yes -endif - -ifndef CONFIG_WIN32 -LIBS=-lm -ifndef CONFIG_NOLDL -LIBS+=-ldl -endif -endif - -# make libtcc as static or dynamic library? -ifdef DISABLE_STATIC -ifndef CONFIG_WIN32 -LIBTCC=libtcc.so.1.0 -else -LIBTCC=libtcc.dll -LIBTCC_DLL=yes -LIBTCC_EXTRA=libtcc.def libtcc.a -endif -LINK_LIBTCC=-Wl,-rpath,"$(libdir)" -ifdef DISABLE_RPATH -LINK_LIBTCC= -endif -else -LIBTCC=libtcc.a -LINK_LIBTCC= -endif - -CONFIG_$(ARCH) = yes -NATIVE_DEFINES_$(CONFIG_i386) += -DTCC_TARGET_I386 -NATIVE_DEFINES_$(CONFIG_x86-64) += -DTCC_TARGET_X86_64 -NATIVE_DEFINES_$(CONFIG_WIN32) += -DTCC_TARGET_PE -NATIVE_DEFINES_$(CONFIG_uClibc) += -DTCC_UCLIBC -NATIVE_DEFINES_$(CONFIG_arm) += -DTCC_TARGET_ARM -NATIVE_DEFINES_$(CONFIG_arm_eabihf) += -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT -NATIVE_DEFINES_$(CONFIG_arm_eabi) += -DTCC_ARM_EABI -NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP -NATIVE_DEFINES_$(CONFIG_arm64) += -DTCC_TARGET_ARM64 -NATIVE_DEFINES += $(NATIVE_DEFINES_yes) - -ifeq ($(TOP),.) - -PROGS=tcc$(EXESUF) -I386_CROSS = i386-linux-gnu-tcc$(EXESUF) -WIN32_CROSS = i386-win-mingw32-tcc$(EXESUF) -WIN64_CROSS = x86_64-win-mingw32-tcc$(EXESUF) -WINCE_CROSS = arm-win-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) -ARM64_CROSS = arm64-tcc$(EXESUF) -C67_CROSS = c67-tcc$(EXESUF) - -# Legacy symlinks for cross compilers -$(I386_CROSS)_LINK = i386-tcc$(EXESUF) -$(WIN32_CROSS)_LINK = i386-win-tcc$(EXESUF) -$(WIN64_CROSS)_LINK = x86_64-win-tcc$(EXESUF) -$(WINCE_CROSS)_LINK = arm-win-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) - -ifeq ($(TARGETOS),Windows) -ifeq ($(ARCH),i386) -PROGS:=$($(WIN32_CROSS)_LINK) -$($(WIN32_CROSS)_LINK)_TCC = yes -endif -ifeq ($(ARCH),x86-64) -PROGS:=$($(WIN64_CROSS)_LINK) -$($(WIN64_CROSS)_LINK)_TCC = yes -endif -endif - -ifeq ($(TARGETOS),Linux) -ifeq ($(ARCH),i386) -PROGS:=$($(I386_CROSS)_LINK) -$($(I386_CROSS)_LINK)_TCC = yes -endif -ifeq ($(ARCH),x86-64) -PROGS:=$($(X64_CROSS)_LINK) -$($(X64_CROSS)_LINK)_TCC = yes -endif -endif - -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) x86/i386-gen.c x86/i386-asm.c x86/i386-asm.h x86/i386-tok.h -WIN32_FILES = $(CORE_FILES) x86/i386-gen.c x86/i386-asm.c x86/i386-asm.h x86/i386-tok.h tccpe.c -WIN64_FILES = $(CORE_FILES) x86/x86_64-gen.c x86/i386-asm.c x86/x86_64-asm.h tccpe.c -WINCE_FILES = $(CORE_FILES) arm/arm-gen.c tccpe.c -X86_64_FILES = $(CORE_FILES) x86/x86_64-gen.c x86/i386-asm.c x86/x86_64-asm.h -ARM_FILES = $(CORE_FILES) arm/arm-gen.c -ARM64_FILES = $(CORE_FILES) arm/arm64-gen.c -C67_FILES = $(CORE_FILES) tms320c67/c67-gen.c tcccoff.c - -ifdef CONFIG_WIN64 -PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF) -NATIVE_FILES=$(WIN64_FILES) -PROGS_CROSS=$(WIN32_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) -LIBTCC1_CROSS=lib/i386-win/libtcc1.a -LIBTCC1=libtcc1.a -else ifdef CONFIG_WIN32 -PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF) -NATIVE_FILES=$(WIN32_FILES) -PROGS_CROSS=$(WIN64_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) -LIBTCC1_CROSS=lib/x86_64-win/libtcc1.a -LIBTCC1=libtcc1.a -else ifeq ($(ARCH),i386) -NATIVE_FILES=$(I386_FILES) -PROGS_CROSS=$($(X64_CROSS)_LINK) $($(WIN32_CROSS)_LINK) $($(WIN64_CROSS)_LINK) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) -LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/libtcc1.a lib/i386/libtcc1.a lib/x86_64/libtcc1.a \ - lib/arm64/libtcc1.a -LIBTCC1=libtcc1.a -else ifeq ($(ARCH),x86-64) -ifeq ($(TARGETOS),Darwin) -NATIVE_FILES=$(X86_64_FILES) -PROGS_CROSS=$($(I386_CROSS)_LINK) $($(WIN32_CROSS)_LINK) $($(WIN64_CROSS)_LINK) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS) -LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/libtcc1.a lib/i386/libtcc1.a lib/x86_64/libtcc1.a -LIBTCC1=libtcc1.a -else -NATIVE_FILES=$(X86_64_FILES) -PROGS_CROSS=$($(I386_CROSS)_LINK) $($(WIN32_CROSS)_LINK) $($(WIN64_CROSS)_LINK) $(ARM_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) -LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/libtcc1.a lib/i386/libtcc1.a lib/x86_64/libtcc1.a \ - lib/arm64/libtcc1.a -LIBTCC1=libtcc1.a -endif -else ifeq ($(ARCH),arm) -NATIVE_FILES=$(ARM_FILES) -PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM64_CROSS) $(C67_CROSS) $(WINCE_CROSS) -LIBTCC1=libtcc1.a -LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/libtcc1.a lib/i386/libtcc1.a -else ifeq ($(ARCH),arm64) -NATIVE_FILES=$(ARM64_FILES) -PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS) $(WINCE_CROSS) -LIBTCC1=libtcc1.a -LIBTCC1_CROSS=lib/i386-win/libtcc1.a lib/x86_64-win/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 - -TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCC_EXTRA) -TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info - -ifdef CONFIG_CROSS -PROGS+=$(PROGS_CROSS) -TCCLIBS+=$(LIBTCC1_CROSS) -endif - -all: $(PROGS) $(TCCLIBS) $(TCCDOCS) - -# Host Tiny C Compiler -tcc$(EXESUF): tcc.o $(LIBTCC) - $(CC) -o $@ $^ $(LIBS) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LINK_LIBTCC) - -# Cross Tiny C Compilers -%-tcc$(EXESUF): tcc.c - $(CC) -o $@ $< -DONE_SOURCE $(if $($@_TCC),$(NATIVE_DEFINES),$(DEFINES)) $(CPPFLAGS) $(CFLAGS) $(LIBS) $(LDFLAGS) - $(if $($@_LINK),ln -sf $@ $($@_LINK)) - $(if $($@_TCC),ln -sf $@ tcc$(EXESUF)) - -# profiling version -tcc_p$(EXESUF): $(NATIVE_FILES) - $(CC) -o $@ $< -DONE_SOURCE $(NATIVE_DEFINES) $(CPPFLAGS_P) $(CFLAGS_P) $(LIBS_P) $(LDFLAGS_P) - -$(I386_CROSS) $($(I386_CROSS)_LINK): DEFINES = -DTCC_TARGET_I386 -$(X64_CROSS) $($(X64_CROSS)_LINK): DEFINES = -DTCC_TARGET_X86_64 -$(WIN32_CROSS) $($(WIN32_CROSS)_LINK): DEFINES = -DTCC_TARGET_I386 -DTCC_TARGET_PE \ - -DCONFIG_TCCDIR="\"$(tccdir)/win32\"" \ - -DCONFIG_TCC_LIBPATHS="\"{B}/lib/32;{B}/lib\"" -$(WIN64_CROSS) $($(WIN64_CROSS)_LINK): DEFINES = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE \ - -DCONFIG_TCCDIR="\"$(tccdir)/win32\"" \ - -DCONFIG_TCC_LIBPATHS="\"{B}/lib/64;{B}/lib\"" -$(WINCE_CROSS): DEFINES = -DTCC_TARGET_PE -$(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 -DTCC_ARM_VFP -$(ARM64_CROSS): DEFINES = -DTCC_TARGET_ARM64 - -$(I386_CROSS) $($(I386_CROSS)_LINK): $(I386_FILES) -$(X64_CROSS) $($(X64_CROSS)_LINK): $(X86_64_FILES) -$(WIN32_CROSS) $($(WIN32_CROSS)_LINK): $(WIN32_FILES) -$(WIN64_CROSS) $($(WIN64_CROSS)_LINK): $(WIN64_FILES) -$(WINCE_CROSS) $($(WINCE_CROSS)_LINK): $(WINCE_FILES) -$(C67_CROSS) $($(C67_CROSS)_LINK): $(C67_FILES) -$(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CROSS): $(ARM_FILES) -$($(ARM_FPA_CROSS)_LINK) $($(ARM_FPA_LD_CROSS)_LINK) $($(ARM_VFP_CROSS)_LINK) $($(ARM_EABI_CROSS)_LINK): $(ARM_FILES) -$(ARM64_CROSS): $(ARM64_FILES) - -# libtcc generation and test -ifndef ONE_SOURCE -LIBTCC_OBJ = $(filter-out tcc.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES)))) -LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES),$(NATIVE_FILES)) -else -LIBTCC_OBJ = libtcc.o -LIBTCC_INC = $(NATIVE_FILES) -libtcc.o : NATIVE_DEFINES += -DONE_SOURCE -endif - -$(LIBTCC_OBJ) tcc.o : %.o : %.c $(LIBTCC_INC) - $(CC) -o $@ -c $< $(NATIVE_DEFINES) $(CPPFLAGS) $(CFLAGS) - -ifndef LIBTCC_DLL -libtcc.a: $(LIBTCC_OBJ) - $(AR) rcs $@ $^ -endif - -libtcc.so.1.0: $(LIBTCC_OBJ) - $(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDFLAGS) - -libtcc.so.1.0: CFLAGS+=-fPIC - -ifdef LIBTCC_DLL -libtcc.dll libtcc.def libtcc.a: $(LIBTCC_OBJ) - $(CC) -shared $^ -o $@ $(LDFLAGS) -Wl,--output-def,libtcc.def,--out-implib,libtcc.a -endif - -# windows utilities -tiny_impdef$(EXESUF): ../win32/tools/tiny_impdef.c - $(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -tiny_libmaker$(EXESUF): ../win32/tools/tiny_libmaker.c - $(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) - -# TinyCC runtime libraries -libtcc1.a : FORCE - $(MAKE) -C ../lib native - if test ! -d $(ARCH); then mkdir $(ARCH); fi - if test ! -L $(ARCH)/$@; then ln -sf ../$@ $(ARCH)/$@; fi -lib/%/libtcc1.a : FORCE $(PROGS_CROSS) - $(MAKE) -C ../lib cross TARGET=$* - -FORCE: - -# install -TCC_INCLUDES = stdarg.h stddef.h stdbool.h float.h varargs.h -INSTALL=install -ifdef STRIP_BINARIES -INSTALLBIN=$(INSTALL) -s -else -INSTALLBIN=$(INSTALL) -endif - -install-strip: install - strip $(foreach PROG,$(PROGS),"$(bindir)"/$(PROG)) - -ifndef CONFIG_WIN32 -install: $(PROGS) $(TCCLIBS) $(TCCDOCS) - mkdir -p "$(bindir)" - $(INSTALLBIN) -m755 $(PROGS) "$(bindir)" - cp -P tcc$(EXESUF) "$(bindir)" - mkdir -p "$(mandir)/man1" - -$(INSTALL) -m644 tcc.1 "$(mandir)/man1" - mkdir -p "$(infodir)" - -$(INSTALL) -m644 tcc-doc.info "$(infodir)" - mkdir -p "$(tccdir)" - mkdir -p "$(tccdir)/include" -ifneq ($(LIBTCC1),) - mkdir -p "$(tccdir)/$(ARCH)" - $(INSTALL) -m644 $(LIBTCC1) "$(tccdir)/$(ARCH)" -endif - $(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) $(top_srcdir)/tcclib.h "$(tccdir)/include" - mkdir -p "$(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" -endif - mkdir -p "$(includedir)" - $(INSTALL) -m644 $(top_srcdir)/libtcc.h "$(includedir)" - mkdir -p "$(docdir)" - -$(INSTALL) -m644 tcc-doc.html "$(docdir)" -ifdef CONFIG_CROSS - mkdir -p "$(tccdir)/win32/lib/32" - mkdir -p "$(tccdir)/win32/lib/64" - mkdir -p "$(tccdir)/i386" - mkdir -p "$(tccdir)/x86-64" -ifneq ($(HOST_OS),Darwin) - mkdir -p "$(tccdir)/arm64" - $(INSTALL) -m644 lib/arm64/libtcc1.a "$(tccdir)/arm64" -endif - $(INSTALL) -m644 lib/i386/libtcc1.a "$(tccdir)/i386" - $(INSTALL) -m644 lib/x86_64/libtcc1.a "$(tccdir)/x86-64" - $(INSTALL) -m644 $(top_srcdir)/win32/lib/*.def "$(tccdir)/win32/lib" - $(INSTALL) -m644 lib/i386-win/libtcc1.a "$(tccdir)/win32/lib/32" - $(INSTALL) -m644 lib/x86_64-win/libtcc1.a "$(tccdir)/win32/lib/64" - cp -r $(top_srcdir)/win32/include/. "$(tccdir)/win32/include" - cp -r "$(tccdir)/include" "$(tccdir)/win32" -endif - -uninstall: - rm -fv $(foreach P,$(PROGS),"$(bindir)/$P") - rm -fv "$(bindir)/tcc$(EXESUF)" - rm -fv $(foreach P,$(LIBTCC1),"$(tccdir)/$P") - rm -fv $(foreach P,$(TCC_INCLUDES),"$(tccdir)/include/$P") - rm -fv "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info" - rm -fv "$(libdir)/$(LIBTCC)" "$(includedir)/libtcc.h" - rm -fv "$(libdir)/libtcc.so*" - rm -rv "$(tccdir)" - rm -rv "$(docdir)" -else -# on windows -install: $(PROGS) $(TCCLIBS) $(TCCDOCS) - mkdir -p "$(tccdir)" - mkdir -p "$(tccdir)/lib" - mkdir -p "$(tccdir)/include" - mkdir -p "$(tccdir)/examples" - mkdir -p "$(tccdir)/doc" - mkdir -p "$(tccdir)/libtcc" - $(INSTALLBIN) -m755 $(PROGS) "$(tccdir)" - $(INSTALLBIN) -m755 tcc.exe "$(tccdir)" - $(INSTALL) -m644 $(LIBTCC1) $(top_srcdir)/win32/lib/*.def "$(tccdir)/lib" - cp -r $(top_srcdir)/win32/include/. "$(tccdir)/include" - cp -r $(top_srcdir)/win32/examples/. "$(tccdir)/examples" - $(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) $(top_srcdir)/tcclib.h "$(tccdir)/include" - $(INSTALL) -m644 tcc-doc.html $(top_srcdir)/win32/tcc-win32.txt "$(tccdir)/doc" - $(INSTALL) -m644 $(top_srcdir)/libtcc.h $(LIBTCC_EXTRA) "$(tccdir)/libtcc" - $(INSTALL) -m644 $(LIBTCC) "$(tccdir)" -ifdef CONFIG_CROSS - mkdir -p "$(tccdir)/lib/32" - mkdir -p "$(tccdir)/lib/64" - -$(INSTALL) -m644 lib/i386-win/libtcc1.a "$(tccdir)/lib/32" - -$(INSTALL) -m644 lib/x86_64-win/libtcc1.a "$(tccdir)/lib/64" -endif - -uninstall: - rm -rfv "$(tccdir)/*" -endif - -# documentation and man page -tcc-doc.html: ../docs/tcc-doc.texi - -makeinfo --no-split --html --number-sections -o $@ $< - -tcc.1: ../docs/tcc-doc.texi - -$(top_srcdir)/../docs/texi2pod.pl $< tcc.pod - -pod2man --section=1 --center="Tiny C Compiler" --release=`cat $(top_srcdir)/../VERSION` tcc.pod > $@ - -tcc-doc.info: ../docs/tcc-doc.texi - -makeinfo $< - -# in tests subdir -export LIBTCC1 - -%est: - $(MAKE) -C ../tests $@ 'PROGS_CROSS=$(PROGS_CROSS)' - -clean: - rm -vf $(PROGS) tcc_p$(EXESUF) tcc.pod *~ *.o *.a *.so* *.out *.log \ - *.exe a.out tags TAGS libtcc_test$(EXESUF) tcc$(EXESUF) - -rm -r $(ARCH) arm64 -ifeq ($(HOST_OS),Linux) - -rm -r ./C: -endif - -rm *-tcc$(EXESUF) - $(MAKE) -C ../tests $@ -ifneq ($(LIBTCC1),) - $(MAKE) -C ../lib $@ -endif - -distclean: clean - rm -vf config.h config.mak config.texi tcc.1 tcc-doc.info tcc-doc.html - -config.mak: - @echo "Please run ./configure." - @exit 1 - -tags: - ctags $(top_srcdir)/*.[ch] $(top_srcdir)/include/*.h $(top_srcdir)/lib/*.[chS] - -TAGS: - ctags -e $(top_srcdir)/*.[ch] $(top_srcdir)/include/*.h $(top_srcdir)/lib/*.[chS] - -# create release tarball from *current* git branch (including tcc-doc.html -# and converting two files to CRLF) -TCC-VERSION := tcc-$(shell cat $(top_srcdir)/../VERSION) -tar: tcc-doc.html - mkdir $(TCC-VERSION) - ( cd $(TCC-VERSION) && git --git-dir ../.git checkout -f ) - cp tcc-doc.html $(TCC-VERSION) - for f in tcc-win32.txt build-tcc.bat ; do \ - cat win32/$$f | sed 's,\(.*\),\1\r,g' > $(TCC-VERSION)/win32/$$f ; \ - done - tar cjf $(TCC-VERSION).tar.bz2 $(TCC-VERSION) - rm -rf $(TCC-VERSION) - git reset - -.PHONY: all clean tar tags TAGS distclean install uninstall FORCE - -endif # ifeq ($(TOP),.) diff --git a/src/arm/arm-gen.c b/src/arm/arm-gen.c deleted file mode 100644 index cf2d968..0000000 --- a/src/arm/arm-gen.c +++ /dev/null @@ -1,2162 +0,0 @@ -/* - * ARMv4 code generator for TCC - * - * Copyright (c) 2003 Daniel Glöckner - * Copyright (c) 2012 Thomas Preud'homme - * - * Based on i386-gen.c by Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef TARGET_DEFS_ONLY - -#if defined(TCC_ARM_EABI) && !defined(TCC_ARM_VFP) -#error "Currently TinyCC only supports float computation with VFP instructions" -#endif - -/* number of available registers */ -#ifdef TCC_ARM_VFP -#define NB_REGS 13 -#else -#define NB_REGS 9 -#endif - -typedef int RegArgs; - -#ifndef TCC_ARM_VERSION -#define TCC_ARM_VERSION 5 -#endif - -/* a register can belong to several classes. The classes must be - sorted from more general to more precise (see gv2() code which does - assumptions on it). */ -#define RC_INT 0x0001 /* generic integer register */ -#define RC_FLOAT 0x0002 /* generic float register */ -#define RC_R0 0x0004 -#define RC_R1 0x0008 -#define RC_R2 0x0010 -#define RC_R3 0x0020 -#define RC_R12 0x0040 -#define RC_F0 0x0080 -#define RC_F1 0x0100 -#define RC_F2 0x0200 -#define RC_F3 0x0400 -#ifdef TCC_ARM_VFP -#define RC_F4 0x0800 -#define RC_F5 0x1000 -#define RC_F6 0x2000 -#define RC_F7 0x4000 -#endif -#define RC_IRET RC_R0 /* function return: integer register */ -#define RC_LRET RC_R1 /* function return: second integer register */ -#define RC_FRET RC_F0 /* function return: float register */ - -/* pretty names for the registers */ -enum { - TREG_R0 = 0, - TREG_R1, - TREG_R2, - TREG_R3, - TREG_R12, - TREG_F0, - TREG_F1, - TREG_F2, - TREG_F3, -#ifdef TCC_ARM_VFP - TREG_F4, - TREG_F5, - TREG_F6, - TREG_F7, -#endif -}; - -#ifdef TCC_ARM_VFP -#define T2CPR(t) (((t)&VT_BTYPE) != VT_FLOAT ? 0x100 : 0) -#endif - -/* return registers for function */ -#define REG_IRET TREG_R0 /* single word int return register */ -#define REG_LRET TREG_R1 /* second word return register (for long long) */ -#define REG_FRET TREG_F0 /* float return register */ - -#ifdef TCC_ARM_EABI -#define TOK___divdi3 TOK___aeabi_ldivmod -#define TOK___moddi3 TOK___aeabi_ldivmod -#define TOK___udivdi3 TOK___aeabi_uldivmod -#define TOK___umoddi3 TOK___aeabi_uldivmod -#endif - -/* defined if function parameters must be evaluated in reverse order */ -#define INVERT_FUNC_PARAMS - -/* defined if structures are passed as pointers. Otherwise structures - are directly pushed on stack. */ -/* #define FUNC_STRUCT_PARAM_AS_PTR */ - -/* pointer size, in bytes */ -#define PTR_SIZE 4 - -/* long double size and alignment, in bytes */ -#ifdef TCC_ARM_VFP -#define LDOUBLE_SIZE 8 -#endif - -#ifndef LDOUBLE_SIZE -#define LDOUBLE_SIZE 8 -#endif - -#ifdef TCC_ARM_EABI -#define LDOUBLE_ALIGN 8 -#else -#define LDOUBLE_ALIGN 4 -#endif - -/* maximum alignment (for aligned attribute support) */ -#define MAX_ALIGN 8 - -#define CHAR_IS_UNSIGNED - -/******************************************************/ -/* ELF defines */ - -#define EM_TCC_TARGET EM_ARM - -/* relocation type for 32 bit data relocation */ -#define R_DATA_32 R_ARM_ABS32 -#define R_DATA_PTR R_ARM_ABS32 -#define R_JMP_SLOT R_ARM_JUMP_SLOT -#define R_COPY R_ARM_COPY - -#define ELF_START_ADDR 0x00008000 -#define ELF_PAGE_SIZE 0x1000 - -enum float_abi { - ARM_SOFTFP_FLOAT, - ARM_HARD_FLOAT, -}; - -/******************************************************/ -#else /* ! TARGET_DEFS_ONLY */ -/******************************************************/ -#include "../tcc.h" - -enum float_abi float_abi; - -ST_DATA const int reg_classes[NB_REGS] = { - /* r0 */ RC_INT | RC_R0, - /* r1 */ RC_INT | RC_R1, - /* r2 */ RC_INT | RC_R2, - /* r3 */ RC_INT | RC_R3, - /* r12 */ RC_INT | RC_R12, - /* f0 */ RC_FLOAT | RC_F0, - /* f1 */ RC_FLOAT | RC_F1, - /* f2 */ RC_FLOAT | RC_F2, - /* f3 */ RC_FLOAT | RC_F3, -#ifdef TCC_ARM_VFP - /* d4/s8 */ RC_FLOAT | RC_F4, - /* d5/s10 */ RC_FLOAT | RC_F5, - /* d6/s12 */ RC_FLOAT | RC_F6, - /* d7/s14 */ RC_FLOAT | RC_F7, -#endif -}; - -static int func_sub_sp_offset, last_itod_magic; -static int leaffunc; - -#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) -static CType float_type, double_type, func_float_type, func_double_type; -ST_FUNC void arm_init(struct TCCState* s) -{ - float_type.t = VT_FLOAT; - double_type.t = VT_DOUBLE; - func_float_type.t = VT_FUNC; - func_float_type.ref = - sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD); - func_double_type.t = VT_FUNC; - func_double_type.ref = - sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD); - - float_abi = s->float_abi; -#ifndef TCC_ARM_HARDFLOAT - tcc_warning("soft float ABI currently not supported: default to softfp"); -#endif -} -#else -#define func_float_type func_old_type -#define func_double_type func_old_type -#define func_ldouble_type func_old_type -ST_FUNC void arm_init(struct TCCState* s) -{ -#if !defined(TCC_ARM_VFP) - tcc_warning("Support for FPA is deprecated and will be removed in next" - " release"); -#endif -#if !defined(TCC_ARM_EABI) - tcc_warning("Support for OABI is deprecated and will be removed in next" - " release"); -#endif -} -#endif - -static int two2mask(int a, int b) -{ - return (reg_classes[a] | reg_classes[b]) & ~(RC_INT | RC_FLOAT); -} - -static int regmask(int r) -{ - return reg_classes[r] & ~(RC_INT | RC_FLOAT); -} - -/******************************************************/ - -#if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP) -char* default_elfinterp(struct TCCState* s) -{ - if (s->float_abi == ARM_HARD_FLOAT) - return "/lib/ld-linux-armhf.so.3"; - else - return "/lib/ld-linux.so.3"; -} -#endif - -void o(uint32_t i) -{ - /* this is a good place to start adding big-endian support*/ - int ind1; - - ind1 = ind + 4; - if (!cur_text_section) - tcc_error("compiler error! This happens f.ex. if the compiler\n" - "can't evaluate constant expressions outside of a function."); - if (ind1 > cur_text_section->data_allocated) - section_realloc(cur_text_section, ind1); - cur_text_section->data[ind++] = i & 255; - i >>= 8; - cur_text_section->data[ind++] = i & 255; - i >>= 8; - cur_text_section->data[ind++] = i & 255; - i >>= 8; - cur_text_section->data[ind++] = i; -} - -static uint32_t stuff_const(uint32_t op, uint32_t c) -{ - int try_neg = 0; - uint32_t nc = 0, negop = 0; - - switch (op & 0x1F00000) { - case 0x800000: // add - case 0x400000: // sub - try_neg = 1; - negop = op ^ 0xC00000; - nc = -c; - break; - case 0x1A00000: // mov - case 0x1E00000: // mvn - try_neg = 1; - negop = op ^ 0x400000; - nc = ~c; - break; - case 0x200000: // xor - if (c == ~0) - return (op & 0xF010F000) | ((op >> 16) & 0xF) | 0x1E00000; - break; - case 0x0: // and - if (c == ~0) - return (op & 0xF010F000) | ((op >> 16) & 0xF) | 0x1A00000; - case 0x1C00000: // bic - try_neg = 1; - negop = op ^ 0x1C00000; - nc = ~c; - break; - case 0x1800000: // orr - if (c == ~0) - return (op & 0xFFF0FFFF) | 0x1E00000; - break; - } - do { - uint32_t m; - int i; - if (c < 256) /* catch undefined <<32 */ - return op | c; - for (i = 2; i < 32; i += 2) { - m = (0xff >> i) | (0xff << (32 - i)); - if (!(c & ~m)) - return op | (i << 7) | (c << i) | (c >> (32 - i)); - } - op = negop; - c = nc; - } while (try_neg--); - return 0; -} - -// only add,sub -void stuff_const_harder(uint32_t op, uint32_t v) -{ - uint32_t x; - x = stuff_const(op, v); - if (x) - o(x); - else { - uint32_t a[16], nv, no, o2, n2; - int i, j, k; - a[0] = 0xff; - o2 = (op & 0xfff0ffff) | ((op & 0xf000) << 4); - ; - for (i = 1; i < 16; i++) - a[i] = (a[i - 1] >> 2) | (a[i - 1] << 30); - for (i = 0; i < 12; i++) - for (j = i < 4 ? i + 12 : 15; j >= i + 4; j--) - if ((v & (a[i] | a[j])) == v) { - o(stuff_const(op, v & a[i])); - o(stuff_const(o2, v & a[j])); - return; - } - no = op ^ 0xC00000; - n2 = o2 ^ 0xC00000; - nv = -v; - for (i = 0; i < 12; i++) - for (j = i < 4 ? i + 12 : 15; j >= i + 4; j--) - if ((nv & (a[i] | a[j])) == nv) { - o(stuff_const(no, nv & a[i])); - o(stuff_const(n2, nv & a[j])); - return; - } - for (i = 0; i < 8; i++) - for (j = i + 4; j < 12; j++) - for (k = i < 4 ? i + 12 : 15; k >= j + 4; k--) - if ((v & (a[i] | a[j] | a[k])) == v) { - o(stuff_const(op, v & a[i])); - o(stuff_const(o2, v & a[j])); - o(stuff_const(o2, v & a[k])); - return; - } - no = op ^ 0xC00000; - nv = -v; - for (i = 0; i < 8; i++) - for (j = i + 4; j < 12; j++) - for (k = i < 4 ? i + 12 : 15; k >= j + 4; k--) - if ((nv & (a[i] | a[j] | a[k])) == nv) { - o(stuff_const(no, nv & a[i])); - o(stuff_const(n2, nv & a[j])); - o(stuff_const(n2, nv & a[k])); - return; - } - o(stuff_const(op, v & a[0])); - o(stuff_const(o2, v & a[4])); - o(stuff_const(o2, v & a[8])); - o(stuff_const(o2, v & a[12])); - } -} - -ST_FUNC uint32_t encbranch(int pos, int addr, int fail) -{ - addr -= pos + 8; - addr /= 4; - if (addr >= 0x1000000 || addr < -0x1000000) { - if (fail) - tcc_error("FIXME: function bigger than 32MB"); - return 0; - } - return 0x0A000000 | (addr & 0xffffff); -} - -int decbranch(int pos) -{ - int x; - x = *(uint32_t*)(cur_text_section->data + pos); - x &= 0x00ffffff; - if (x & 0x800000) - x -= 0x1000000; - return x * 4 + pos + 8; -} - -/* output a symbol and patch all calls to it */ -void gsym_addr(int t, int a) -{ - uint32_t* x; - int lt; - while (t) { - x = (uint32_t*)(cur_text_section->data + t); - t = decbranch(lt = t); - if (a == lt + 4) - *x = 0xE1A00000; // nop - else { - *x &= 0xff000000; - *x |= encbranch(lt, a, 1); - } - } -} - -void gsym(int t) -{ - gsym_addr(t, ind); -} - -#ifdef TCC_ARM_VFP -static uint32_t vfpr(int r) -{ - if (r < TREG_F0 || r > TREG_F7) - tcc_error("compiler error! register %i is no vfp register", r); - return r - 5; -} -#else -static uint32_t fpr(int r) -{ - if (r < TREG_F0 || r > TREG_F3) - tcc_error("compiler error! register %i is no fpa register", r); - return r - 5; -} -#endif - -static uint32_t intr(int r) -{ - if (r == 4) - return 12; - if ((r < 0 || r > 4) && r != 14) - tcc_error("compiler error! register %i is no int register", r); - return r; -} - -static void calcaddr(uint32_t* base, int* off, int* sgn, int maxoff, - unsigned shift) -{ - if (*off > maxoff || *off & ((1 << shift) - 1)) { - uint32_t x, y; - x = 0xE280E000; - if (*sgn) - x = 0xE240E000; - x |= (*base) << 16; - *base = 14; // lr - y = stuff_const(x, *off & ~maxoff); - if (y) { - o(y); - *off &= maxoff; - return; - } - y = stuff_const(x, (*off + maxoff) & ~maxoff); - if (y) { - o(y); - *sgn = !*sgn; - *off = ((*off + maxoff) & ~maxoff) - *off; - return; - } - stuff_const_harder(x, *off & ~maxoff); - *off &= maxoff; - } -} - -static uint32_t mapcc(int cc) -{ - switch (cc) { - case TOK_ULT: - return 0x30000000; /* CC/LO */ - case TOK_UGE: - return 0x20000000; /* CS/HS */ - case TOK_EQ: - return 0x00000000; /* EQ */ - case TOK_NE: - return 0x10000000; /* NE */ - case TOK_ULE: - return 0x90000000; /* LS */ - case TOK_UGT: - return 0x80000000; /* HI */ - case TOK_Nset: - return 0x40000000; /* MI */ - case TOK_Nclear: - return 0x50000000; /* PL */ - case TOK_LT: - return 0xB0000000; /* LT */ - case TOK_GE: - return 0xA0000000; /* GE */ - case TOK_LE: - return 0xD0000000; /* LE */ - case TOK_GT: - return 0xC0000000; /* GT */ - } - tcc_error("unexpected condition code"); - return 0xE0000000; /* AL */ -} - -static int negcc(int cc) -{ - switch (cc) { - case TOK_ULT: - return TOK_UGE; - case TOK_UGE: - return TOK_ULT; - case TOK_EQ: - return TOK_NE; - case TOK_NE: - return TOK_EQ; - case TOK_ULE: - return TOK_UGT; - case TOK_UGT: - return TOK_ULE; - case TOK_Nset: - return TOK_Nclear; - case TOK_Nclear: - return TOK_Nset; - case TOK_LT: - return TOK_GE; - case TOK_GE: - return TOK_LT; - case TOK_LE: - return TOK_GT; - case TOK_GT: - return TOK_LE; - } - tcc_error("unexpected condition code"); - return TOK_NE; -} - -/* load 'r' from value 'sv' */ -void load(int r, SValue* sv) -{ - int v, ft, fc, fr, sign; - uint32_t op; - SValue v1; - - fr = sv->r; - ft = sv->type.t; - fc = sv->c.ul; - - if (fc >= 0) - sign = 0; - else { - sign = 1; - fc = -fc; - } - - v = fr & VT_VALMASK; - if (fr & VT_LVAL) { - uint32_t base = 0xB; // fp - if (v == VT_LLOCAL) { - v1.type.t = VT_PTR; - v1.r = VT_LOCAL | VT_LVAL; - v1.c.ul = sv->c.ul; - load(base = 14 /* lr */, &v1); - fc = sign = 0; - v = VT_LOCAL; - } else if (v == VT_CONST) { - v1.type.t = VT_PTR; - v1.r = fr & ~VT_LVAL; - v1.c.ul = sv->c.ul; - v1.sym = sv->sym; - load(base = 14, &v1); - fc = sign = 0; - v = VT_LOCAL; - } else if (v < VT_CONST) { - base = intr(v); - fc = sign = 0; - v = VT_LOCAL; - } - if (v == VT_LOCAL) { - if (is_float(ft)) { - calcaddr(&base, &fc, &sign, 1020, 2); -#ifdef TCC_ARM_VFP - op = 0xED100A00; /* flds */ - if (!sign) - op |= 0x800000; - if ((ft & VT_BTYPE) != VT_FLOAT) - op |= 0x100; /* flds -> fldd */ - o(op | (vfpr(r) << 12) | (fc >> 2) | (base << 16)); -#else - op = 0xED100100; - if (!sign) - op |= 0x800000; -#if LDOUBLE_SIZE == 8 - if ((ft & VT_BTYPE) != VT_FLOAT) - op |= 0x8000; -#else - if ((ft & VT_BTYPE) == VT_DOUBLE) - op |= 0x8000; - else if ((ft & VT_BTYPE) == VT_LDOUBLE) - op |= 0x400000; -#endif - o(op | (fpr(r) << 12) | (fc >> 2) | (base << 16)); -#endif - } else if ((ft & (VT_BTYPE | VT_UNSIGNED)) == VT_BYTE || - (ft & VT_BTYPE) == VT_SHORT) { - calcaddr(&base, &fc, &sign, 255, 0); - op = 0xE1500090; - if ((ft & VT_BTYPE) == VT_SHORT) - op |= 0x20; - if ((ft & VT_UNSIGNED) == 0) - op |= 0x40; - if (!sign) - op |= 0x800000; - o(op | (intr(r) << 12) | (base << 16) | ((fc & 0xf0) << 4) | - (fc & 0xf)); - } else { - calcaddr(&base, &fc, &sign, 4095, 0); - op = 0xE5100000; - if (!sign) - op |= 0x800000; - if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) - op |= 0x400000; - o(op | (intr(r) << 12) | fc | (base << 16)); - } - return; - } - } else { - if (v == VT_CONST) { - op = stuff_const(0xE3A00000 | (intr(r) << 12), sv->c.ul); - if (fr & VT_SYM || !op) { - o(0xE59F0000 | (intr(r) << 12)); - o(0xEA000000); - if (fr & VT_SYM) - greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); - o(sv->c.ul); - } else - o(op); - return; - } else if (v == VT_LOCAL) { - op = stuff_const(0xE28B0000 | (intr(r) << 12), sv->c.ul); - if (fr & VT_SYM || !op) { - o(0xE59F0000 | (intr(r) << 12)); - o(0xEA000000); - if (fr & VT_SYM) // needed ? - greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); - o(sv->c.ul); - o(0xE08B0000 | (intr(r) << 12) | intr(r)); - } else - o(op); - return; - } else if (v == VT_CMP) { - o(mapcc(sv->c.ul) | 0x3A00001 | (intr(r) << 12)); - o(mapcc(negcc(sv->c.ul)) | 0x3A00000 | (intr(r) << 12)); - return; - } else if (v == VT_JMP || v == VT_JMPI) { - int t; - t = v & 1; - o(0xE3A00000 | (intr(r) << 12) | t); - o(0xEA000000); - gsym(sv->c.ul); - o(0xE3A00000 | (intr(r) << 12) | (t ^ 1)); - return; - } else if (v < VT_CONST) { - if (is_float(ft)) -#ifdef TCC_ARM_VFP - o(0xEEB00A40 | (vfpr(r) << 12) | vfpr(v) | - T2CPR(ft)); /* fcpyX */ -#else - o(0xEE008180 | (fpr(r) << 12) | fpr(v)); -#endif - else - o(0xE1A00000 | (intr(r) << 12) | intr(v)); - return; - } - } - tcc_error("load unimplemented!"); -} - -/* store register 'r' in lvalue 'v' */ -void store(int r, SValue* sv) -{ - SValue v1; - int v, ft, fc, fr, sign; - uint32_t op; - - fr = sv->r; - ft = sv->type.t; - fc = sv->c.ul; - - if (fc >= 0) - sign = 0; - else { - sign = 1; - fc = -fc; - } - - v = fr & VT_VALMASK; - if (fr & VT_LVAL || fr == VT_LOCAL) { - uint32_t base = 0xb; - if (v < VT_CONST) { - base = intr(v); - v = VT_LOCAL; - fc = sign = 0; - } else if (v == VT_CONST) { - v1.type.t = ft; - v1.r = fr & ~VT_LVAL; - v1.c.ul = sv->c.ul; - v1.sym = sv->sym; - load(base = 14, &v1); - fc = sign = 0; - v = VT_LOCAL; - } - if (v == VT_LOCAL) { - if (is_float(ft)) { - calcaddr(&base, &fc, &sign, 1020, 2); -#ifdef TCC_ARM_VFP - op = 0xED000A00; /* fsts */ - if (!sign) - op |= 0x800000; - if ((ft & VT_BTYPE) != VT_FLOAT) - op |= 0x100; /* fsts -> fstd */ - o(op | (vfpr(r) << 12) | (fc >> 2) | (base << 16)); -#else - op = 0xED000100; - if (!sign) - op |= 0x800000; -#if LDOUBLE_SIZE == 8 - if ((ft & VT_BTYPE) != VT_FLOAT) - op |= 0x8000; -#else - if ((ft & VT_BTYPE) == VT_DOUBLE) - op |= 0x8000; - if ((ft & VT_BTYPE) == VT_LDOUBLE) - op |= 0x400000; -#endif - o(op | (fpr(r) << 12) | (fc >> 2) | (base << 16)); -#endif - return; - } else if ((ft & VT_BTYPE) == VT_SHORT) { - calcaddr(&base, &fc, &sign, 255, 0); - op = 0xE14000B0; - if (!sign) - op |= 0x800000; - o(op | (intr(r) << 12) | (base << 16) | ((fc & 0xf0) << 4) | - (fc & 0xf)); - } else { - calcaddr(&base, &fc, &sign, 4095, 0); - op = 0xE5000000; - if (!sign) - op |= 0x800000; - if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) - op |= 0x400000; - o(op | (intr(r) << 12) | fc | (base << 16)); - } - return; - } - } - tcc_error("store unimplemented"); -} - -static void gadd_sp(int val) -{ - stuff_const_harder(0xE28DD000, val); -} - -/* 'is_jmp' is '1' if it is a jump */ -static void gcall_or_jmp(int is_jmp) -{ - int r; - if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { - uint32_t x; - /* constant case */ - x = encbranch(ind, ind + vtop->c.ul, 0); - if (x) { - if (vtop->r & VT_SYM) { - /* relocation case */ - greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24); - } else - put_elf_reloc(symtab_section, cur_text_section, ind, R_ARM_PC24, - 0); - o(x | (is_jmp ? 0xE0000000 : 0xE1000000)); - } else { - if (!is_jmp) - o(0xE28FE004); // add lr,pc,#4 - o(0xE51FF004); // ldr pc,[pc,#-4] - if (vtop->r & VT_SYM) - greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32); - o(vtop->c.ul); - } - } else { - /* otherwise, indirect call */ - r = gv(RC_INT); - if (!is_jmp) - o(0xE1A0E00F); // mov lr,pc - o(0xE1A0F000 | intr(r)); // mov pc,r - } -} - -/* Return whether a structure is an homogeneous float aggregate or not. - The answer is true if all the elements of the structure are of the same - primitive float type and there is less than 4 elements. - - type: the type corresponding to the structure to be tested */ -static int is_hgen_float_aggr(CType* type) -{ - if ((type->t & VT_BTYPE) == VT_STRUCT) { - struct Sym* ref; - int btype, nb_fields = 0; - - ref = type->ref->next; - btype = ref->type.t & VT_BTYPE; - if (btype == VT_FLOAT || btype == VT_DOUBLE) { - for (; ref && btype == (ref->type.t & VT_BTYPE); - ref = ref->next, nb_fields++) - ; - return !ref && nb_fields <= 4; - } - } - return 0; -} - -struct avail_regs { - signed char - avail[3]; /* 3 holes max with only float and double alignments */ - int first_hole; /* first available hole */ - int last_hole; /* last available hole (none if equal to first_hole) */ - int first_free_reg; /* next free register in the sequence, hole excluded */ -}; - -#define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 } - -/* Find suitable registers for a VFP Co-Processor Register Candidate (VFP CPRC - param) according to the rules described in the procedure call standard for - the ARM architecture (AAPCS). If found, the registers are assigned to this - VFP CPRC parameter. Registers are allocated in sequence unless a hole exists - and the parameter is a single float. - - avregs: opaque structure to keep track of available VFP co-processor regs - align: alignment contraints for the param, as returned by type_size() - size: size of the parameter, as returned by type_size() */ -int assign_vfpreg(struct avail_regs* avregs, int align, int size) -{ - int first_reg = 0; - - if (avregs->first_free_reg == -1) - return -1; - if (align >> 3) { /* double alignment */ - first_reg = avregs->first_free_reg; - /* alignment contraint not respected so use next reg and record hole */ - if (first_reg & 1) - avregs->avail[avregs->last_hole++] = first_reg++; - } else { /* no special alignment (float or array of float) */ - /* if single float and a hole is available, assign the param to it */ - if (size == 4 && avregs->first_hole != avregs->last_hole) - return avregs->avail[avregs->first_hole++]; - else - first_reg = avregs->first_free_reg; - } - if (first_reg + size / 4 <= 16) { - avregs->first_free_reg = first_reg + size / 4; - return first_reg; - } - avregs->first_free_reg = -1; - return -1; -} - -/* Returns whether all params need to be passed in core registers or not. - This is the case for function part of the runtime ABI. */ -int floats_in_core_regs(SValue* sval) -{ - if (!sval->sym) - return 0; - - switch (sval->sym->v) { - case TOK___floatundisf: - case TOK___floatundidf: - case TOK___fixunssfdi: - case TOK___fixunsdfdi: -#ifndef TCC_ARM_VFP - case TOK___fixunsxfdi: -#endif - case TOK___floatdisf: - case TOK___floatdidf: - case TOK___fixsfdi: - case TOK___fixdfdi: - return 1; - - default: - return 0; - } -} - -ST_FUNC int regargs_nregs(RegArgs* args) -{ - return *args; -} - -/* 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* regsize, RegArgs* args) -{ -#ifdef TCC_ARM_EABI - int size, align; - size = type_size(vt, &align); - if (float_abi == ARM_HARD_FLOAT && !variadic && - (is_float(vt->t) || is_hgen_float_aggr(vt))) { - *ret_align = 8; - *regsize = 8; - ret->ref = NULL; - ret->t = VT_DOUBLE; - *args = (size + 7) >> 3; - } else if (size <= 4) { - *ret_align = 4; - *regsize = 4; - ret->ref = NULL; - ret->t = VT_INT; - *args = 1; - } else - *args = 0; -#else - *args = 0; -#endif - - return *args != 0; -} - -/* Parameters are classified according to how they are copied to their final - destination for the function call. Because the copying is performed class - after class according to the order in the union below, it is important that - some constraints about the order of the members of this union are respected: - - CORE_STRUCT_CLASS must come after STACK_CLASS; - - CORE_CLASS must come after STACK_CLASS, CORE_STRUCT_CLASS and - VFP_STRUCT_CLASS; - - VFP_STRUCT_CLASS must come after VFP_CLASS. - See the comment for the main loop in copy_params() for the reason. */ -enum reg_class { - STACK_CLASS = 0, - CORE_STRUCT_CLASS, - VFP_CLASS, - VFP_STRUCT_CLASS, - CORE_CLASS, - NB_CLASSES -}; - -struct param_plan { - int start; /* first reg or addr used depending on the class */ - int end; /* last reg used or next free addr depending on the class */ - SValue* sval; /* pointer to SValue on the value stack */ - struct param_plan* prev; /* previous element in this class */ -}; - -struct plan { - struct param_plan* pplans; /* array of all the param plans */ - struct param_plan* - clsplans[NB_CLASSES]; /* per class lists of param plans */ -}; - -#define add_param_plan(plan, pplan, class) \ - do { \ - pplan.prev = plan->clsplans[class]; \ - plan->pplans[plan##_nb] = pplan; \ - plan->clsplans[class] = &plan->pplans[plan##_nb++]; \ - } while (0) - -/* Assign parameters to registers and stack with alignment according to the - rules in the procedure call standard for the ARM architecture (AAPCS). - The overall assignment is recorded in an array of per parameter structures - called parameter plans. The parameter plans are also further organized in a - number of linked lists, one per class of parameter (see the comment for the - definition of union reg_class). - - nb_args: number of parameters of the function for which a call is generated - float_abi: float ABI in use for this function call - plan: the structure where the overall assignment is recorded - todo: a bitmap that record which core registers hold a parameter - - Returns the amount of stack space needed for parameter passing - - Note: this function allocated an array in plan->pplans with tcc_malloc. It - is the responsibility of the caller to free this array once used (ie not - before copy_params). */ -static int assign_regs(int nb_args, int float_abi, struct plan* plan, int* todo) -{ - int i, size, align; - int ncrn /* next core register number */, - nsaa /* next stacked argument address*/; - int plan_nb = 0; - struct param_plan pplan; - struct avail_regs avregs = AVAIL_REGS_INITIALIZER; - - ncrn = nsaa = 0; - *todo = 0; - plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans)); - memset(plan->clsplans, 0, sizeof(plan->clsplans)); - for (i = nb_args; i--;) { - int j, start_vfpreg = 0; - CType type = vtop[-i].type; - type.t &= ~VT_ARRAY; - size = type_size(&type, &align); - size = (size + 3) & ~3; - align = (align + 3) & ~3; - switch (vtop[-i].type.t & VT_BTYPE) { - case VT_STRUCT: - case VT_FLOAT: - case VT_DOUBLE: - case VT_LDOUBLE: - if (float_abi == ARM_HARD_FLOAT) { - int is_hfa = 0; /* Homogeneous float aggregate */ - - if (is_float(vtop[-i].type.t) || - (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) { - int end_vfpreg; - - start_vfpreg = assign_vfpreg(&avregs, align, size); - end_vfpreg = start_vfpreg + ((size - 1) >> 2); - if (start_vfpreg >= 0) { - pplan = (struct param_plan){start_vfpreg, end_vfpreg, - &vtop[-i]}; - if (is_hfa) - add_param_plan(plan, pplan, VFP_STRUCT_CLASS); - else - add_param_plan(plan, pplan, VFP_CLASS); - continue; - } else - break; - } - } - ncrn = (ncrn + (align - 1) / 4) & ~((align / 4) - 1); - if (ncrn + size / 4 <= 4 || (ncrn < 4 && start_vfpreg != -1)) { - /* The parameter is allocated both in core register and on - * stack. As - * such, it can be of either class: it would either be the last of - * CORE_STRUCT_CLASS or the first of STACK_CLASS. */ - for (j = ncrn; j < 4 && j < ncrn + size / 4; j++) - *todo |= (1 << j); - pplan = (struct param_plan){ncrn, j, &vtop[-i]}; - add_param_plan(plan, pplan, CORE_STRUCT_CLASS); - ncrn += size / 4; - if (ncrn > 4) - nsaa = (ncrn - 4) * 4; - } else { - ncrn = 4; - break; - } - continue; - default: - if (ncrn < 4) { - int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG; - - if (is_long) { - ncrn = (ncrn + 1) & -2; - if (ncrn == 4) - break; - } - pplan = (struct param_plan){ncrn, ncrn, &vtop[-i]}; - ncrn++; - if (is_long) - pplan.end = ncrn++; - add_param_plan(plan, pplan, CORE_CLASS); - continue; - } - } - nsaa = (nsaa + (align - 1)) & ~(align - 1); - pplan = (struct param_plan){nsaa, nsaa + size, &vtop[-i]}; - add_param_plan(plan, pplan, STACK_CLASS); - nsaa += size; /* size already rounded up before */ - } - return nsaa; -} - -#undef add_param_plan - -/* Copy parameters to their final destination (core reg, VFP reg or stack) for - function call. - - nb_args: number of parameters the function take - plan: the overall assignment plan for parameters - todo: a bitmap indicating what core reg will hold a parameter - - Returns the number of SValue added by this function on the value stack */ -static int copy_params(int nb_args, struct plan* plan, int todo) -{ - int size, align, r, i, nb_extra_sval = 0; - struct param_plan* pplan; - - /* Several constraints require parameters to be copied in a specific order: - - structures are copied to the stack before being loaded in a reg; - - floats loaded to an odd numbered VFP reg are first copied to the - preceding even numbered VFP reg and then moved to the next VFP reg. - - It is thus important that: - - structures assigned to core regs must be copied after parameters - assigned to the stack but before structures assigned to VFP regs - because a structure can lie partly in core registers and partly on - the stack; - - parameters assigned to the stack and all structures be copied before - parameters assigned to a core reg since copying a parameter to the - stack require using a core reg; - - parameters assigned to VFP regs be copied before structures assigned to - VFP regs as the copy might use an even numbered VFP reg that already - holds part of a structure. */ - for (i = 0; i < NB_CLASSES; i++) { - for (pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) { - vpushv(pplan->sval); - pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */ - switch (i) { - case STACK_CLASS: - case CORE_STRUCT_CLASS: - case VFP_STRUCT_CLASS: - if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) { - int padding = 0; - size = type_size(&pplan->sval->type, &align); - /* align to stack align size */ - size = (size + 3) & ~3; - if (i == STACK_CLASS && pplan->prev) - padding = pplan->start - pplan->prev->end; - size += padding; /* Add padding if any */ - /* allocate the necessary size on stack */ - gadd_sp(-size); - /* generate structure store */ - r = get_reg(RC_INT); - o(0xE28D0000 | (intr(r) << 12) | - padding); /* add r, sp, padding */ - vset(&vtop->type, r | VT_LVAL, 0); - vswap(); - vstore(); /* memcpy to current sp + potential padding */ - - /* Homogeneous float aggregate are loaded to VFP registers - immediately since there is no way of loading data in - multiple non consecutive VFP registers as what is done - for other structures (see the use of todo). */ - if (i == VFP_STRUCT_CLASS) { - int first = pplan->start, nb = pplan->end - first + 1; - /* vpop.32 {pplan->start, ..., pplan->end} */ - o(0xECBD0A00 | (first & 1) << 22 | (first >> 1) << 12 | - nb); - /* No need to write the register used to a SValue since - VFP regs cannot be used for gcall_or_jmp */ - } - } else { - if (is_float(pplan->sval->type.t)) { -#ifdef TCC_ARM_VFP - r = vfpr(gv(RC_FLOAT)) << 12; - if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) - size = 4; - else { - size = 8; - r |= 0x101; /* vpush.32 -> vpush.64 */ - } - o(0xED2D0A01 + r); /* vpush */ -#else - r = fpr(gv(RC_FLOAT)) << 12; - if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) - size = 4; - else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE) - size = 8; - else - size = LDOUBLE_SIZE; - - if (size == 12) - r |= 0x400000; - else if (size == 8) - r |= 0x8000; - - o(0xED2D0100 | r | (size >> 2)); /* some kind of vpush for FPA */ -#endif - } else { - /* simple type (currently always same size) */ - /* XXX: implicit cast ? */ - size = 4; - if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { - lexpand_nr(); - size = 8; - r = gv(RC_INT); - o(0xE52D0004 | (intr(r) << 12)); /* push r */ - vtop--; - } - r = gv(RC_INT); - o(0xE52D0004 | (intr(r) << 12)); /* push r */ - } - if (i == STACK_CLASS && pplan->prev) - gadd_sp(pplan->prev->end - - pplan->start); /* Add padding if any */ - } - break; - - case VFP_CLASS: - gv(regmask(TREG_F0 + (pplan->start >> 1))); - if (pplan->start & - 1) { /* Must be in upper part of double register */ - o(0xEEF00A40 | ((pplan->start >> 1) << 12) | - (pplan->start >> 1)); /* vmov.f32 s(n+1), sn */ - vtop->r = - VT_CONST; /* avoid being saved on stack by gv for next - float */ - } - break; - - case CORE_CLASS: - if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { - lexpand_nr(); - gv(regmask(pplan->end)); - pplan->sval->r2 = vtop->r; - vtop--; - } - gv(regmask(pplan->start)); - /* Mark register as used so that gcall_or_jmp use another one - (regs >=4 are free as never used to pass parameters) */ - pplan->sval->r = vtop->r; - break; - } - vtop--; - } - } - - /* Manually free remaining registers since next parameters are loaded - * manually, without the help of gv(int). */ - save_regs(nb_args); - - if (todo) { - o(0xE8BD0000 | todo); /* pop {todo} */ - for (pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; - pplan = pplan->prev) { - int r; - pplan->sval->r = pplan->start; - /* An SValue can only pin 2 registers at best (r and r2) but a - structure can occupy more than 2 registers. Thus, we need to - push on the value stack some fake parameter to have on SValue - for each registers used by a structure (r2 is not used). */ - for (r = pplan->start + 1; r <= pplan->end; r++) { - if (todo & (1 << r)) { - nb_extra_sval++; - vpushi(0); - vtop->r = r; - } - } - } - } - return nb_extra_sval; -} - -/* Generate function call. The function address is pushed first, then - all the parameters in call order. This functions pops all the - parameters and the function address. */ -void gfunc_call(int nb_args) -{ - int r, args_size; - int def_float_abi = float_abi; - int todo; - struct plan plan; - -#ifdef TCC_ARM_EABI - int variadic; - - if (float_abi == ARM_HARD_FLOAT) { - variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); - if (variadic || floats_in_core_regs(&vtop[-nb_args])) - float_abi = ARM_SOFTFP_FLOAT; - } -#endif - /* cannot let cpu flags if other instruction are generated. Also avoid - leaving VT_JMP anywhere except on the top of the stack because it - would complicate the code generator. */ - r = vtop->r & VT_VALMASK; - if (r == VT_CMP || (r & ~1) == VT_JMP) - gv(RC_INT); - - args_size = assign_regs(nb_args, float_abi, &plan, &todo); - -#ifdef TCC_ARM_EABI - if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */ - args_size = (args_size + 7) & ~7; - o(0xE24DD004); /* sub sp, sp, #4 */ - } -#endif - - nb_args += copy_params(nb_args, &plan, todo); - tcc_free(plan.pplans); - - /* Move fct SValue on top as required by gcall_or_jmp */ - vrotb(nb_args + 1); - gcall_or_jmp(0); - if (args_size) - gadd_sp(args_size); /* pop all parameters passed on the stack */ -#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) - if (float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) { - if ((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) { - o(0xEE000A10); /*vmov s0, r0 */ - } else { - o(0xEE000B10); /* vmov.32 d0[0], r0 */ - o(0xEE201B10); /* vmov.32 d0[1], r1 */ - } - } -#endif - vtop -= nb_args + 1; /* Pop all params and fct address from value stack */ - leaffunc = - 0; /* we are calling a function, so we aren't in a leaf function */ - float_abi = def_float_abi; -} - -/* generate function prolog of type 't' */ -void gfunc_prolog(CType* func_type) -{ - Sym* sym, *sym2; - int n, nf, size, align, rs, struct_ret = 0; - int addr, pn, sn; /* pn=core, sn=stack */ - CType ret_type; - RegArgs dummy; - -#ifdef TCC_ARM_EABI - struct avail_regs avregs = AVAIL_REGS_INITIALIZER; -#endif - - sym = func_type->ref; - func_vt = sym->type; - func_var = (func_type->ref->c == FUNC_ELLIPSIS); - - n = nf = 0; - if ((func_vt.t & VT_BTYPE) == VT_STRUCT && - !gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs, &dummy)) { - n++; - struct_ret = 1; - func_vc = 12; /* Offset from fp of the place to store the result */ - } - for (sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) { - size = type_size(&sym2->type, &align); -#ifdef TCC_ARM_EABI - if (float_abi == ARM_HARD_FLOAT && !func_var && - (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) { - int tmpnf = assign_vfpreg(&avregs, align, size); - tmpnf += (size + 3) / 4; - nf = (tmpnf > nf) ? tmpnf : nf; - } else -#endif - if (n < 4) - n += (size + 3) / 4; - } - o(0xE1A0C00D); /* mov ip,sp */ - if (func_var) - n = 4; - if (n) { - if (n > 4) - n = 4; -#ifdef TCC_ARM_EABI - n = (n + 1) & -2; -#endif - o(0xE92D0000 | ((1 << n) - 1)); /* save r0-r4 on stack if needed */ - } - if (nf) { - if (nf > 16) - nf = 16; - nf = (nf + 1) & -2; /* nf => HARDFLOAT => EABI */ - o(0xED2D0A00 | nf); /* save s0-s15 on stack if needed */ - } - o(0xE92D5800); /* save fp, ip, lr */ - o(0xE1A0B00D); /* mov fp, sp */ - func_sub_sp_offset = ind; - o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */ - -#ifdef TCC_ARM_EABI - if (float_abi == ARM_HARD_FLOAT) { - func_vc += nf * 4; - avregs = AVAIL_REGS_INITIALIZER; - } -#endif - pn = struct_ret, sn = 0; - while ((sym = sym->next)) { - CType* type; - type = &sym->type; - size = type_size(type, &align); - size = (size + 3) >> 2; - align = (align + 3) & ~3; -#ifdef TCC_ARM_EABI - if (float_abi == ARM_HARD_FLOAT && !func_var && - (is_float(sym->type.t) || is_hgen_float_aggr(&sym->type))) { - int fpn = assign_vfpreg(&avregs, align, size << 2); - if (fpn >= 0) - addr = fpn * 4; - else - goto from_stack; - } else -#endif - if (pn < 4) { -#ifdef TCC_ARM_EABI - pn = (pn + (align - 1) / 4) & -(align / 4); -#endif - addr = (nf + pn) * 4; - pn += size; - if (!sn && pn > 4) - sn = (pn - 4); - } else { -#ifdef TCC_ARM_EABI - from_stack: - sn = (sn + (align - 1) / 4) & -(align / 4); -#endif - addr = (n + nf + sn) * 4; - sn += size; - } - sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), - addr + 12); - } - last_itod_magic = 0; - leaffunc = 1; - loc = 0; -} - -/* generate function epilog */ -void gfunc_epilog(void) -{ - uint32_t x; - int diff; -/* Copy float return value to core register if base standard is used and - float computation is made with VFP */ -#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) - if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) { - if ((func_vt.t & VT_BTYPE) == VT_FLOAT) - o(0xEE100A10); /* fmrs r0, s0 */ - else { - o(0xEE100B10); /* fmrdl r0, d0 */ - o(0xEE301B10); /* fmrdh r1, d0 */ - } - } -#endif - o(0xE89BA800); /* restore fp, sp, pc */ - diff = (-loc + 3) & -4; -#ifdef TCC_ARM_EABI - if (!leaffunc) - diff = ((diff + 11) & -8) - 4; -#endif - if (diff > 0) { - x = stuff_const(0xE24BD000, diff); /* sub sp,fp,# */ - if (x) - *(uint32_t*)(cur_text_section->data + func_sub_sp_offset) = x; - else { - int addr; - addr = ind; - o(0xE59FC004); /* ldr ip,[pc+4] */ - o(0xE04BD00C); /* sub sp,fp,ip */ - o(0xE1A0F00E); /* mov pc,lr */ - o(diff); - *(uint32_t*)(cur_text_section->data + func_sub_sp_offset) = - 0xE1000000 | encbranch(func_sub_sp_offset, addr, 1); - } - } -} - -/* generate a jump to a label */ -int gjmp(int t) -{ - int r; - r = ind; - o(0xE0000000 | encbranch(r, t, 1)); - return r; -} - -/* generate a jump to a fixed address */ -void gjmp_addr(int a) -{ - gjmp(a); -} - -/* generate a test. set 'inv' to invert test. Stack entry is popped */ -int gtst(int inv, int t) -{ - int v, r; - uint32_t op; - v = vtop->r & VT_VALMASK; - r = ind; - if (v == VT_CMP) { - op = mapcc(inv ? negcc(vtop->c.i) : vtop->c.i); - op |= encbranch(r, t, 1); - o(op); - t = r; - } else if (v == VT_JMP || v == VT_JMPI) { - if ((v & 1) == inv) { - if (!vtop->c.i) - vtop->c.i = t; - else { - uint32_t* x; - int p, lp; - if (t) { - p = vtop->c.i; - do { - p = decbranch(lp = p); - } while (p); - x = (uint32_t*)(cur_text_section->data + lp); - *x &= 0xff000000; - *x |= encbranch(lp, t, 1); - } - t = vtop->c.i; - } - } else { - t = gjmp(t); - gsym(vtop->c.i); - } - } - vtop--; - return t; -} - -/* generate an integer binary operation */ -void gen_opi(int op) -{ - int c, func = 0; - uint32_t opc = 0, r, fr; - unsigned short retreg = REG_IRET; - - c = 0; - switch (op) { - case '+': - opc = 0x8; - c = 1; - break; - case TOK_ADDC1: /* add with carry generation */ - opc = 0x9; - c = 1; - break; - case '-': - opc = 0x4; - c = 1; - break; - case TOK_SUBC1: /* sub with carry generation */ - opc = 0x5; - c = 1; - break; - case TOK_ADDC2: /* add with carry use */ - opc = 0xA; - c = 1; - break; - case TOK_SUBC2: /* sub with carry use */ - opc = 0xC; - c = 1; - break; - case '&': - opc = 0x0; - c = 1; - break; - case '^': - opc = 0x2; - c = 1; - break; - case '|': - opc = 0x18; - c = 1; - break; - case '*': - gv2(RC_INT, RC_INT); - r = vtop[-1].r; - fr = vtop[0].r; - vtop--; - o(0xE0000090 | (intr(r) << 16) | (intr(r) << 8) | intr(fr)); - return; - case TOK_SHL: - opc = 0; - c = 2; - break; - case TOK_SHR: - opc = 1; - c = 2; - break; - case TOK_SAR: - opc = 2; - c = 2; - break; - case '/': - case TOK_PDIV: - func = TOK___divsi3; - c = 3; - break; - case TOK_UDIV: - func = TOK___udivsi3; - c = 3; - break; - case '%': -#ifdef TCC_ARM_EABI - func = TOK___aeabi_idivmod; - retreg = REG_LRET; -#else - func = TOK___modsi3; -#endif - c = 3; - break; - case TOK_UMOD: -#ifdef TCC_ARM_EABI - func = TOK___aeabi_uidivmod; - retreg = REG_LRET; -#else - func = TOK___umodsi3; -#endif - c = 3; - break; - case TOK_UMULL: - gv2(RC_INT, RC_INT); - r = intr(vtop[-1].r2 = get_reg(RC_INT)); - c = vtop[-1].r; - vtop[-1].r = get_reg_ex(RC_INT, regmask(c)); - vtop--; - o(0xE0800090 | (r << 16) | (intr(vtop->r) << 12) | (intr(c) << 8) | - intr(vtop[1].r)); - return; - default: - opc = 0x15; - c = 1; - break; - } - switch (c) { - case 1: - if ((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - if (opc == 4 || opc == 5 || opc == 0xc) { - vswap(); - opc |= 2; // sub -> rsb - } - } - if ((vtop->r & VT_VALMASK) == VT_CMP || - (vtop->r & (VT_VALMASK & ~1)) == VT_JMP) - gv(RC_INT); - vswap(); - c = intr(gv(RC_INT)); - vswap(); - opc = 0xE0000000 | (opc << 20) | (c << 16); - if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - uint32_t x; - x = stuff_const(opc | 0x2000000, vtop->c.i); - if (x) { - r = intr(vtop[-1].r = get_reg_ex(RC_INT, regmask(vtop[-1].r))); - o(x | (r << 12)); - goto done; - } - } - fr = intr(gv(RC_INT)); - r = intr(vtop[-1].r = - get_reg_ex(RC_INT, two2mask(vtop->r, vtop[-1].r))); - o(opc | (r << 12) | fr); - done: - vtop--; - if (op >= TOK_ULT && op <= TOK_GT) { - vtop->r = VT_CMP; - vtop->c.i = op; - } - break; - case 2: - opc = 0xE1A00000 | (opc << 5); - if ((vtop->r & VT_VALMASK) == VT_CMP || - (vtop->r & (VT_VALMASK & ~1)) == VT_JMP) - gv(RC_INT); - vswap(); - r = intr(gv(RC_INT)); - vswap(); - opc |= r; - if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - fr = intr(vtop[-1].r = get_reg_ex(RC_INT, regmask(vtop[-1].r))); - c = vtop->c.i & 0x1f; - o(opc | (c << 7) | (fr << 12)); - } else { - fr = intr(gv(RC_INT)); - c = intr(vtop[-1].r = - get_reg_ex(RC_INT, two2mask(vtop->r, vtop[-1].r))); - o(opc | (c << 12) | (fr << 8) | 0x10); - } - vtop--; - break; - case 3: - vpush_global_sym(&func_old_type, func); - vrott(3); - gfunc_call(2); - vpushi(0); - vtop->r = retreg; - break; - default: - tcc_error("gen_opi %i unimplemented!", op); - } -} - -#ifdef TCC_ARM_VFP -static int is_zero(int i) -{ - if ((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) - return 0; - if (vtop[i].type.t == VT_FLOAT) - return (vtop[i].c.f == 0.f); - else if (vtop[i].type.t == VT_DOUBLE) - return (vtop[i].c.d == 0.0); - return (vtop[i].c.ld == 0.l); -} - -/* generate a floating point operation 'v = t1 op t2' instruction. The - * two operands are guaranted to have the same floating point type */ -void gen_opf(int op) -{ - uint32_t x; - int fneg = 0, r; - x = 0xEE000A00 | T2CPR(vtop->type.t); - switch (op) { - case '+': - if (is_zero(-1)) - vswap(); - if (is_zero(0)) { - vtop--; - return; - } - x |= 0x300000; - break; - case '-': - x |= 0x300040; - if (is_zero(0)) { - vtop--; - return; - } - if (is_zero(-1)) { - x |= 0x810000; /* fsubX -> fnegX */ - vswap(); - vtop--; - fneg = 1; - } - break; - case '*': - x |= 0x200000; - break; - case '/': - x |= 0x800000; - break; - default: - if (op < TOK_ULT || op > TOK_GT) { - tcc_error("unknown fp op %x!", op); - return; - } - if (is_zero(-1)) { - vswap(); - switch(op) { - case TOK_LT: op = TOK_GT; break; - case TOK_GE: op = TOK_ULE; break; - case TOK_LE: op = TOK_GE; break; - case TOK_GT: op = TOK_ULT; break; - } - } - x |= 0xB40040; /* fcmpX */ - if (op != TOK_EQ && op != TOK_NE) - x |= 0x80; /* fcmpX -> fcmpeX */ - if (is_zero(0)) { - vtop--; - o(x | 0x10000 | - (vfpr(gv(RC_FLOAT)) << 12)); /* fcmp(e)X -> fcmp(e)zX */ - } else { - x |= vfpr(gv(RC_FLOAT)); - vswap(); - o(x | (vfpr(gv(RC_FLOAT)) << 12)); - vtop--; - } - o(0xEEF1FA10); /* fmstat */ - - switch(op) { - case TOK_LE: op = TOK_ULE; break; - case TOK_LT: op = TOK_ULT; break; - case TOK_UGE: op = TOK_GE; break; - case TOK_UGT: op = TOK_GT; break; - } - - vtop->r = VT_CMP; - vtop->c.i = op; - return; - } - r = gv(RC_FLOAT); - x |= vfpr(r); - r = regmask(r); - if (!fneg) { - int r2; - vswap(); - r2 = gv(RC_FLOAT); - x |= vfpr(r2) << 16; - r |= regmask(r2); - } - vtop->r = get_reg_ex(RC_FLOAT, r); - if (!fneg) - vtop--; - o(x | (vfpr(vtop->r) << 12)); -} - -#else -static uint32_t is_fconst() -{ - long double f; - uint32_t r; - if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) - return 0; - if (vtop->type.t == VT_FLOAT) - f = vtop->c.f; - else if (vtop->type.t == VT_DOUBLE) - f = vtop->c.d; - else - f = vtop->c.ld; - if (!ieee_finite(f)) - return 0; - r = 0x8; - if (f < 0.0) { - r = 0x18; - f = -f; - } - if (f == 0.0) - return r; - if (f == 1.0) - return r | 1; - if (f == 2.0) - return r | 2; - if (f == 3.0) - return r | 3; - if (f == 4.0) - return r | 4; - if (f == 5.0) - return r | 5; - if (f == 0.5) - return r | 6; - if (f == 10.0) - return r | 7; - return 0; -} - -/* generate a floating point operation 'v = t1 op t2' instruction. The - two operands are guaranted to have the same floating point type */ -void gen_opf(int op) -{ - uint32_t x, r, r2, c1, c2; - // fputs("gen_opf\n",stderr); - vswap(); - c1 = is_fconst(); - vswap(); - c2 = is_fconst(); - x = 0xEE000100; -#if LDOUBLE_SIZE == 8 - if ((vtop->type.t & VT_BTYPE) != VT_FLOAT) - x |= 0x80; -#else - if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) - x |= 0x80; - else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) - x |= 0x80000; -#endif - switch (op) { - case '+': - if (!c2) { - vswap(); - c2 = c1; - } - vswap(); - r = fpr(gv(RC_FLOAT)); - vswap(); - if (c2) { - if (c2 > 0xf) - x |= 0x200000; // suf - r2 = c2 & 0xf; - } else { - r2 = fpr(gv(RC_FLOAT)); - } - break; - case '-': - if (c2) { - if (c2 <= 0xf) - x |= 0x200000; // suf - r2 = c2 & 0xf; - vswap(); - r = fpr(gv(RC_FLOAT)); - vswap(); - } else if (c1 && c1 <= 0xf) { - x |= 0x300000; // rsf - r2 = c1; - r = fpr(gv(RC_FLOAT)); - vswap(); - } else { - x |= 0x200000; // suf - vswap(); - r = fpr(gv(RC_FLOAT)); - vswap(); - r2 = fpr(gv(RC_FLOAT)); - } - break; - case '*': - if (!c2 || c2 > 0xf) { - vswap(); - c2 = c1; - } - vswap(); - r = fpr(gv(RC_FLOAT)); - vswap(); - if (c2 && c2 <= 0xf) - r2 = c2; - else - r2 = fpr(gv(RC_FLOAT)); - x |= 0x100000; // muf - break; - case '/': - if (c2 && c2 <= 0xf) { - x |= 0x400000; // dvf - r2 = c2; - vswap(); - r = fpr(gv(RC_FLOAT)); - vswap(); - } else if (c1 && c1 <= 0xf) { - x |= 0x500000; // rdf - r2 = c1; - r = fpr(gv(RC_FLOAT)); - vswap(); - } else { - x |= 0x400000; // dvf - vswap(); - r = fpr(gv(RC_FLOAT)); - vswap(); - r2 = fpr(gv(RC_FLOAT)); - } - break; - default: - if (op >= TOK_ULT && op <= TOK_GT) { - x |= 0xd0f110; // cmfe - /* bug (intention?) in Linux FPU emulator - doesn't set carry if equal */ - switch (op) { - case TOK_ULT: - case TOK_UGE: - case TOK_ULE: - case TOK_UGT: - tcc_error("unsigned comparison on floats?"); - break; - case TOK_LT: - op = TOK_Nset; - break; - case TOK_LE: - op = TOK_ULE; /* correct in unordered case only if AC bit in - FPSR set */ - break; - case TOK_EQ: - case TOK_NE: - x &= ~0x400000; // cmfe -> cmf - break; - } - if (c1 && !c2) { - c2 = c1; - vswap(); - switch (op) { - case TOK_Nset: - op = TOK_GT; - break; - case TOK_GE: - op = TOK_ULE; - break; - case TOK_ULE: - op = TOK_GE; - break; - case TOK_GT: - op = TOK_Nset; - break; - } - } - vswap(); - r = fpr(gv(RC_FLOAT)); - vswap(); - if (c2) { - if (c2 > 0xf) - x |= 0x200000; - r2 = c2 & 0xf; - } else { - r2 = fpr(gv(RC_FLOAT)); - } - vtop[-1].r = VT_CMP; - vtop[-1].c.i = op; - } else { - tcc_error("unknown fp op %x!", op); - return; - } - } - if (vtop[-1].r == VT_CMP) - c1 = 15; - else { - c1 = vtop->r; - if (r2 & 0x8) - c1 = vtop[-1].r; - vtop[-1].r = get_reg_ex(RC_FLOAT, two2mask(vtop[-1].r, c1)); - c1 = fpr(vtop[-1].r); - } - vtop--; - o(x | (r << 16) | (c1 << 12) | r2); -} -#endif - -/* convert integers to fp 't' type. Must handle 'int', 'unsigned int' - and 'long long' cases. */ -ST_FUNC void gen_cvt_itof1(int t) -{ - uint32_t r, r2; - int bt; - bt = vtop->type.t & VT_BTYPE; - if (bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) { -#ifndef TCC_ARM_VFP - uint32_t dsize = 0; -#endif - r = intr(gv(RC_INT)); -#ifdef TCC_ARM_VFP - r2 = vfpr(vtop->r = get_reg(RC_FLOAT)); - o(0xEE000A10 | (r << 12) | (r2 << 16)); /* fmsr */ - r2 |= r2 << 12; - if (!(vtop->type.t & VT_UNSIGNED)) - r2 |= 0x80; /* fuitoX -> fsituX */ - o(0xEEB80A40 | r2 | T2CPR(t)); /* fYitoX*/ -#else - r2 = fpr(vtop->r = get_reg(RC_FLOAT)); - if ((t & VT_BTYPE) != VT_FLOAT) - dsize = 0x80; /* flts -> fltd */ - o(0xEE000110 | dsize | (r2 << 16) | (r << 12)); /* flts */ - if ((vtop->type.t & (VT_UNSIGNED | VT_BTYPE)) == - (VT_UNSIGNED | VT_INT)) { - uint32_t off = 0; - o(0xE3500000 | (r << 12)); /* cmp */ - r = fpr(get_reg(RC_FLOAT)); - if (last_itod_magic) { - off = ind + 8 - last_itod_magic; - off /= 4; - if (off > 255) - off = 0; - } - o(0xBD1F0100 | (r << 12) | off); /* ldflts */ - if (!off) { - o(0xEA000000); /* b */ - last_itod_magic = ind; - o(0x4F800000); /* 4294967296.0f */ - } - o(0xBE000100 | dsize | (r2 << 16) | (r2 << 12) | r); /* adflt */ - } -#endif - return; - } else if (bt == VT_LLONG) { - int func; - CType* func_type = 0; - if ((t & VT_BTYPE) == VT_FLOAT) { - func_type = &func_float_type; - if (vtop->type.t & VT_UNSIGNED) - func = TOK___floatundisf; - else - func = TOK___floatdisf; -#if LDOUBLE_SIZE != 8 - } else if ((t & VT_BTYPE) == VT_LDOUBLE) { - func_type = &func_ldouble_type; - if (vtop->type.t & VT_UNSIGNED) - func = TOK___floatundixf; - else - func = TOK___floatdixf; - } else if ((t & VT_BTYPE) == VT_DOUBLE) { -#else - } else if ((t & VT_BTYPE) == VT_DOUBLE || - (t & VT_BTYPE) == VT_LDOUBLE) { -#endif - func_type = &func_double_type; - if (vtop->type.t & VT_UNSIGNED) - func = TOK___floatundidf; - else - func = TOK___floatdidf; - } - if (func_type) { - vpush_global_sym(func_type, func); - vswap(); - gfunc_call(1); - vpushi(0); - vtop->r = TREG_F0; - return; - } - } - tcc_error("unimplemented gen_cvt_itof %x!", vtop->type.t); -} - -/* convert fp to int 't' type */ -void gen_cvt_ftoi(int t) -{ - uint32_t r, r2; - int u, func = 0; - u = t & VT_UNSIGNED; - t &= VT_BTYPE; - r2 = vtop->type.t & VT_BTYPE; - if (t == VT_INT) { -#ifdef TCC_ARM_VFP - r = vfpr(gv(RC_FLOAT)); - u = u ? 0 : 0x10000; - o(0xEEBC0AC0 | (r << 12) | r | T2CPR(r2) | u); /* ftoXizY */ - r2 = intr(vtop->r = get_reg(RC_INT)); - o(0xEE100A10 | (r << 16) | (r2 << 12)); - return; -#else - if (u) { - if (r2 == VT_FLOAT) - func = TOK___fixunssfsi; -#if LDOUBLE_SIZE != 8 - else if (r2 == VT_LDOUBLE) - func = TOK___fixunsxfsi; - else if (r2 == VT_DOUBLE) -#else - else if (r2 == VT_LDOUBLE || r2 == VT_DOUBLE) -#endif - func = TOK___fixunsdfsi; - } else { - r = fpr(gv(RC_FLOAT)); - r2 = intr(vtop->r = get_reg(RC_INT)); - o(0xEE100170 | (r2 << 12) | r); - return; - } -#endif - } else if (t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1 - if (r2 == VT_FLOAT) - func = TOK___fixsfdi; -#if LDOUBLE_SIZE != 8 - else if (r2 == VT_LDOUBLE) - func = TOK___fixxfdi; - else if (r2 == VT_DOUBLE) -#else - else if (r2 == VT_LDOUBLE || r2 == VT_DOUBLE) -#endif - func = TOK___fixdfdi; - } - if (func) { - vpush_global_sym(&func_old_type, func); - vswap(); - gfunc_call(1); - vpushi(0); - if (t == VT_LLONG) - vtop->r2 = REG_LRET; - vtop->r = REG_IRET; - return; - } - tcc_error("unimplemented gen_cvt_ftoi!"); -} - -/* convert from one floating point type to another */ -void gen_cvt_ftof(int t) -{ -#ifdef TCC_ARM_VFP - if (((vtop->type.t & VT_BTYPE) == VT_FLOAT) != - ((t & VT_BTYPE) == VT_FLOAT)) { - uint32_t r = vfpr(gv(RC_FLOAT)); - o(0xEEB70AC0 | (r << 12) | r | T2CPR(vtop->type.t)); - } -#else - /* all we have to do on i386 and FPA ARM is to put the float in a register - */ - gv(RC_FLOAT); -#endif -} - -/* computed goto support */ -void ggoto(void) -{ - gcall_or_jmp(1); - vtop--; -} - -/* Save the stack pointer onto the stack and return the location of its address - */ -ST_FUNC void gen_vla_sp_save(int addr) -{ - tcc_error("variable length arrays unsupported for this target"); -} - -/* Restore the SP from a location on the stack */ -ST_FUNC void gen_vla_sp_restore(int addr) -{ - tcc_error("variable length arrays unsupported for this target"); -} - -/* Subtract from the stack pointer, and push the resulting value onto the stack - */ -ST_FUNC void gen_vla_alloc(CType* type, int align) -{ - tcc_error("variable length arrays unsupported for this target"); -} - -/* end of ARM code generator */ -/*************************************************************/ -#endif -/*************************************************************/ diff --git a/src/tcccoff.c b/src/tcccoff.c deleted file mode 100644 index 1964bed..0000000 --- a/src/tcccoff.c +++ /dev/null @@ -1,924 +0,0 @@ -/* - * COFF file handling for TCC - * - * Copyright (c) 2003, 2004 TK - * Copyright (c) 2004 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "tcc.h" - -#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */ -#define MAX_STR_TABLE 1000000 -AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */ - -SCNHDR section_header[MAXNSCNS]; - -#define MAX_FUNCS 1000 -#define MAX_FUNC_NAME_LENGTH 128 - -int nFuncs; -char Func[MAX_FUNCS][MAX_FUNC_NAME_LENGTH]; -char AssociatedFile[MAX_FUNCS][MAX_FUNC_NAME_LENGTH]; -int LineNoFilePtr[MAX_FUNCS]; -int EndAddress[MAX_FUNCS]; -int LastLineNo[MAX_FUNCS]; -int FuncEntries[MAX_FUNCS]; - -int OutputTheSection(Section* sect); -short int GetCoffFlags(const char* s); -void SortSymbolTable(void); -Section* FindSection(TCCState* s1, const char* sname); - -int C67_main_entry_point; - -int FindCoffSymbolIndex(const char* func_name); -int nb_syms; - -typedef struct { - long tag; - long size; - long fileptr; - long nextsym; - short int dummy; -} AUXFUNC; - -typedef struct { - long regmask; - unsigned short lineno; - unsigned short nentries; - int localframe; - int nextentry; - short int dummy; -} AUXBF; - -typedef struct { - long dummy; - unsigned short lineno; - unsigned short dummy1; - int dummy2; - int dummy3; - unsigned short dummy4; -} AUXEF; - -ST_FUNC int tcc_output_coff(TCCState* s1, FILE* f) -{ - Section* tcc_sect; - SCNHDR* coff_sec; - int file_pointer; - char* Coff_str_table, *pCoff_str_table; - int CoffTextSectionNo, coff_nb_syms; - FILHDR file_hdr; /* FILE HEADER STRUCTURE */ - Section* stext, *sdata, *sbss; - int i, NSectionsToOutput = 0; - - Coff_str_table = pCoff_str_table = NULL; - - stext = FindSection(s1, ".text"); - sdata = FindSection(s1, ".data"); - sbss = FindSection(s1, ".bss"); - - nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym); - coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1"); - - file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */ - file_hdr.f_timdat = 0; /* time & date stamp */ - file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */ - file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */ - file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */ - - o_filehdr.magic = 0x0108; /* see magic.h */ - o_filehdr.vstamp = 0x0190; /* version stamp */ - o_filehdr.tsize = - stext->data_offset; /* text size in bytes, padded to FW bdry */ - o_filehdr.dsize = sdata->data_offset; /* initialized data " " */ - o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */ - o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */ - o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */ - o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */ - - // create all the section headers - - file_pointer = FILHSZ + sizeof(AOUTHDR); - - CoffTextSectionNo = -1; - - for (i = 1; i < s1->nb_sections; i++) { - coff_sec = §ion_header[i]; - tcc_sect = s1->sections[i]; - - if (OutputTheSection(tcc_sect)) { - NSectionsToOutput++; - - if (CoffTextSectionNo == -1 && tcc_sect == stext) - CoffTextSectionNo = NSectionsToOutput; // rem which coff sect - // number the .text sect - // is - - strcpy(coff_sec->s_name, tcc_sect->name); /* section name */ - - coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */ - coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */ - coff_sec->s_size = tcc_sect->data_offset; /* section size */ - coff_sec->s_scnptr = 0; /* file ptr to raw data for section */ - coff_sec->s_relptr = 0; /* file ptr to relocation */ - coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */ - coff_sec->s_nreloc = 0; /* number of relocation entries */ - coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */ - coff_sec->s_reserved = 0; /* reserved byte */ - coff_sec->s_page = 0; /* memory page id */ - - file_pointer += sizeof(SCNHDR); - } - } - - file_hdr.f_nscns = NSectionsToOutput; /* number of sections */ - - // now loop through and determine file pointer locations - // for the raw data - - for (i = 1; i < s1->nb_sections; i++) { - coff_sec = §ion_header[i]; - tcc_sect = s1->sections[i]; - - if (OutputTheSection(tcc_sect)) { - // put raw data - coff_sec->s_scnptr = - file_pointer; /* file ptr to raw data for section */ - file_pointer += coff_sec->s_size; - } - } - - // now loop through and determine file pointer locations - // for the relocation data - - for (i = 1; i < s1->nb_sections; i++) { - coff_sec = §ion_header[i]; - tcc_sect = s1->sections[i]; - - if (OutputTheSection(tcc_sect)) { - // put relocations data - if (coff_sec->s_nreloc > 0) { - coff_sec->s_relptr = file_pointer; /* file ptr to relocation */ - file_pointer += coff_sec->s_nreloc * sizeof(struct reloc); - } - } - } - - // now loop through and determine file pointer locations - // for the line number data - - for (i = 1; i < s1->nb_sections; i++) { - coff_sec = §ion_header[i]; - tcc_sect = s1->sections[i]; - - coff_sec->s_nlnno = 0; - coff_sec->s_lnnoptr = 0; - - if (s1->do_debug && tcc_sect == stext) { - // count how many line nos data - - // also find association between source file name and function - // so we can sort the symbol table - - Stab_Sym* sym, *sym_end; - char func_name[MAX_FUNC_NAME_LENGTH], - last_func_name[MAX_FUNC_NAME_LENGTH]; - unsigned long func_addr, last_pc, pc; - const char* incl_files[INCLUDE_STACK_SIZE]; - int incl_index, len, last_line_num; - const char* str, *p; - - coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */ - - func_name[0] = '\0'; - func_addr = 0; - incl_index = 0; - last_func_name[0] = '\0'; - last_pc = 0xffffffff; - last_line_num = 1; - sym = (Stab_Sym*)stab_section->data + 1; - sym_end = - (Stab_Sym*)(stab_section->data + stab_section->data_offset); - - nFuncs = 0; - while (sym < sym_end) { - switch (sym->n_type) { - /* function start or end */ - case N_FUN: - if (sym->n_strx == 0) { - // end of function - - coff_sec->s_nlnno++; - file_pointer += LINESZ; - - pc = sym->n_value + func_addr; - func_name[0] = '\0'; - func_addr = 0; - EndAddress[nFuncs] = pc; - FuncEntries[nFuncs] = - (file_pointer - LineNoFilePtr[nFuncs]) / LINESZ - 1; - LastLineNo[nFuncs++] = last_line_num + 1; - } else { - // beginning of function - - LineNoFilePtr[nFuncs] = file_pointer; - coff_sec->s_nlnno++; - file_pointer += LINESZ; - - str = (const char*)stabstr_section->data + sym->n_strx; - - p = strchr(str, ':'); - if (!p) { - pstrcpy(func_name, sizeof(func_name), str); - pstrcpy(Func[nFuncs], sizeof(func_name), str); - } else { - len = p - str; - if (len > sizeof(func_name) - 1) - len = sizeof(func_name) - 1; - memcpy(func_name, str, len); - memcpy(Func[nFuncs], str, len); - func_name[len] = '\0'; - } - - // save the file that it came in so we can sort later - pstrcpy(AssociatedFile[nFuncs], sizeof(func_name), - incl_files[incl_index - 1]); - - func_addr = sym->n_value; - } - break; - - /* line number info */ - case N_SLINE: - pc = sym->n_value + func_addr; - - last_pc = pc; - last_line_num = sym->n_desc; - - /* XXX: slow! */ - strcpy(last_func_name, func_name); - - coff_sec->s_nlnno++; - file_pointer += LINESZ; - break; - /* include files */ - case N_BINCL: - str = (const char*)stabstr_section->data + sym->n_strx; - add_incl: - if (incl_index < INCLUDE_STACK_SIZE) { - incl_files[incl_index++] = str; - } - break; - case N_EINCL: - if (incl_index > 1) - incl_index--; - break; - case N_SO: - if (sym->n_strx == 0) { - incl_index = 0; /* end of translation unit */ - } else { - str = (const char*)stabstr_section->data + sym->n_strx; - /* do not add path */ - len = strlen(str); - if (len > 0 && str[len - 1] != '/') - goto add_incl; - } - break; - } - sym++; - } - } - } - - file_hdr.f_symptr = file_pointer; /* file pointer to symtab */ - - if (s1->do_debug) - file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */ - else - file_hdr.f_nsyms = 0; - - file_pointer += file_hdr.f_nsyms * SYMNMLEN; - - // OK now we are all set to write the file - - fwrite(&file_hdr, FILHSZ, 1, f); - fwrite(&o_filehdr, sizeof(o_filehdr), 1, f); - - // write section headers - for (i = 1; i < s1->nb_sections; i++) { - coff_sec = §ion_header[i]; - tcc_sect = s1->sections[i]; - - if (OutputTheSection(tcc_sect)) { - fwrite(coff_sec, sizeof(SCNHDR), 1, f); - } - } - - // write raw data - for (i = 1; i < s1->nb_sections; i++) { - coff_sec = §ion_header[i]; - tcc_sect = s1->sections[i]; - - if (OutputTheSection(tcc_sect)) { - fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f); - } - } - - // write relocation data - for (i = 1; i < s1->nb_sections; i++) { - coff_sec = §ion_header[i]; - tcc_sect = s1->sections[i]; - - if (OutputTheSection(tcc_sect)) { - // put relocations data - if (coff_sec->s_nreloc > 0) { - fwrite(tcc_sect->reloc, - coff_sec->s_nreloc * sizeof(struct reloc), 1, f); - } - } - } - - // group the symbols in order of filename, func1, func2, etc - // finally global symbols - - if (s1->do_debug) - SortSymbolTable(); - - // write line no data - - for (i = 1; i < s1->nb_sections; i++) { - coff_sec = §ion_header[i]; - tcc_sect = s1->sections[i]; - - if (s1->do_debug && tcc_sect == stext) { - // count how many line nos data - - Stab_Sym* sym, *sym_end; - char func_name[128], last_func_name[128]; - unsigned long func_addr, last_pc, pc; - const char* incl_files[INCLUDE_STACK_SIZE]; - int incl_index, len, last_line_num; - const char* str, *p; - - LINENO CoffLineNo; - - func_name[0] = '\0'; - func_addr = 0; - incl_index = 0; - last_func_name[0] = '\0'; - last_pc = 0; - last_line_num = 1; - sym = (Stab_Sym*)stab_section->data + 1; - sym_end = - (Stab_Sym*)(stab_section->data + stab_section->data_offset); - - while (sym < sym_end) { - switch (sym->n_type) { - /* function start or end */ - case N_FUN: - if (sym->n_strx == 0) { - // end of function - - CoffLineNo.l_addr.l_paddr = last_pc; - CoffLineNo.l_lnno = last_line_num + 1; - fwrite(&CoffLineNo, 6, 1, f); - - pc = sym->n_value + func_addr; - func_name[0] = '\0'; - func_addr = 0; - } else { - // beginning of function - - str = (const char*)stabstr_section->data + sym->n_strx; - - p = strchr(str, ':'); - if (!p) { - pstrcpy(func_name, sizeof(func_name), str); - } else { - len = p - str; - if (len > sizeof(func_name) - 1) - len = sizeof(func_name) - 1; - memcpy(func_name, str, len); - func_name[len] = '\0'; - } - func_addr = sym->n_value; - last_pc = func_addr; - last_line_num = -1; - - // output a function begin - - CoffLineNo.l_addr.l_symndx = - FindCoffSymbolIndex(func_name); - CoffLineNo.l_lnno = 0; - - fwrite(&CoffLineNo, 6, 1, f); - } - break; - - /* line number info */ - case N_SLINE: - pc = sym->n_value + func_addr; - - /* XXX: slow! */ - strcpy(last_func_name, func_name); - - // output a line reference - - CoffLineNo.l_addr.l_paddr = last_pc; - - if (last_line_num == -1) { - CoffLineNo.l_lnno = sym->n_desc; - } else { - CoffLineNo.l_lnno = last_line_num + 1; - } - - fwrite(&CoffLineNo, 6, 1, f); - - last_pc = pc; - last_line_num = sym->n_desc; - - break; - - /* include files */ - case N_BINCL: - str = (const char*)stabstr_section->data + sym->n_strx; - add_incl2: - if (incl_index < INCLUDE_STACK_SIZE) { - incl_files[incl_index++] = str; - } - break; - case N_EINCL: - if (incl_index > 1) - incl_index--; - break; - case N_SO: - if (sym->n_strx == 0) { - incl_index = 0; /* end of translation unit */ - } else { - str = (const char*)stabstr_section->data + sym->n_strx; - /* do not add path */ - len = strlen(str); - if (len > 0 && str[len - 1] != '/') - goto add_incl2; - } - break; - } - sym++; - } - } - } - - // write symbol table - if (s1->do_debug) { - int k; - struct syment csym; - AUXFUNC auxfunc; - AUXBF auxbf; - AUXEF auxef; - int i; - Elf32_Sym* p; - const char* name; - int nstr; - int n = 0; - - Coff_str_table = (char*)tcc_malloc(MAX_STR_TABLE); - pCoff_str_table = Coff_str_table; - nstr = 0; - - p = (Elf32_Sym*)symtab_section->data; - - for (i = 0; i < nb_syms; i++) { - - name = symtab_section->link->data + p->st_name; - - for (k = 0; k < 8; k++) - csym._n._n_name[k] = 0; - - if (strlen(name) <= 8) { - strcpy(csym._n._n_name, name); - } else { - if (pCoff_str_table - Coff_str_table + strlen(name) > - MAX_STR_TABLE - 1) - tcc_error("String table too large"); - - csym._n._n_n._n_zeroes = 0; - csym._n._n_n._n_offset = pCoff_str_table - Coff_str_table + 4; - - strcpy(pCoff_str_table, name); - pCoff_str_table += strlen(name) + 1; // skip over null - nstr++; - } - - if (p->st_info == 4) { - // put a filename symbol - csym.n_value = 33; // ????? - csym.n_scnum = N_DEBUG; - csym.n_type = 0; - csym.n_sclass = C_FILE; - csym.n_numaux = 0; - fwrite(&csym, 18, 1, f); - n++; - - } else if (p->st_info == 0x12) { - // find the function data - - for (k = 0; k < nFuncs; k++) { - if (strcmp(name, Func[k]) == 0) - break; - } - - if (k >= nFuncs) { - tcc_error("debug info can't find function: %s", name); - } - // put a Function Name - - csym.n_value = p->st_value; // physical address - csym.n_scnum = CoffTextSectionNo; - csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0); - csym.n_sclass = C_EXT; - csym.n_numaux = 1; - fwrite(&csym, 18, 1, f); - - // now put aux info - - auxfunc.tag = 0; - auxfunc.size = EndAddress[k] - p->st_value; - auxfunc.fileptr = LineNoFilePtr[k]; - auxfunc.nextsym = n + 6; // tktk - auxfunc.dummy = 0; - fwrite(&auxfunc, 18, 1, f); - - // put a .bf - - strcpy(csym._n._n_name, ".bf"); - csym.n_value = p->st_value; // physical address - csym.n_scnum = CoffTextSectionNo; - csym.n_type = 0; - csym.n_sclass = C_FCN; - csym.n_numaux = 1; - fwrite(&csym, 18, 1, f); - - // now put aux info - - auxbf.regmask = 0; - auxbf.lineno = 0; - auxbf.nentries = FuncEntries[k]; - auxbf.localframe = 0; - auxbf.nextentry = n + 6; - auxbf.dummy = 0; - fwrite(&auxbf, 18, 1, f); - - // put a .ef - - strcpy(csym._n._n_name, ".ef"); - csym.n_value = EndAddress[k]; // physical address - csym.n_scnum = CoffTextSectionNo; - csym.n_type = 0; - csym.n_sclass = C_FCN; - csym.n_numaux = 1; - fwrite(&csym, 18, 1, f); - - // now put aux info - - auxef.dummy = 0; - auxef.lineno = LastLineNo[k]; - auxef.dummy1 = 0; - auxef.dummy2 = 0; - auxef.dummy3 = 0; - auxef.dummy4 = 0; - fwrite(&auxef, 18, 1, f); - - n += 6; - - } else { - // try an put some type info - - if ((p->st_other & VT_BTYPE) == VT_DOUBLE) { - csym.n_type = T_DOUBLE; // int - csym.n_sclass = C_EXT; - } else if ((p->st_other & VT_BTYPE) == VT_FLOAT) { - csym.n_type = T_FLOAT; - csym.n_sclass = C_EXT; - } else if ((p->st_other & VT_BTYPE) == VT_INT) { - csym.n_type = T_INT; // int - csym.n_sclass = C_EXT; - } else if ((p->st_other & VT_BTYPE) == VT_SHORT) { - csym.n_type = T_SHORT; - csym.n_sclass = C_EXT; - } else if ((p->st_other & VT_BTYPE) == VT_BYTE) { - csym.n_type = T_CHAR; - csym.n_sclass = C_EXT; - } else { - csym.n_type = T_INT; // just mark as a label - csym.n_sclass = C_LABEL; - } - - csym.n_value = p->st_value; - csym.n_scnum = 2; - csym.n_numaux = 1; - fwrite(&csym, 18, 1, f); - - auxfunc.tag = 0; - auxfunc.size = 0x20; - auxfunc.fileptr = 0; - auxfunc.nextsym = 0; - auxfunc.dummy = 0; - fwrite(&auxfunc, 18, 1, f); - n++; - n++; - } - - p++; - } - } - - if (s1->do_debug) { - // write string table - - // first write the size - i = pCoff_str_table - Coff_str_table; - fwrite(&i, 4, 1, f); - - // then write the strings - fwrite(Coff_str_table, i, 1, f); - - tcc_free(Coff_str_table); - } - - return 0; -} - -// group the symbols in order of filename, func1, func2, etc -// finally global symbols - -void SortSymbolTable(void) -{ - int i, j, k, n = 0; - Elf32_Sym* p, *p2, *NewTable; - char* name, *name2; - - NewTable = (Elf32_Sym*)tcc_malloc(nb_syms * sizeof(Elf32_Sym)); - - p = (Elf32_Sym*)symtab_section->data; - - // find a file symbol, copy it over - // then scan the whole symbol list and copy any function - // symbols that match the file association - - for (i = 0; i < nb_syms; i++) { - if (p->st_info == 4) { - name = (char*)symtab_section->link->data + p->st_name; - - // this is a file symbol, copy it over - - NewTable[n++] = *p; - - p2 = (Elf32_Sym*)symtab_section->data; - - for (j = 0; j < nb_syms; j++) { - if (p2->st_info == 0x12) { - // this is a func symbol - - name2 = (char*)symtab_section->link->data + p2->st_name; - - // find the function data index - - for (k = 0; k < nFuncs; k++) { - if (strcmp(name2, Func[k]) == 0) - break; - } - - if (k >= nFuncs) { - tcc_error("debug (sort) info can't find function: %s", - name2); - } - - if (strcmp(AssociatedFile[k], name) == 0) { - // yes they match copy it over - - NewTable[n++] = *p2; - } - } - p2++; - } - } - p++; - } - - // now all the filename and func symbols should have been copied over - // copy all the rest over (all except file and funcs) - - p = (Elf32_Sym*)symtab_section->data; - for (i = 0; i < nb_syms; i++) { - if (p->st_info != 4 && p->st_info != 0x12) { - NewTable[n++] = *p; - } - p++; - } - - if (n != nb_syms) - tcc_error("Internal Compiler error, debug info"); - - // copy it all back - - p = (Elf32_Sym*)symtab_section->data; - for (i = 0; i < nb_syms; i++) { - *p++ = NewTable[i]; - } - - tcc_free(NewTable); -} - -int FindCoffSymbolIndex(const char* func_name) -{ - int i, n = 0; - Elf32_Sym* p; - char* name; - - p = (Elf32_Sym*)symtab_section->data; - - for (i = 0; i < nb_syms; i++) { - - name = (char*)symtab_section->link->data + p->st_name; - - if (p->st_info == 4) { - // put a filename symbol - n++; - } else if (p->st_info == 0x12) { - - if (strcmp(func_name, name) == 0) - return n; - - n += 6; - - // put a Function Name - - // now put aux info - - // put a .bf - - // now put aux info - - // put a .ef - - // now put aux info - - } else { - n += 2; - } - - p++; - } - - return n; // total number of symbols -} - -int OutputTheSection(Section* sect) -{ - const char* s = sect->name; - - if (!strcmp(s, ".text")) - return 1; - else if (!strcmp(s, ".data")) - return 1; - else - return 0; -} - -short int GetCoffFlags(const char* s) -{ - if (!strcmp(s, ".text")) - return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400; - else if (!strcmp(s, ".data")) - return STYP_DATA; - else if (!strcmp(s, ".bss")) - return STYP_BSS; - else if (!strcmp(s, ".stack")) - return STYP_BSS | STYP_ALIGN | 0x200; - else if (!strcmp(s, ".cinit")) - return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200; - else - return 0; -} - -Section* FindSection(TCCState* s1, const char* sname) -{ - Section* s; - int i; - - for (i = 1; i < s1->nb_sections; i++) { - s = s1->sections[i]; - - if (!strcmp(sname, s->name)) - return s; - } - - tcc_error("could not find section %s", sname); - return 0; -} - -ST_FUNC int tcc_load_coff(TCCState* s1, int fd) -{ - // tktk TokenSym *ts; - - FILE* f; - unsigned int str_size; - char* Coff_str_table, *name; - int i, k; - struct syment csym; - char name2[9]; - FILHDR file_hdr; /* FILE HEADER STRUCTURE */ - - f = fdopen(fd, "rb"); - if (!f) { - tcc_error("Unable to open .out file for input"); - } - - if (fread(&file_hdr, FILHSZ, 1, f) != 1) - tcc_error("error reading .out file for input"); - - if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1) - tcc_error("error reading .out file for input"); - - // first read the string table - - if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET)) - tcc_error("error reading .out file for input"); - - if (fread(&str_size, sizeof(int), 1, f) != 1) - tcc_error("error reading .out file for input"); - - Coff_str_table = (char*)tcc_malloc(str_size); - - if (fread(Coff_str_table, str_size - 4, 1, f) != 1) - tcc_error("error reading .out file for input"); - - // read/process all the symbols - - // seek back to symbols - - if (fseek(f, file_hdr.f_symptr, SEEK_SET)) - tcc_error("error reading .out file for input"); - - for (i = 0; i < file_hdr.f_nsyms; i++) { - if (fread(&csym, SYMESZ, 1, f) != 1) - tcc_error("error reading .out file for input"); - - if (csym._n._n_n._n_zeroes == 0) { - name = Coff_str_table + csym._n._n_n._n_offset - 4; - } else { - name = csym._n._n_name; - - if (name[7] != 0) { - for (k = 0; k < 8; k++) - name2[k] = name[k]; - - name2[8] = 0; - - name = name2; - } - } - // if (strcmp("_DAC_Buffer",name)==0) // tktk - // name[0]=0; - - if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || - ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || - (csym.n_type == 0x4 && csym.n_sclass == 0x2) || - (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures - (csym.n_type == 0x18 && - csym.n_sclass == 0x2) || // pointer to structure - (csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles - (csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats - { - // strip off any leading underscore (except for other main routine) - - if (name[0] == '_' && strcmp(name, "_main") != 0) - name++; - - tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value); - } - // skip any aux records - - if (csym.n_numaux == 1) { - if (fread(&csym, SYMESZ, 1, f) != 1) - tcc_error("error reading .out file for input"); - i++; - } - } - - return 0; -} diff --git a/src/stab.def b/stab.def similarity index 100% rename from src/stab.def rename to stab.def diff --git a/src/stab.h b/stab.h similarity index 100% rename from src/stab.h rename to stab.h diff --git a/docs/tcc-doc.texi b/tcc-doc.texi similarity index 98% rename from docs/tcc-doc.texi rename to tcc-doc.texi index c673c2c..a8849f0 100644 --- a/docs/tcc-doc.texi +++ b/tcc-doc.texi @@ -99,9 +99,9 @@ the @code{main()} of a.c. @item @samp{tcc a.c -run b.c arg1} Compile @file{a.c} and @file{b.c}, link them together and execute them. arg1 is given -as first argument to the @code{main()} of the resulting program. -@ignore -Because multiple C files are specified, @option{--} are necessary to clearly +as first argument to the @code{main()} of the resulting program. +@ignore +Because multiple C files are specified, @option{--} are necessary to clearly separate the program arguments from the TCC options. @end ignore @@ -136,14 +136,14 @@ need to add @code{#!/usr/local/bin/tcc -run} at the start of your C source: #!/usr/local/bin/tcc -run #include -int main() +int main() @{ printf("Hello World\n"); return 0; @} @end example -TCC can read C source code from @emph{standard input} when @option{-} is used in +TCC can read C source code from @emph{standard input} when @option{-} is used in place of @option{infile}. Example: @example @@ -271,7 +271,7 @@ Make string constants be of type @code{const char *} instead of @code{char @item -Werror Abort compilation if warnings are issued. -@item -Wall +@item -Wall Activate all warnings, except @option{-Werror}, @option{-Wunusupported} and @option{-Wwrite-strings}. @@ -451,7 +451,7 @@ function name. int tab[10] = @{ 1, 2, [5] = 5, [9] = 9@}; @end example - + @item Compound initializers are supported: @example int *p = (int [])@{ 1, 2, 3 @}; @@ -465,7 +465,7 @@ works for structures and strings. @end example @noindent -is the same as writing +is the same as writing @example double d = 4771840.0; @end example @@ -481,12 +481,12 @@ TCC implements some GNU C extensions: @itemize -@item array designators can be used without '=': +@item array designators can be used without '=': @example int a[10] = @{ [0] 1, [5] 2, 3, 4 @}; @end example -@item Structure field designators can be a label: +@item Structure field designators can be a label: @example struct @{ int x, y; @} st = @{ x: 1, y: 1@}; @end example @@ -555,7 +555,7 @@ Here are some examples: align variable @code{a} to 8 bytes and put it in section @code{.mysection}. @example - int my_add(int a, int b) __attribute__ ((section(".mycodesection"))) + int my_add(int a, int b) __attribute__ ((section(".mycodesection"))) @{ return a + b; @} @@ -572,17 +572,17 @@ generate function @code{my_add} in section @code{.mycodesection}. dprintf("one arg %d\n", 1); @end example -@item @code{__FUNCTION__} is interpreted as C99 @code{__func__} +@item @code{__FUNCTION__} is interpreted as C99 @code{__func__} (so it has not exactly the same semantics as string literal GNUC where it is a string literal). -@item The @code{__alignof__} keyword can be used as @code{sizeof} +@item The @code{__alignof__} keyword can be used as @code{sizeof} to get the alignment of a type or an expression. -@item The @code{typeof(x)} returns the type of @code{x}. +@item The @code{typeof(x)} returns the type of @code{x}. @code{x} is an expression or a type. -@item Computed gotos: @code{&&label} returns a pointer of type +@item Computed gotos: @code{&&label} returns a pointer of type @code{void *} on the goto label @code{label}. @code{goto *expr} can be used to jump on the pointer resulting from @code{expr}. @@ -616,7 +616,7 @@ TCC includes its own x86 inline assembler with a @code{gas}-like (GNU assembler) syntax. No intermediate files are generated. GCC 3.x named operands are supported. -@item @code{__builtin_types_compatible_p()} and @code{__builtin_constant_p()} +@item @code{__builtin_types_compatible_p()} and @code{__builtin_constant_p()} are supported. @item @code{#pragma pack} is supported for win32 compatibility. @@ -681,7 +681,7 @@ same as C. @item +, - @end enumerate -@item A value is either an absolute number or a label plus an offset. +@item A value is either an absolute number or a label plus an offset. All operators accept absolute values except '+' and '-'. '+' or '-' can be used to add an offset to a label. '-' supports two labels only if they are the same or if they are both defined and in the same section. @@ -694,7 +694,7 @@ are the same or if they are both defined and in the same section. @item All labels are considered as local, except undefined ones. -@item Numeric labels can be used as local @code{gas}-like labels. +@item Numeric labels can be used as local @code{gas}-like labels. They can be defined several times in the same source. Use 'b' (backward) or 'f' (forward) as suffix to reference them: @@ -901,7 +901,7 @@ Here are some examples of caught errors: @chapter The @code{libtcc} library The @code{libtcc} library enables you to use TCC as a backend for -dynamic code generation. +dynamic code generation. Read the @file{libtcc.h} to have an overview of the API. Read @file{libtcc_test.c} to have a very simple example. @@ -941,10 +941,10 @@ except: @itemize -@item For initialized arrays with unknown size, a first pass +@item For initialized arrays with unknown size, a first pass is done to count the number of elements. -@item For architectures where arguments are evaluated in +@item For architectures where arguments are evaluated in reverse order, a first pass is done to reverse the argument order. @end itemize @@ -1156,7 +1156,7 @@ stack. @item VT_CMP indicates that the value is actually stored in the CPU flags (i.e. the value is the consequence of a test). The value is either 0 or 1. The -actual CPU flags used is indicated in @code{SValue.c.i}. +actual CPU flags used is indicated in @code{SValue.c.i}. If any code is generated which destroys the CPU flags, this value MUST be put in a normal register. @@ -1176,7 +1176,7 @@ taken. @item VT_LVAL is a flag indicating that the value is actually an lvalue (left value of an assignment). It means that the value stored is actually a pointer to -the wanted value. +the wanted value. Understanding the use @code{VT_LVAL} is very important if you want to understand how TCC works. diff --git a/src/tcc.c b/tcc.c similarity index 99% rename from src/tcc.c rename to tcc.c index cce9699..704f8bc 100644 --- a/src/tcc.c +++ b/tcc.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 diff --git a/src/tcc.h b/tcc.h similarity index 99% rename from src/tcc.h rename to tcc.h index eb0365d..567c294 100644 --- a/src/tcc.h +++ b/tcc.h @@ -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 @@ -293,20 +293,20 @@ #define TARGET_DEFS_ONLY #ifdef TCC_TARGET_I386 -# include "x86/i386-gen.c" +# include "i386-gen.c" #endif #ifdef TCC_TARGET_X86_64 -# include "x86/x86_64-gen.c" +# include "x86_64-gen.c" #endif #ifdef TCC_TARGET_ARM -# include "arm/arm-gen.c" +# include "arm-gen.c" #endif #ifdef TCC_TARGET_ARM64 -# include "arm/arm64-gen.c" +# include "arm64-gen.c" #endif #ifdef TCC_TARGET_C67 # include "coff.h" -# include "tms320c67c67-gen.c" +# include "c67-gen.c" #endif #undef TARGET_DEFS_ONLY @@ -605,7 +605,7 @@ struct TCCState { int old_struct_init_code; /* use old algorithm to init array in struct when there is no '{' used. Liuux 2.4.26 can't find initrd when compiled with a new algorithm */ int dollars_in_identifiers; /* allows '$' char in indentifiers */ - + /* warning switches */ int warn_write_strings; int warn_unsupported; @@ -631,7 +631,7 @@ struct TCCState { char *init_symbol; /* symbols to call at load-time (not used currently) */ char *fini_symbol; /* symbols to call at unload-time (not used currently) */ - + #ifdef TCC_TARGET_I386 int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */ #endif @@ -885,7 +885,7 @@ struct TCCState { #define TOK_SHL 0x01 /* shift left */ #define TOK_SAR 0x02 /* signed shift right */ - + /* assignement operators : normal operator or 0x80 */ #define TOK_A_MOD 0xa5 #define TOK_A_AND 0xa6 diff --git a/src/tccasm.c b/tccasm.c similarity index 95% rename from src/tccasm.c rename to tccasm.c index be34ef4..3cbae19 100644 --- a/src/tccasm.c +++ b/tccasm.c @@ -1,6 +1,6 @@ /* * GAS like assembler for TCC - * + * * Copyright (c) 2001-2004 Fabrice Bellard * * This library is free software; you can redistribute it and/or @@ -92,10 +92,10 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe) break; case TOK_CCHAR: case TOK_LCHAR: - pe->v = tokc.i; - pe->sym = NULL; - next(); - break; + pe->v = tokc.i; + pe->sym = NULL; + next(); + break; case '(': next(); asm_expr(s1, pe); @@ -125,7 +125,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe) break; } } - + static void asm_expr_prod(TCCState *s1, ExprValue *pe) { int op; @@ -134,7 +134,7 @@ static void asm_expr_prod(TCCState *s1, ExprValue *pe) asm_expr_unary(s1, pe); for(;;) { op = tok; - if (op != '*' && op != '/' && op != '%' && + if (op != '*' && op != '/' && op != '%' && op != TOK_SHL && op != TOK_SAR) break; next(); @@ -145,14 +145,14 @@ static void asm_expr_prod(TCCState *s1, ExprValue *pe) case '*': pe->v *= e2.v; break; - case '/': + case '/': if (e2.v == 0) { div_error: tcc_error("division by zero"); } pe->v /= e2.v; break; - case '%': + case '%': if (e2.v == 0) goto div_error; pe->v %= e2.v; @@ -186,7 +186,7 @@ static void asm_expr_logic(TCCState *s1, ExprValue *pe) case '&': pe->v &= e2.v; break; - case '|': + case '|': pe->v |= e2.v; break; default: @@ -224,7 +224,7 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe) } else if (pe->sym && !e2.sym) { /* OK */ } else if (pe->sym && e2.sym) { - if (pe->sym == e2.sym) { + if (pe->sym == e2.sym) { /* OK */ } else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) { /* we also accept defined symbols in the same section */ @@ -267,7 +267,7 @@ static void asm_new_label1(TCCState *s1, int label, int is_local, if (sym->r) { /* the label is already defined */ if (!is_local) { - tcc_error("assembler label '%s' already defined", + tcc_error("assembler label '%s' already defined", get_tok_str(label, NULL)); } else { /* redefinition of local labels is possible */ @@ -492,25 +492,25 @@ static void asm_parse_directive(TCCState *s1) case TOK_ASM_global: case TOK_ASM_weak: case TOK_ASM_hidden: - tok1 = tok; - do { - Sym *sym; + tok1 = tok; + do { + Sym *sym; - next(); - sym = label_find(tok); - if (!sym) { - sym = label_push(&s1->asm_labels, tok, 0); - sym->type.t = VT_VOID; - } - 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; + next(); + sym = label_find(tok); + if (!sym) { + sym = label_push(&s1->asm_labels, tok, 0); + sym->type.t = VT_VOID; + } + 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; case TOK_ASM_string: case TOK_ASM_ascii: case TOK_ASM_asciz: @@ -536,24 +536,24 @@ static void asm_parse_directive(TCCState *s1) break; } } - } - break; + } + break; case TOK_ASM_text: case TOK_ASM_data: case TOK_ASM_bss: - { + { char sname[64]; tok1 = tok; n = 0; next(); if (tok != ';' && tok != TOK_LINEFEED) { - n = asm_int_expr(s1); - next(); + n = asm_int_expr(s1); + next(); } sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n); use_section(s1, sname); - } - break; + } + break; case TOK_ASM_file: { char filename[512]; @@ -591,7 +591,7 @@ static void asm_parse_directive(TCCState *s1) } break; case TOK_ASM_size: - { + { Sym *sym; next(); @@ -612,7 +612,7 @@ static void asm_parse_directive(TCCState *s1) } break; case TOK_ASM_type: - { + { Sym *sym; const char *newtype; @@ -637,7 +637,7 @@ static void asm_parse_directive(TCCState *s1) 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", + tcc_warning("change type of '%s' from 0x%x to '%s' ignored", get_tok_str(sym->v, NULL), sym->type.t, newtype); next(); @@ -669,7 +669,7 @@ static void asm_parse_directive(TCCState *s1) } break; case TOK_ASM_previous: - { + { Section *sec; next(); if (!last_text_section) @@ -830,7 +830,7 @@ ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess) cur_text_section->data_offset = ind; - free_defines(define_start); + free_defines(define_start); return ret; } @@ -863,7 +863,7 @@ static void tcc_assemble_inline(TCCState *s1, char *str, int len) /* find a constraint by its number or id (gcc 3 extended syntax). return -1 if not found. Return in *pp in char after the constraint */ -ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, +ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp) { int index; @@ -901,7 +901,7 @@ ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, return index; } -static void subst_asm_operands(ASMOperand *operands, int nb_operands, +static void subst_asm_operands(ASMOperand *operands, int nb_operands, int nb_outputs, CString *out_str, CString *in_str) { @@ -1052,12 +1052,12 @@ ST_FUNC void asm_instr(void) token after the assembler parsing */ if (tok != ';') expect("';'"); - + /* save all values in the memory */ save_regs(0); /* compute constraints */ - asm_compute_constraints(operands, nb_operands, nb_outputs, + asm_compute_constraints(operands, nb_operands, nb_outputs, clobber_regs, &out_reg); /* substitute the operands in the asm string. No substitution is @@ -1076,8 +1076,8 @@ ST_FUNC void asm_instr(void) #endif /* generate loads */ - asm_gen_code(operands, nb_operands, nb_outputs, 0, - clobber_regs, out_reg); + asm_gen_code(operands, nb_operands, nb_outputs, 0, + clobber_regs, out_reg); /* assemble the string with tcc internal assembler */ tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1); @@ -1086,9 +1086,9 @@ ST_FUNC void asm_instr(void) next(); /* store the output values if needed */ - asm_gen_code(operands, nb_operands, nb_outputs, 1, + asm_gen_code(operands, nb_operands, nb_outputs, 1, clobber_regs, out_reg); - + /* free everything */ for(i=0;idata_offset = ind; /* restore the current C token */ diff --git a/tcccoff.c b/tcccoff.c new file mode 100644 index 0000000..1421ca2 --- /dev/null +++ b/tcccoff.c @@ -0,0 +1,948 @@ +/* + * COFF file handling for TCC + * + * Copyright (c) 2003, 2004 TK + * Copyright (c) 2004 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "tcc.h" + +#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */ +#define MAX_STR_TABLE 1000000 +AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */ + +SCNHDR section_header[MAXNSCNS]; + +#define MAX_FUNCS 1000 +#define MAX_FUNC_NAME_LENGTH 128 + +int nFuncs; +char Func[MAX_FUNCS][MAX_FUNC_NAME_LENGTH]; +char AssociatedFile[MAX_FUNCS][MAX_FUNC_NAME_LENGTH]; +int LineNoFilePtr[MAX_FUNCS]; +int EndAddress[MAX_FUNCS]; +int LastLineNo[MAX_FUNCS]; +int FuncEntries[MAX_FUNCS]; + +int OutputTheSection(Section * sect); +short int GetCoffFlags(const char *s); +void SortSymbolTable(void); +Section *FindSection(TCCState * s1, const char *sname); + +int C67_main_entry_point; + +int FindCoffSymbolIndex(const char *func_name); +int nb_syms; + +typedef struct { + long tag; + long size; + long fileptr; + long nextsym; + short int dummy; +} AUXFUNC; + +typedef struct { + long regmask; + unsigned short lineno; + unsigned short nentries; + int localframe; + int nextentry; + short int dummy; +} AUXBF; + +typedef struct { + long dummy; + unsigned short lineno; + unsigned short dummy1; + int dummy2; + int dummy3; + unsigned short dummy4; +} AUXEF; + +ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f) +{ + Section *tcc_sect; + SCNHDR *coff_sec; + int file_pointer; + char *Coff_str_table, *pCoff_str_table; + int CoffTextSectionNo, coff_nb_syms; + FILHDR file_hdr; /* FILE HEADER STRUCTURE */ + Section *stext, *sdata, *sbss; + int i, NSectionsToOutput = 0; + + Coff_str_table = pCoff_str_table = NULL; + + stext = FindSection(s1, ".text"); + sdata = FindSection(s1, ".data"); + sbss = FindSection(s1, ".bss"); + + nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym); + coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1"); + + file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */ + file_hdr.f_timdat = 0; /* time & date stamp */ + file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */ + file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */ + file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */ + + o_filehdr.magic = 0x0108; /* see magic.h */ + o_filehdr.vstamp = 0x0190; /* version stamp */ + o_filehdr.tsize = stext->data_offset; /* text size in bytes, padded to FW bdry */ + o_filehdr.dsize = sdata->data_offset; /* initialized data " " */ + o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */ + o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */ + o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */ + o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */ + + + // create all the section headers + + file_pointer = FILHSZ + sizeof(AOUTHDR); + + CoffTextSectionNo = -1; + + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { + NSectionsToOutput++; + + if (CoffTextSectionNo == -1 && tcc_sect == stext) + CoffTextSectionNo = NSectionsToOutput; // rem which coff sect number the .text sect is + + strcpy(coff_sec->s_name, tcc_sect->name); /* section name */ + + coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */ + coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */ + coff_sec->s_size = tcc_sect->data_offset; /* section size */ + coff_sec->s_scnptr = 0; /* file ptr to raw data for section */ + coff_sec->s_relptr = 0; /* file ptr to relocation */ + coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */ + coff_sec->s_nreloc = 0; /* number of relocation entries */ + coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */ + coff_sec->s_reserved = 0; /* reserved byte */ + coff_sec->s_page = 0; /* memory page id */ + + file_pointer += sizeof(SCNHDR); + } + } + + file_hdr.f_nscns = NSectionsToOutput; /* number of sections */ + + // now loop through and determine file pointer locations + // for the raw data + + + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { + // put raw data + coff_sec->s_scnptr = file_pointer; /* file ptr to raw data for section */ + file_pointer += coff_sec->s_size; + } + } + + // now loop through and determine file pointer locations + // for the relocation data + + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { + // put relocations data + if (coff_sec->s_nreloc > 0) { + coff_sec->s_relptr = file_pointer; /* file ptr to relocation */ + file_pointer += coff_sec->s_nreloc * sizeof(struct reloc); + } + } + } + + // now loop through and determine file pointer locations + // for the line number data + + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + coff_sec->s_nlnno = 0; + coff_sec->s_lnnoptr = 0; + + if (s1->do_debug && tcc_sect == stext) { + // count how many line nos data + + // also find association between source file name and function + // so we can sort the symbol table + + + Stab_Sym *sym, *sym_end; + char func_name[MAX_FUNC_NAME_LENGTH], + last_func_name[MAX_FUNC_NAME_LENGTH]; + unsigned long func_addr, last_pc, pc; + const char *incl_files[INCLUDE_STACK_SIZE]; + int incl_index, len, last_line_num; + const char *str, *p; + + coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */ + + + func_name[0] = '\0'; + func_addr = 0; + incl_index = 0; + last_func_name[0] = '\0'; + last_pc = 0xffffffff; + last_line_num = 1; + sym = (Stab_Sym *) stab_section->data + 1; + sym_end = + (Stab_Sym *) (stab_section->data + + stab_section->data_offset); + + nFuncs = 0; + while (sym < sym_end) { + switch (sym->n_type) { + /* function start or end */ + case N_FUN: + if (sym->n_strx == 0) { + // end of function + + coff_sec->s_nlnno++; + file_pointer += LINESZ; + + pc = sym->n_value + func_addr; + func_name[0] = '\0'; + func_addr = 0; + EndAddress[nFuncs] = pc; + FuncEntries[nFuncs] = + (file_pointer - + LineNoFilePtr[nFuncs]) / LINESZ - 1; + LastLineNo[nFuncs++] = last_line_num + 1; + } else { + // beginning of function + + LineNoFilePtr[nFuncs] = file_pointer; + coff_sec->s_nlnno++; + file_pointer += LINESZ; + + str = + (const char *) stabstr_section->data + + sym->n_strx; + + p = strchr(str, ':'); + if (!p) { + pstrcpy(func_name, sizeof(func_name), str); + pstrcpy(Func[nFuncs], sizeof(func_name), str); + } else { + len = p - str; + if (len > sizeof(func_name) - 1) + len = sizeof(func_name) - 1; + memcpy(func_name, str, len); + memcpy(Func[nFuncs], str, len); + func_name[len] = '\0'; + } + + // save the file that it came in so we can sort later + pstrcpy(AssociatedFile[nFuncs], sizeof(func_name), + incl_files[incl_index - 1]); + + func_addr = sym->n_value; + } + break; + + /* line number info */ + case N_SLINE: + pc = sym->n_value + func_addr; + + last_pc = pc; + last_line_num = sym->n_desc; + + /* XXX: slow! */ + strcpy(last_func_name, func_name); + + coff_sec->s_nlnno++; + file_pointer += LINESZ; + break; + /* include files */ + case N_BINCL: + str = + (const char *) stabstr_section->data + sym->n_strx; + add_incl: + if (incl_index < INCLUDE_STACK_SIZE) { + incl_files[incl_index++] = str; + } + break; + case N_EINCL: + if (incl_index > 1) + incl_index--; + break; + case N_SO: + if (sym->n_strx == 0) { + incl_index = 0; /* end of translation unit */ + } else { + str = + (const char *) stabstr_section->data + + sym->n_strx; + /* do not add path */ + len = strlen(str); + if (len > 0 && str[len - 1] != '/') + goto add_incl; + } + break; + } + sym++; + } + } + + } + + file_hdr.f_symptr = file_pointer; /* file pointer to symtab */ + + if (s1->do_debug) + file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */ + else + file_hdr.f_nsyms = 0; + + file_pointer += file_hdr.f_nsyms * SYMNMLEN; + + // OK now we are all set to write the file + + + fwrite(&file_hdr, FILHSZ, 1, f); + fwrite(&o_filehdr, sizeof(o_filehdr), 1, f); + + // write section headers + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { + fwrite(coff_sec, sizeof(SCNHDR), 1, f); + } + } + + // write raw data + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { + fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f); + } + } + + // write relocation data + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { + // put relocations data + if (coff_sec->s_nreloc > 0) { + fwrite(tcc_sect->reloc, + coff_sec->s_nreloc * sizeof(struct reloc), 1, f); + } + } + } + + + // group the symbols in order of filename, func1, func2, etc + // finally global symbols + + if (s1->do_debug) + SortSymbolTable(); + + // write line no data + + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (s1->do_debug && tcc_sect == stext) { + // count how many line nos data + + + Stab_Sym *sym, *sym_end; + char func_name[128], last_func_name[128]; + unsigned long func_addr, last_pc, pc; + const char *incl_files[INCLUDE_STACK_SIZE]; + int incl_index, len, last_line_num; + const char *str, *p; + + LINENO CoffLineNo; + + func_name[0] = '\0'; + func_addr = 0; + incl_index = 0; + last_func_name[0] = '\0'; + last_pc = 0; + last_line_num = 1; + sym = (Stab_Sym *) stab_section->data + 1; + sym_end = + (Stab_Sym *) (stab_section->data + + stab_section->data_offset); + + while (sym < sym_end) { + switch (sym->n_type) { + /* function start or end */ + case N_FUN: + if (sym->n_strx == 0) { + // end of function + + CoffLineNo.l_addr.l_paddr = last_pc; + CoffLineNo.l_lnno = last_line_num + 1; + fwrite(&CoffLineNo, 6, 1, f); + + pc = sym->n_value + func_addr; + func_name[0] = '\0'; + func_addr = 0; + } else { + // beginning of function + + str = + (const char *) stabstr_section->data + + sym->n_strx; + + + p = strchr(str, ':'); + if (!p) { + pstrcpy(func_name, sizeof(func_name), str); + } else { + len = p - str; + if (len > sizeof(func_name) - 1) + len = sizeof(func_name) - 1; + memcpy(func_name, str, len); + func_name[len] = '\0'; + } + func_addr = sym->n_value; + last_pc = func_addr; + last_line_num = -1; + + // output a function begin + + CoffLineNo.l_addr.l_symndx = + FindCoffSymbolIndex(func_name); + CoffLineNo.l_lnno = 0; + + fwrite(&CoffLineNo, 6, 1, f); + } + break; + + /* line number info */ + case N_SLINE: + pc = sym->n_value + func_addr; + + + /* XXX: slow! */ + strcpy(last_func_name, func_name); + + // output a line reference + + CoffLineNo.l_addr.l_paddr = last_pc; + + if (last_line_num == -1) { + CoffLineNo.l_lnno = sym->n_desc; + } else { + CoffLineNo.l_lnno = last_line_num + 1; + } + + fwrite(&CoffLineNo, 6, 1, f); + + last_pc = pc; + last_line_num = sym->n_desc; + + break; + + /* include files */ + case N_BINCL: + str = + (const char *) stabstr_section->data + sym->n_strx; + add_incl2: + if (incl_index < INCLUDE_STACK_SIZE) { + incl_files[incl_index++] = str; + } + break; + case N_EINCL: + if (incl_index > 1) + incl_index--; + break; + case N_SO: + if (sym->n_strx == 0) { + incl_index = 0; /* end of translation unit */ + } else { + str = + (const char *) stabstr_section->data + + sym->n_strx; + /* do not add path */ + len = strlen(str); + if (len > 0 && str[len - 1] != '/') + goto add_incl2; + } + break; + } + sym++; + } + } + } + + // write symbol table + if (s1->do_debug) { + int k; + struct syment csym; + AUXFUNC auxfunc; + AUXBF auxbf; + AUXEF auxef; + int i; + Elf32_Sym *p; + const char *name; + int nstr; + int n = 0; + + Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE); + pCoff_str_table = Coff_str_table; + nstr = 0; + + p = (Elf32_Sym *) symtab_section->data; + + + for (i = 0; i < nb_syms; i++) { + + name = symtab_section->link->data + p->st_name; + + for (k = 0; k < 8; k++) + csym._n._n_name[k] = 0; + + if (strlen(name) <= 8) { + strcpy(csym._n._n_name, name); + } else { + if (pCoff_str_table - Coff_str_table + strlen(name) > + MAX_STR_TABLE - 1) + tcc_error("String table too large"); + + csym._n._n_n._n_zeroes = 0; + csym._n._n_n._n_offset = + pCoff_str_table - Coff_str_table + 4; + + strcpy(pCoff_str_table, name); + pCoff_str_table += strlen(name) + 1; // skip over null + nstr++; + } + + if (p->st_info == 4) { + // put a filename symbol + csym.n_value = 33; // ????? + csym.n_scnum = N_DEBUG; + csym.n_type = 0; + csym.n_sclass = C_FILE; + csym.n_numaux = 0; + fwrite(&csym, 18, 1, f); + n++; + + } else if (p->st_info == 0x12) { + // find the function data + + for (k = 0; k < nFuncs; k++) { + if (strcmp(name, Func[k]) == 0) + break; + } + + if (k >= nFuncs) { + tcc_error("debug info can't find function: %s", name); + } + // put a Function Name + + csym.n_value = p->st_value; // physical address + csym.n_scnum = CoffTextSectionNo; + csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0); + csym.n_sclass = C_EXT; + csym.n_numaux = 1; + fwrite(&csym, 18, 1, f); + + // now put aux info + + auxfunc.tag = 0; + auxfunc.size = EndAddress[k] - p->st_value; + auxfunc.fileptr = LineNoFilePtr[k]; + auxfunc.nextsym = n + 6; // tktk + auxfunc.dummy = 0; + fwrite(&auxfunc, 18, 1, f); + + // put a .bf + + strcpy(csym._n._n_name, ".bf"); + csym.n_value = p->st_value; // physical address + csym.n_scnum = CoffTextSectionNo; + csym.n_type = 0; + csym.n_sclass = C_FCN; + csym.n_numaux = 1; + fwrite(&csym, 18, 1, f); + + // now put aux info + + auxbf.regmask = 0; + auxbf.lineno = 0; + auxbf.nentries = FuncEntries[k]; + auxbf.localframe = 0; + auxbf.nextentry = n + 6; + auxbf.dummy = 0; + fwrite(&auxbf, 18, 1, f); + + // put a .ef + + strcpy(csym._n._n_name, ".ef"); + csym.n_value = EndAddress[k]; // physical address + csym.n_scnum = CoffTextSectionNo; + csym.n_type = 0; + csym.n_sclass = C_FCN; + csym.n_numaux = 1; + fwrite(&csym, 18, 1, f); + + // now put aux info + + auxef.dummy = 0; + auxef.lineno = LastLineNo[k]; + auxef.dummy1 = 0; + auxef.dummy2 = 0; + auxef.dummy3 = 0; + auxef.dummy4 = 0; + fwrite(&auxef, 18, 1, f); + + n += 6; + + } else { + // try an put some type info + + if ((p->st_other & VT_BTYPE) == VT_DOUBLE) { + csym.n_type = T_DOUBLE; // int + csym.n_sclass = C_EXT; + } else if ((p->st_other & VT_BTYPE) == VT_FLOAT) { + csym.n_type = T_FLOAT; + csym.n_sclass = C_EXT; + } else if ((p->st_other & VT_BTYPE) == VT_INT) { + csym.n_type = T_INT; // int + csym.n_sclass = C_EXT; + } else if ((p->st_other & VT_BTYPE) == VT_SHORT) { + csym.n_type = T_SHORT; + csym.n_sclass = C_EXT; + } else if ((p->st_other & VT_BTYPE) == VT_BYTE) { + csym.n_type = T_CHAR; + csym.n_sclass = C_EXT; + } else { + csym.n_type = T_INT; // just mark as a label + csym.n_sclass = C_LABEL; + } + + + csym.n_value = p->st_value; + csym.n_scnum = 2; + csym.n_numaux = 1; + fwrite(&csym, 18, 1, f); + + auxfunc.tag = 0; + auxfunc.size = 0x20; + auxfunc.fileptr = 0; + auxfunc.nextsym = 0; + auxfunc.dummy = 0; + fwrite(&auxfunc, 18, 1, f); + n++; + n++; + + } + + p++; + } + } + + if (s1->do_debug) { + // write string table + + // first write the size + i = pCoff_str_table - Coff_str_table; + fwrite(&i, 4, 1, f); + + // then write the strings + fwrite(Coff_str_table, i, 1, f); + + tcc_free(Coff_str_table); + } + + return 0; +} + + + +// group the symbols in order of filename, func1, func2, etc +// finally global symbols + +void SortSymbolTable(void) +{ + int i, j, k, n = 0; + Elf32_Sym *p, *p2, *NewTable; + char *name, *name2; + + NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym)); + + p = (Elf32_Sym *) symtab_section->data; + + + // find a file symbol, copy it over + // then scan the whole symbol list and copy any function + // symbols that match the file association + + for (i = 0; i < nb_syms; i++) { + if (p->st_info == 4) { + name = (char *) symtab_section->link->data + p->st_name; + + // this is a file symbol, copy it over + + NewTable[n++] = *p; + + p2 = (Elf32_Sym *) symtab_section->data; + + for (j = 0; j < nb_syms; j++) { + if (p2->st_info == 0x12) { + // this is a func symbol + + name2 = + (char *) symtab_section->link->data + p2->st_name; + + // find the function data index + + for (k = 0; k < nFuncs; k++) { + if (strcmp(name2, Func[k]) == 0) + break; + } + + if (k >= nFuncs) { + tcc_error("debug (sort) info can't find function: %s", name2); + } + + if (strcmp(AssociatedFile[k], name) == 0) { + // yes they match copy it over + + NewTable[n++] = *p2; + } + } + p2++; + } + } + p++; + } + + // now all the filename and func symbols should have been copied over + // copy all the rest over (all except file and funcs) + + p = (Elf32_Sym *) symtab_section->data; + for (i = 0; i < nb_syms; i++) { + if (p->st_info != 4 && p->st_info != 0x12) { + NewTable[n++] = *p; + } + p++; + } + + if (n != nb_syms) + tcc_error("Internal Compiler error, debug info"); + + // copy it all back + + p = (Elf32_Sym *) symtab_section->data; + for (i = 0; i < nb_syms; i++) { + *p++ = NewTable[i]; + } + + tcc_free(NewTable); +} + + +int FindCoffSymbolIndex(const char *func_name) +{ + int i, n = 0; + Elf32_Sym *p; + char *name; + + p = (Elf32_Sym *) symtab_section->data; + + for (i = 0; i < nb_syms; i++) { + + name = (char *) symtab_section->link->data + p->st_name; + + if (p->st_info == 4) { + // put a filename symbol + n++; + } else if (p->st_info == 0x12) { + + if (strcmp(func_name, name) == 0) + return n; + + n += 6; + + // put a Function Name + + // now put aux info + + // put a .bf + + // now put aux info + + // put a .ef + + // now put aux info + + } else { + n += 2; + } + + p++; + } + + return n; // total number of symbols +} + +int OutputTheSection(Section * sect) +{ + const char *s = sect->name; + + if (!strcmp(s, ".text")) + return 1; + else if (!strcmp(s, ".data")) + return 1; + else + return 0; +} + +short int GetCoffFlags(const char *s) +{ + if (!strcmp(s, ".text")) + return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400; + else if (!strcmp(s, ".data")) + return STYP_DATA; + else if (!strcmp(s, ".bss")) + return STYP_BSS; + else if (!strcmp(s, ".stack")) + return STYP_BSS | STYP_ALIGN | 0x200; + else if (!strcmp(s, ".cinit")) + return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200; + else + return 0; +} + +Section *FindSection(TCCState * s1, const char *sname) +{ + Section *s; + int i; + + for (i = 1; i < s1->nb_sections; i++) { + s = s1->sections[i]; + + if (!strcmp(sname, s->name)) + return s; + } + + tcc_error("could not find section %s", sname); + return 0; +} + +ST_FUNC int tcc_load_coff(TCCState * s1, int fd) +{ +// tktk TokenSym *ts; + + FILE *f; + unsigned int str_size; + char *Coff_str_table, *name; + int i, k; + struct syment csym; + char name2[9]; + FILHDR file_hdr; /* FILE HEADER STRUCTURE */ + + f = fdopen(fd, "rb"); + if (!f) { + tcc_error("Unable to open .out file for input"); + } + + if (fread(&file_hdr, FILHSZ, 1, f) != 1) + tcc_error("error reading .out file for input"); + + if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1) + tcc_error("error reading .out file for input"); + + // first read the string table + + if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET)) + tcc_error("error reading .out file for input"); + + if (fread(&str_size, sizeof(int), 1, f) != 1) + tcc_error("error reading .out file for input"); + + + Coff_str_table = (char *) tcc_malloc(str_size); + + if (fread(Coff_str_table, str_size - 4, 1, f) != 1) + tcc_error("error reading .out file for input"); + + // read/process all the symbols + + // seek back to symbols + + if (fseek(f, file_hdr.f_symptr, SEEK_SET)) + tcc_error("error reading .out file for input"); + + for (i = 0; i < file_hdr.f_nsyms; i++) { + if (fread(&csym, SYMESZ, 1, f) != 1) + tcc_error("error reading .out file for input"); + + if (csym._n._n_n._n_zeroes == 0) { + name = Coff_str_table + csym._n._n_n._n_offset - 4; + } else { + name = csym._n._n_name; + + if (name[7] != 0) { + for (k = 0; k < 8; k++) + name2[k] = name[k]; + + name2[8] = 0; + + name = name2; + } + } +// if (strcmp("_DAC_Buffer",name)==0) // tktk +// name[0]=0; + + if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures + (csym.n_type == 0x18 && csym.n_sclass == 0x2) || // pointer to structure + (csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles + (csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats + { + // strip off any leading underscore (except for other main routine) + + if (name[0] == '_' && strcmp(name, "_main") != 0) + name++; + + tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value); + } + // skip any aux records + + if (csym.n_numaux == 1) { + if (fread(&csym, SYMESZ, 1, f) != 1) + tcc_error("error reading .out file for input"); + i++; + } + } + + return 0; +} diff --git a/src/tccelf.c b/tccelf.c similarity index 93% rename from src/tccelf.c rename to tccelf.c index 2bbf479..1f87946 100644 --- a/src/tccelf.c +++ b/tccelf.c @@ -451,7 +451,7 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve) if (addr) { sym->st_value = (addr_t)addr; #ifdef DEBUG_RELOC - printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value); + printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value); #endif goto found; } @@ -580,10 +580,10 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) { int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko; x = (*(int *) ptr) & 0xffffff; - if (sym->st_shndx == SHN_UNDEF) - val = s1->plt->sh_addr; + if (sym->st_shndx == SHN_UNDEF) + val = s1->plt->sh_addr; #ifdef DEBUG_RELOC - printf ("reloc %d: x=0x%x val=0x%x ", type, x, val); + printf ("reloc %d: x=0x%x val=0x%x ", type, x, val); #endif (*(int *)ptr) &= 0xff000000; if (x & 0x800000) @@ -595,8 +595,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl)); x += val - addr; #ifdef DEBUG_RELOC - printf (" newx=0x%x name=%s\n", x, - (char *) symtab_section->link->data + sym->st_name); + printf (" newx=0x%x name=%s\n", x, + (char *) symtab_section->link->data + sym->st_name); #endif h = x & 2; th_ko = (x & 3) && (!blx_avail || !is_call); @@ -797,21 +797,21 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) break; case R_AARCH64_JUMP26: case R_AARCH64_CALL26: - /* This check must match the one in build_got_entries, testing - if we really need a PLT slot. */ - if (sym->st_shndx == SHN_UNDEF) - /* We've put the PLT slot offset into r_addend when generating - it, and that's what we must use as relocation value (adjusted - by section offset of course). */ - val = s1->plt->sh_addr + rel->r_addend; + /* This check must match the one in build_got_entries, testing + if we really need a PLT slot. */ + if (sym->st_shndx == SHN_UNDEF) + /* We've put the PLT slot offset into r_addend when generating + it, and that's what we must use as relocation value (adjusted + by section offset of course). */ + val = s1->plt->sh_addr + rel->r_addend; #ifdef DEBUG_RELOC - printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val, - (char *) symtab_section->link->data + sym->st_name); + printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val, + (char *) symtab_section->link->data + sym->st_name); #endif if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc) - { + { tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed (val=%lx, addr=%lx)", addr, val); - } + } *(uint32_t *)ptr = 0x14000000 | (type == R_AARCH64_CALL26) << 31 | ((val - addr) >> 2 & 0x3ffffff); break; @@ -836,9 +836,9 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) case R_AARCH64_JUMP_SLOT: /* They don't need addend */ #ifdef DEBUG_RELOC - printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, - val - rel->r_addend, - (char *) symtab_section->link->data + sym->st_name); + printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, + val - rel->r_addend, + (char *) symtab_section->link->data + sym->st_name); #endif *(addr_t *)ptr = val - rel->r_addend; break; @@ -879,12 +879,12 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) qrel->r_offset = rel->r_offset; if (esym_index) { qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64); - qrel->r_addend = rel->r_addend; + qrel->r_addend = rel->r_addend; qrel++; break; } else { - qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE); - qrel->r_addend = *(long long *)ptr + val; + qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE); + qrel->r_addend = *(long long *)ptr + val; qrel++; } } @@ -917,21 +917,21 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) goto plt32pc32; case R_X86_64_PLT32: - /* We've put the PLT slot offset into r_addend when generating - it, and that's what we must use as relocation value (adjusted - by section offset of course). */ - val = s1->plt->sh_addr + rel->r_addend; - /* fallthrough. */ + /* We've put the PLT slot offset into r_addend when generating + it, and that's what we must use as relocation value (adjusted + by section offset of course). */ + val = s1->plt->sh_addr + rel->r_addend; + /* fallthrough. */ - plt32pc32: - { - long long diff; - diff = (long long)val - addr; - if (diff < -2147483648LL || diff > 2147483647LL) { - tcc_error("internal error: relocation failed"); - } - *(int *)ptr += diff; + plt32pc32: + { + long long diff; + diff = (long long)val - addr; + if (diff < -2147483648LL || diff > 2147483647LL) { + tcc_error("internal error: relocation failed"); } + *(int *)ptr += diff; + } break; case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: @@ -1080,8 +1080,8 @@ static void build_got(TCCState *s1) and 'info' can be modifed if more precise info comes from the DLL. Returns offset of GOT or PLT slot. */ static unsigned long put_got_entry(TCCState *s1, - int reloc_type, unsigned long size, int info, - int sym_index) + int reloc_type, unsigned long size, int info, + int sym_index) { int index, need_plt_entry; const char *name; @@ -1107,18 +1107,18 @@ static unsigned long put_got_entry(TCCState *s1, #endif if (need_plt_entry && !s1->plt) { - /* add PLT */ - s1->plt = new_section(s1, ".plt", SHT_PROGBITS, - SHF_ALLOC | SHF_EXECINSTR); - s1->plt->sh_entsize = 4; + /* add PLT */ + s1->plt = new_section(s1, ".plt", SHT_PROGBITS, + SHF_ALLOC | SHF_EXECINSTR); + s1->plt->sh_entsize = 4; } /* If a got/plt entry already exists for that symbol, no need to add one */ if (sym_index < s1->nb_sym_attrs) { - if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset) - return s1->sym_attrs[sym_index].plt_offset; - else if (!need_plt_entry && s1->sym_attrs[sym_index].got_offset) - return s1->sym_attrs[sym_index].got_offset; + if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset) + return s1->sym_attrs[sym_index].plt_offset; + else if (!need_plt_entry && s1->sym_attrs[sym_index].got_offset) + return s1->sym_attrs[sym_index].got_offset; } symattr = alloc_sym_attr(s1, sym_index); @@ -1135,7 +1135,7 @@ static unsigned long put_got_entry(TCCState *s1, Section *plt; uint8_t *p; int modrm; - unsigned long relofs; + unsigned long relofs; #if defined(TCC_OUTPUT_DLL_WITH_PLT) modrm = 0x25; @@ -1160,10 +1160,10 @@ static unsigned long put_got_entry(TCCState *s1, put32(p + 8, PTR_SIZE * 2); } - /* The PLT slot refers to the relocation entry it needs - via offset. The reloc entry is created below, so its - offset is the current data_offset. */ - relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0; + /* The PLT slot refers to the relocation entry it needs + via offset. The reloc entry is created below, so its + offset is the current data_offset. */ + relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0; symattr->plt_offset = plt->data_offset; p = section_ptr_add(plt, 16); p[0] = 0xff; /* jmp *(got + x) */ @@ -1171,20 +1171,20 @@ static unsigned long put_got_entry(TCCState *s1, put32(p + 2, s1->got->data_offset); p[6] = 0x68; /* push $xxx */ #ifdef TCC_TARGET_X86_64 - /* On x86-64, the relocation is referred to by _index_. */ - put32(p + 7, relofs / sizeof (ElfW_Rel)); + /* On x86-64, the relocation is referred to by _index_. */ + put32(p + 7, relofs / sizeof (ElfW_Rel)); #else put32(p + 7, relofs); #endif p[11] = 0xe9; /* jmp plt_start */ put32(p + 12, -(plt->data_offset)); - /* If this was an UNDEF symbol set the offset in the - dynsymtab to the PLT slot, so that PC32 relocs to it - can be resolved. */ - if (sym->st_shndx == SHN_UNDEF) - offset = plt->data_offset - 16; - } + /* If this was an UNDEF symbol set the offset in the + dynsymtab to the PLT slot, so that PC32 relocs to it + can be resolved. */ + if (sym->st_shndx == SHN_UNDEF) + offset = plt->data_offset - 16; + } #elif defined(TCC_TARGET_ARM) if (need_plt_entry) { Section *plt; @@ -1220,9 +1220,9 @@ static unsigned long put_got_entry(TCCState *s1, /* the symbol is modified so that it will be relocated to the PLT */ - if (sym->st_shndx == SHN_UNDEF) + if (sym->st_shndx == SHN_UNDEF) offset = plt->data_offset - 16; - } + } #elif defined(TCC_TARGET_ARM64) if (need_plt_entry) { Section *plt; @@ -1250,29 +1250,29 @@ static unsigned long put_got_entry(TCCState *s1, #error unsupported CPU #endif if (s1->dynsym) { - /* XXX This might generate multiple syms for name. */ + /* XXX This might generate multiple syms for name. */ index = put_elf_sym(s1->dynsym, offset, size, info, 0, sym->st_shndx, name); /* Create the relocation (it's against the GOT for PLT - and GOT relocs). */ + and GOT relocs). */ put_elf_reloc(s1->dynsym, s1->got, s1->got->data_offset, reloc_type, index); } else { - /* Without .dynsym (i.e. static link or memory output) we - still need relocs against the generated got, so as to fill - the entries with the symbol values (determined later). */ - put_elf_reloc(symtab_section, s1->got, - s1->got->data_offset, - reloc_type, sym_index); + /* Without .dynsym (i.e. static link or memory output) we + still need relocs against the generated got, so as to fill + the entries with the symbol values (determined later). */ + put_elf_reloc(symtab_section, s1->got, + s1->got->data_offset, + reloc_type, sym_index); } /* And now create the GOT slot itself. */ ptr = section_ptr_add(s1->got, PTR_SIZE); *ptr = 0; if (need_plt_entry) - return symattr->plt_offset; + return symattr->plt_offset; else - return symattr->got_offset; + return symattr->got_offset; } /* build GOT and PLT entries */ @@ -1324,8 +1324,8 @@ ST_FUNC void build_got_entries(TCCState *s1) build_got(s1); sym_index = ELFW(R_SYM)(rel->r_info); sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC - && sym->st_shndx == SHN_UNDEF) { + if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC + && sym->st_shndx == SHN_UNDEF) { unsigned long ofs; /* look at the symbol got offset. If none, then add one */ if (type == R_ARM_GOT32) @@ -1333,27 +1333,27 @@ ST_FUNC void build_got_entries(TCCState *s1) else reloc_type = R_ARM_JUMP_SLOT; ofs = put_got_entry(s1, reloc_type, sym->st_size, - sym->st_info, sym_index); + sym->st_info, sym_index); #ifdef DEBUG_RELOC - printf("maybegot: %s, %d, %d --> ofs=0x%x\n", - (char *) symtab_section->link->data + sym->st_name, - type, sym->st_shndx, ofs); + printf ("maybegot: %s, %d, %d --> ofs=0x%x\n", + (char *) symtab_section->link->data + sym->st_name, + type, sym->st_shndx, ofs); #endif - if (type != R_ARM_GOT32) { - addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data - + rel->r_offset); - /* x must be signed! */ - int x = *ptr & 0xffffff; - x = (x << 8) >> 8; - x <<= 2; - x += ofs; - x >>= 2; + if (type != R_ARM_GOT32) { + addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data + + rel->r_offset); + /* x must be signed! */ + int x = *ptr & 0xffffff; + x = (x << 8) >> 8; + x <<= 2; + x += ofs; + x >>= 2; #ifdef DEBUG_RELOC - printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr, - (*ptr & 0xff000000) | x, x); + printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr, + (*ptr & 0xff000000) | x, x); #endif - *ptr = (*ptr & 0xff000000) | x; - } + *ptr = (*ptr & 0xff000000) | x; + } } break; case R_ARM_THM_JUMP24: @@ -1397,22 +1397,22 @@ ST_FUNC void build_got_entries(TCCState *s1) sym_index); break; - case R_AARCH64_JUMP26: - case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + case R_AARCH64_CALL26: if (!s1->got) build_got(s1); sym_index = ELFW(R_SYM)(rel->r_info); sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; if (sym->st_shndx == SHN_UNDEF) { - unsigned long ofs; - reloc_type = R_AARCH64_JUMP_SLOT; + unsigned long ofs; + reloc_type = R_AARCH64_JUMP_SLOT; ofs = put_got_entry(s1, reloc_type, sym->st_size, - sym->st_info, sym_index); - /* We store the place of the generated PLT slot - in our addend. */ - rel->r_addend += ofs; + sym->st_info, sym_index); + /* We store the place of the generated PLT slot + in our addend. */ + rel->r_addend += ofs; } - break; + break; #elif defined(TCC_TARGET_C67) case R_C60_GOT32: case R_C60_GOTOFF: @@ -1439,29 +1439,29 @@ ST_FUNC void build_got_entries(TCCState *s1) case R_X86_64_PLT32: sym_index = ELFW(R_SYM)(rel->r_info); sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - if (type == R_X86_64_PLT32 && - ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT) - { - rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32); - break; - } + if (type == R_X86_64_PLT32 && + ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT) + { + rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32); + break; + } if (!s1->got) build_got(s1); if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL || type == R_X86_64_PLT32) { - unsigned long ofs; + unsigned long ofs; /* look at the symbol got offset. If none, then add one */ if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL) reloc_type = R_X86_64_GLOB_DAT; else - reloc_type = R_X86_64_JUMP_SLOT; + reloc_type = R_X86_64_JUMP_SLOT; ofs = put_got_entry(s1, reloc_type, sym->st_size, - sym->st_info, sym_index); - if (type == R_X86_64_PLT32) - /* We store the place of the generated PLT slot - in our addend. */ - rel->r_addend += ofs; + sym->st_info, sym_index); + if (type == R_X86_64_PLT32) + /* We store the place of the generated PLT slot + in our addend. */ + rel->r_addend += ofs; } break; #else @@ -1546,21 +1546,21 @@ static int tcc_add_support(TCCState *s1, const char *filename) snprintf(buf, sizeof(buf), "%s/%s/%s", s1->tcc_lib_path, /* an cpu specific path inside tcc_lib_path, mainly for keeping libtcc1.a */ #ifdef TCC_TARGET_I386 - "i386" + "i386" #endif #ifdef TCC_TARGET_X86_64 - "x86_64" + "x86-64" #endif #ifdef TCC_TARGET_ARM - "arm" + "arm" #endif #ifdef TCC_TARGET_ARM64 - "arm64" + "arm64" #endif #ifdef TCC_TARGET_C67 - "C67" + "C67" #endif - , filename); + ,filename); return tcc_add_file(s1, buf, TCC_FILETYPE_BINARY); } @@ -1587,17 +1587,17 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1) when __bound_ptr_add, __bound_new_region, __bound_delete_region called */ - int sym_index = find_elf_sym(symtab_section, "__bound_init"); - if (sym_index) { - Section *init_section = find_section(s1, ".init"); - unsigned char *pinit = section_ptr_add(init_section, 5); - pinit[0] = 0xe8; - put32(pinit + 1, -4); - put_elf_reloc(symtab_section, init_section, - init_section->data_offset - 4, R_386_PC32, sym_index); - } - else - tcc_warning("__bound_init not defined"); + int sym_index = find_elf_sym(symtab_section, "__bound_init"); + if (sym_index) { + Section *init_section = find_section(s1, ".init"); + unsigned char *pinit = section_ptr_add(init_section, 5); + pinit[0] = 0xe8; + put32(pinit + 1, -4); + put_elf_reloc(symtab_section, init_section, + init_section->data_offset - 4, R_386_PC32, sym_index); + } + else + tcc_warning("__bound_init not defined"); } #endif } @@ -1905,11 +1905,11 @@ static void export_global_syms(TCCState *s1) s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms); for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { - name = (char *) symtab_section->link->data + sym->st_name; - dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, - sym->st_info, 0, sym->st_shndx, name); - index = sym - (ElfW(Sym) *) symtab_section->data; - s1->symtab_to_dynsym[index] = dynindex; + name = (char *) symtab_section->link->data + sym->st_name; + dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, + sym->st_info, 0, sym->st_shndx, name); + index = sym - (ElfW(Sym) *) symtab_section->data; + s1->symtab_to_dynsym[index] = dynindex; } } } @@ -2179,15 +2179,15 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, file_offset += s->sh_size; } } - if (j == 0) { - /* Make the first PT_LOAD segment include the program - headers itself (and the ELF header as well), it'll - come out with same memory use but will make various - tools like binutils strip work better. */ - ph->p_offset &= ~(ph->p_align - 1); - ph->p_vaddr &= ~(ph->p_align - 1); - ph->p_paddr &= ~(ph->p_align - 1); - } + if (j == 0) { + /* Make the first PT_LOAD segment include the program + headers itself (and the ELF header as well), it'll + come out with same memory use but will make various + tools like binutils strip work better. */ + ph->p_offset &= ~(ph->p_align - 1); + ph->p_vaddr &= ~(ph->p_align - 1); + ph->p_paddr &= ~(ph->p_align - 1); + } ph->p_filesz = file_offset - ph->p_offset; ph->p_memsz = addr - ph->p_vaddr; ph++; @@ -2662,10 +2662,10 @@ static int elf_output_file(TCCState *s1, const char *filename) for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) { if (sym->st_shndx == SHN_UNDEF) { /* relocate to PLT if symbol corresponds to a PLT entry, - but not if it's a weak symbol */ - if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) - sym->st_value = 0; - else if (sym->st_value) + but not if it's a weak symbol */ + if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) + sym->st_value = 0; + else if (sym->st_value) sym->st_value += s1->plt->sh_addr; } else if (sym->st_shndx < SHN_LORESERVE) { /* do symbol relocation */ @@ -2690,14 +2690,14 @@ static int elf_output_file(TCCState *s1, const char *filename) /* Create the ELF file with name 'filename' */ ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order); if (s1->do_strip) { - int rc; - const char *strip_cmd = "sstrip "; // super strip utility from ELFkickers - const char *null_dev = " 2> /dev/null"; - char buf[1050]; - snprintf(buf, sizeof(buf), "%s%s%s", strip_cmd, filename, null_dev); - rc = system(buf); - if (rc) - system(buf+1); // call a strip utility from binutils + int rc; + const char *strip_cmd = "sstrip "; // super strip utility from ELFkickers + const char *null_dev = " 2> /dev/null"; + char buf[1050]; + snprintf(buf, sizeof(buf), "%s%s%s", strip_cmd, filename, null_dev); + rc = system(buf); + if (rc) + system(buf+1); // call a strip utility from binutils } the_end: tcc_free(s1->symtab_to_dynsym); diff --git a/src/tccgen.c b/tccgen.c similarity index 95% rename from src/tccgen.c rename to tccgen.c index 981e991..5ed7b34 100644 --- a/src/tccgen.c +++ b/tccgen.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 @@ -299,7 +299,7 @@ static void weaken_symbol(Sym *sym) if (sym->c > 0) { int esym_type; ElfW(Sym) *esym; - + esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; esym_type = ELFW(ST_TYPE)(esym->st_info); esym->st_info = ELFW(ST_INFO)(STB_WEAK, esym_type); @@ -321,9 +321,9 @@ static void apply_visibility(Sym *sym, CType *type) if (sym->c > 0) { ElfW(Sym) *esym; - + esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; - vis >>= VT_VIS_SHIFT; + vis >>= VT_VIS_SHIFT; esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1)) | vis; } } @@ -425,7 +425,7 @@ ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsign /* push a reference to a section offset by adding a dummy symbol */ static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size) { - vpushsym(type, get_sym_ref(type, sec, offset, size)); + vpushsym(type, get_sym_ref(type, sec, offset, size)); } /* define a new external reference to a symbol 'v' of type 'u' */ @@ -461,7 +461,7 @@ static Sym *external_sym(int v, CType *type, int r, char *asm_label) s->r = r | VT_CONST | VT_SYM; s->type.t |= VT_EXTERN; } else if (!is_compatible_types(&s->type, type)) { - tcc_error("incompatible types for redefinition of '%s'", + tcc_error("incompatible types for redefinition of '%s'", get_tok_str(v, NULL)); } /* Merge some storage attributes. */ @@ -600,7 +600,7 @@ ST_FUNC int get_reg_ex(int rc, int rc2) { int r; SValue *p; - + for(r=0;rtype.t) && + if (is_float(vtop->type.t) && (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { Sym *sym; int *ptr; @@ -769,7 +769,7 @@ ST_FUNC int gv(int rc) #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP) CValue check; #endif - + /* XXX: unify with initializers handling ? */ /* CPUs usually cannot use float constants, so we store them generically in data segment */ @@ -803,7 +803,7 @@ ST_FUNC int gv(int rc) vtop->c.ptr_offset = 0; } #ifdef CONFIG_TCC_BCHECK - if (vtop->r & VT_MUSTBOUND) + if (vtop->r & VT_MUSTBOUND) gbound(); #endif @@ -921,7 +921,7 @@ ST_FUNC int gv(int rc) vtop->r = r; #ifdef TCC_TARGET_C67 /* uses register pairs for doubles */ - if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) + if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) vtop->r2 = r+1; #endif } @@ -1036,7 +1036,7 @@ static void lbuild(int t) vpop(); } -/* rotate n first stack elements to the bottom +/* rotate n first stack elements to the bottom I1 ... In -> I2 ... In I1 [top is right] */ ST_FUNC void vrotb(int n) @@ -1476,7 +1476,7 @@ static void gen_opic(int op) vtop--; } else { /* if commutative ops, put c2 as constant */ - if (c1 && (op == '+' || op == '&' || op == '^' || + if (c1 && (op == '+' || op == '&' || op == '^' || op == '|' || op == '*')) { vswap(); c2 = c1; //c = c1, c1 = c2, c2 = c; @@ -1582,13 +1582,13 @@ static void gen_opif(int op) case '+': f1 += f2; break; case '-': f1 -= f2; break; case '*': f1 *= f2; break; - case '/': + case '/': if (f2 == 0.0) { if (const_wanted) tcc_error("division by zero in constant"); goto general_case; } - f1 /= f2; + f1 /= f2; break; /* XXX: also handles tests ? */ default: @@ -1631,12 +1631,12 @@ static inline int is_null_pointer(SValue *p) return 0; return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) || ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0) || - ((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr_offset == 0); + ((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr_offset == 0); } static inline int is_integer_btype(int bt) { - return (bt == VT_BYTE || bt == VT_SHORT || + return (bt == VT_BYTE || bt == VT_SHORT || bt == VT_INT || bt == VT_LLONG); } @@ -1645,7 +1645,7 @@ static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op) { CType *type1, *type2, tmp_type1, tmp_type2; int bt1, bt2; - + /* null pointers are accepted for all comparisons as gcc */ if (is_null_pointer(p1) || is_null_pointer(p2)) return; @@ -1663,16 +1663,16 @@ static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op) /* both must be pointers or implicit function pointers */ if (bt1 == VT_PTR) { type1 = pointed_type(type1); - } else if (bt1 != VT_FUNC) + } else if (bt1 != VT_FUNC) goto invalid_operands; if (bt2 == VT_PTR) { type2 = pointed_type(type2); - } else if (bt2 != VT_FUNC) { + } else if (bt2 != VT_FUNC) { invalid_operands: tcc_error("invalid operands to binary %s", get_tok_str(op, NULL)); } - if ((type1->t & VT_BTYPE) == VT_VOID || + if ((type1->t & VT_BTYPE) == VT_VOID || (type2->t & VT_BTYPE) == VT_VOID) return; tmp_type1 = *type1; @@ -1698,7 +1698,7 @@ ST_FUNC void gen_op(int op) t2 = vtop[0].type.t; bt1 = t1 & VT_BTYPE; bt2 = t2 & VT_BTYPE; - + if (bt1 == VT_PTR || bt2 == VT_PTR) { /* at least one operand is a pointer */ /* relationnal op: must be both pointers */ @@ -1729,7 +1729,7 @@ ST_FUNC void gen_op(int op) #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64) vtop->type.t = VT_LLONG; #else - vtop->type.t = VT_INT; + vtop->type.t = VT_INT; #endif vswap(); gen_op(TOK_PDIV); @@ -1761,18 +1761,18 @@ ST_FUNC void gen_op(int op) #if 0 /* #ifdef CONFIG_TCC_BCHECK The main reason to removing this code: - #include - int main () - { - int v[10]; - int i = 10; - int j = 9; - fprintf(stderr, "v+i-j = %p\n", v+i-j); - fprintf(stderr, "v+(i-j) = %p\n", v+(i-j)); - } - When this code is on. then the output looks like - v+i-j = 0xfffffffe - v+(i-j) = 0xbff84000 + #include + int main () + { + int v[10]; + int i = 10; + int j = 9; + fprintf(stderr, "v+i-j = %p\n", v+i-j); + fprintf(stderr, "v+(i-j) = %p\n", v+(i-j)); + } + When this code is on. then the output looks like + v+i-j = 0xfffffffe + v+(i-j) = 0xbff84000 */ /* if evaluating constant expression, no code should be generated, so no bound check */ @@ -1880,7 +1880,7 @@ static void gen_cvt_itof1(int t) #ifdef TCC_TARGET_ARM64 gen_cvt_itof(t); #else - if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == + if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED)) { if (t == VT_FLOAT) @@ -2127,7 +2127,7 @@ static void gen_cast(CType *type) /* scalar to bool */ vpushi(0); gen_op(TOK_NE); - } else if ((dbt & VT_BTYPE) == VT_BYTE || + } else if ((dbt & VT_BTYPE) == VT_BYTE || (dbt & VT_BTYPE) == VT_SHORT) { if (sbt == VT_PTR) { vtop->type.t = VT_INT; @@ -2140,7 +2140,7 @@ static void gen_cast(CType *type) /* from long long: just take low order word */ lexpand(); vpop(); - } + } /* if lvalue and single word type, nothing to do because the lvalue already contains the real type size (see VT_LVAL_xxx constants) */ @@ -2194,7 +2194,7 @@ ST_FUNC int type_size(CType *type, int *a) #endif #elif defined(TCC_TARGET_ARM) #ifdef TCC_ARM_EABI - *a = 8; + *a = 8; #else *a = 4; #endif @@ -2289,7 +2289,7 @@ static int is_compatible_func(CType *type1, CType *type2) /* return true if type1 and type2 are the same. If unqualified is true, qualifiers on the types are ignored. - - enums are not checked as gcc __builtin_types_compatible_p () + - enums are not checked as gcc __builtin_types_compatible_p () */ static int compare_types(CType *type1, CType *type2, int unqualified) { @@ -2326,7 +2326,7 @@ static int compare_types(CType *type1, CType *type2, int unqualified) } /* return true if type1 and type2 are exactly the same (including - qualifiers). + qualifiers). */ static int is_compatible_types(CType *type1, CType *type2) { @@ -2344,7 +2344,7 @@ static int is_compatible_parameter_types(CType *type1, CType *type2) printed in the type */ /* XXX: union */ /* XXX: add array and function pointers */ -static void type_to_str(char *buf, int buf_size, +static void type_to_str(char *buf, int buf_size, CType *type, const char *varstr) { int bt, v, t; @@ -2450,18 +2450,18 @@ static void gen_assign_cast(CType *dt) dbt = dt->t & VT_BTYPE; sbt = st->t & VT_BTYPE; if (sbt == VT_VOID || dbt == VT_VOID) { - if (sbt == VT_VOID && dbt == VT_VOID) - ; /* - It is Ok if both are void - A test program: - void func1() {} - void func2() { - return func1(); - } - gcc accepts this program - */ - else - tcc_error("cannot cast from/to void"); + if (sbt == VT_VOID && dbt == VT_VOID) + ; /* + It is Ok if both are void + A test program: + void func1() {} + void func2() { + return func1(); + } + gcc accepts this program + */ + else + tcc_error("cannot cast from/to void"); } if (dt->t & VT_CONSTANT) tcc_warning("assignment of read-only location"); @@ -2487,7 +2487,7 @@ static void gen_assign_cast(CType *dt) if (sbt != VT_PTR) goto error; type2 = pointed_type(st); - if ((type1->t & VT_BTYPE) == VT_VOID || + if ((type1->t & VT_BTYPE) == VT_VOID || (type2->t & VT_BTYPE) == VT_VOID) { /* void * can match anything */ } else { @@ -2542,7 +2542,7 @@ ST_FUNC void vstore(void) dbt = ft & VT_BTYPE; if ((((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) || (sbt == VT_INT && dbt == VT_SHORT)) - && !(vtop->type.t & VT_BITFIELD)) { + && !(vtop->type.t & VT_BITFIELD)) { /* optimize char/short casts */ delayed_cast = VT_MUSTCAST; vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT))); @@ -2716,7 +2716,7 @@ ST_FUNC void inc(int post, int c) vrotb(3); } /* add constant */ - vpushi(c - TOK_MID); + vpushi(c - TOK_MID); gen_op('+'); vstore(); /* store value */ if (post) @@ -2734,7 +2734,7 @@ ST_FUNC void inc(int post, int c) static void parse_attribute(AttributeDef *ad) { int t, n; - + while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) { next(); skip('('); @@ -2764,20 +2764,20 @@ static void parse_attribute(AttributeDef *ad) next(); skip(')'); break; - case TOK_VISIBILITY1: - case TOK_VISIBILITY2: + case TOK_VISIBILITY1: + case TOK_VISIBILITY2: skip('('); if (tok != TOK_STR) expect("visibility(\"default|hidden|internal|protected\")"); - if (!strcmp (tokc.cstr->data, "default")) - ad->a.visibility = STV_DEFAULT; - else if (!strcmp (tokc.cstr->data, "hidden")) - ad->a.visibility = STV_HIDDEN; - else if (!strcmp (tokc.cstr->data, "internal")) - ad->a.visibility = STV_INTERNAL; - else if (!strcmp (tokc.cstr->data, "protected")) - ad->a.visibility = STV_PROTECTED; - else + if (!strcmp (tokc.cstr->data, "default")) + ad->a.visibility = STV_DEFAULT; + else if (!strcmp (tokc.cstr->data, "hidden")) + ad->a.visibility = STV_HIDDEN; + else if (!strcmp (tokc.cstr->data, "internal")) + ad->a.visibility = STV_INTERNAL; + else if (!strcmp (tokc.cstr->data, "protected")) + ad->a.visibility = STV_PROTECTED; + else expect("visibility(\"default|hidden|internal|protected\")"); next(); skip(')'); @@ -2787,7 +2787,7 @@ static void parse_attribute(AttributeDef *ad) if (tok == '(') { next(); n = expr_const(); - if (n <= 0 || (n & (n - 1)) != 0) + if (n <= 0 || (n & (n - 1)) != 0) tcc_error("alignment must be a positive power of two"); skip(')'); } else { @@ -2828,7 +2828,7 @@ static void parse_attribute(AttributeDef *ad) case TOK_REGPARM2: skip('('); n = expr_const(); - if (n > 3) + if (n > 3) n = 3; else if (n < 0) n = 0; @@ -2840,7 +2840,7 @@ static void parse_attribute(AttributeDef *ad) case TOK_FASTCALL2: case TOK_FASTCALL3: ad->a.func_call = FUNC_FASTCALLW; - break; + break; #endif case TOK_MODE: skip('('); @@ -2874,9 +2874,9 @@ static void parse_attribute(AttributeDef *ad) if (tok == '(') { int parenthesis = 0; do { - if (tok == '(') + if (tok == '(') parenthesis++; - else if (tok == ')') + else if (tok == ')') parenthesis--; next(); } while (parenthesis && tok != -1); @@ -2928,7 +2928,7 @@ static void struct_decl(CType *type, int u, int tdef) do_decl: type->t = u; type->ref = s; - + if (tok == '{') { next(); if (s->c != -1) @@ -2973,8 +2973,8 @@ static void struct_decl(CType *type, int u, int tdef) while (tok != '}') { parse_btype(&btype, &ad); while (1) { - if (flexible) - tcc_error("flexible array member '%s' not at the end of struct", + if (flexible) + tcc_error("flexible array member '%s' not at the end of struct", get_tok_str(v, NULL)); bit_size = -1; v = 0; @@ -2982,26 +2982,26 @@ static void struct_decl(CType *type, int u, int tdef) if (tok != ':') { type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT); if (v == 0) { - if ((type1.t & VT_BTYPE) != VT_STRUCT) - expect("identifier"); - else { - int v = btype.ref->v; - if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) { - if (tcc_state->ms_extensions == 0) - expect("identifier"); - } - } + if ((type1.t & VT_BTYPE) != VT_STRUCT) + expect("identifier"); + else { + int v = btype.ref->v; + if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) { + if (tcc_state->ms_extensions == 0) + expect("identifier"); + } + } } if (type_size(&type1, &align) < 0) { - if ((a == TOK_STRUCT) && (type1.t & VT_ARRAY) && c) - flexible = 1; - else - tcc_error("field '%s' has incomplete type", - get_tok_str(v, NULL)); + if ((a == TOK_STRUCT) && (type1.t & VT_ARRAY) && c) + flexible = 1; + else + tcc_error("field '%s' has incomplete type", + get_tok_str(v, NULL)); } if ((type1.t & VT_BTYPE) == VT_FUNC || (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE))) - tcc_error("invalid type for '%s'", + tcc_error("invalid type for '%s'", get_tok_str(v, NULL)); } if (tok == ':') { @@ -3009,10 +3009,10 @@ static void struct_decl(CType *type, int u, int tdef) bit_size = expr_const(); /* XXX: handle v = 0 case for messages */ if (bit_size < 0) - tcc_error("negative width in bit-field '%s'", + tcc_error("negative width in bit-field '%s'", get_tok_str(v, NULL)); if (v && bit_size == 0) - tcc_error("zero width for bit-field '%s'", + tcc_error("zero width for bit-field '%s'", get_tok_str(v, NULL)); } size = type_size(&type1, &align); @@ -3028,8 +3028,8 @@ static void struct_decl(CType *type, int u, int tdef) lbit_pos = 0; if (bit_size >= 0) { bt = type1.t & VT_BTYPE; - if (bt != VT_INT && - bt != VT_BYTE && + if (bt != VT_INT && + bt != VT_BYTE && bt != VT_SHORT && bt != VT_BOOL && bt != VT_ENUM && @@ -3056,7 +3056,7 @@ static void struct_decl(CType *type, int u, int tdef) bit_pos = 0; lbit_pos = bit_pos; /* XXX: handle LSB first */ - type1.t |= VT_BITFIELD | + type1.t |= VT_BITFIELD | (bit_pos << VT_STRUCT_SHIFT) | (bit_size << (VT_STRUCT_SHIFT + 6)); bit_pos += bit_size; @@ -3083,10 +3083,10 @@ static void struct_decl(CType *type, int u, int tdef) maxalign = align; } #if 0 - printf("add field %s offset=%d", + printf("add field %s offset=%d", get_tok_str(v, NULL), offset); if (type1.t & VT_BITFIELD) { - printf(" pos=%d size=%d", + printf(" pos=%d size=%d", (type1.t >> VT_STRUCT_SHIFT) & 0x3f, (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f); } @@ -3113,7 +3113,7 @@ static void struct_decl(CType *type, int u, int tdef) } skip('}'); /* store size and alignment */ - s->c = (c + maxalign - 1) & -maxalign; + s->c = (c + maxalign - 1) & -maxalign; s->r = maxalign; } } @@ -3126,7 +3126,7 @@ ST_FUNC int is_btype_size(int bt) } /* return 0 if no type declaration. otherwise, return the basic type - and skip it. + and skip it. */ static int parse_btype(CType *type, AttributeDef *ad) { @@ -3436,9 +3436,9 @@ static void post_type(CType *type, AttributeDef *ad) skip(')'); /* NOTE: const is ignored in returned type as it has a special meaning in gcc / C++ */ - type->t &= ~VT_CONSTANT; + type->t &= ~VT_CONSTANT; /* some ancient pre-K&R C allows a function to return an array - and the array brackets to be put after the arguments, such + and the array brackets to be put after the arguments, such that "int c()[]" means something like "int[] c()" */ if (tok == '[') { next(); @@ -3479,7 +3479,7 @@ static void post_type(CType *type, AttributeDef *ad) if (type->t == VT_FUNC) tcc_error("declaration of an array of functions"); t1 |= type->t & VT_VLA; - + if (t1 & VT_VLA) { loc -= type_size(&int_type, &align); loc &= -align; @@ -3493,7 +3493,7 @@ static void post_type(CType *type, AttributeDef *ad) } if (n != -1) vpop(); - + /* we push an anonymous symbol which will contain the array element type */ s = sym_push(SYM_FIELD, type, 0, n); @@ -3506,7 +3506,7 @@ static void post_type(CType *type, AttributeDef *ad) in 'type'. 'td' is a bitmask indicating which kind of type decl is expected. 'type' should contain the basic type. 'ad' is the attribute definition of the basic type. It can be modified by - type_decl(). + type_decl(). */ static void type_decl(CType *type, AttributeDef *ad, int *v, int td) { @@ -3537,7 +3537,7 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td) mk_pointer(type); type->t |= qualifiers; } - + /* XXX: clarify attribute handling */ if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) parse_attribute(ad); @@ -3576,7 +3576,7 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td) type->t |= storage; if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) parse_attribute(ad); - + if (!type1.t) return; /* append type at the end of type1 */ @@ -3711,7 +3711,7 @@ ST_FUNC void unary(void) next(); goto tok_next; case TOK_CINT: - case TOK_CCHAR: + case TOK_CCHAR: case TOK_LCHAR: vpushi(tokc.i); next(); @@ -3807,14 +3807,14 @@ ST_FUNC void unary(void) gen_cast(&type); } } else if (tok == '{') { - /* + /* if (nocode_wanted) tcc_error("statement expression in global scope"); */ - /* this check breaks compilation of the linux 2.4.26 with the meesage: - linux/include/net/tcp.h:945: error: statement expression in global scope */ + /* this check breaks compilation of the linux 2.4.26 with the meesage: + linux/include/net/tcp.h:945: error: statement expression in global scope */ /* save all registers */ - save_regs(0); + save_regs(0); /* statement expression : we do not accept break/continue inside as GCC does */ block(NULL, NULL, NULL, NULL, 0, 1); @@ -3872,12 +3872,12 @@ ST_FUNC void unary(void) if ((vtop->type.t & VT_BTYPE) == VT_PTR) tcc_error("pointer not accepted for unary plus"); /* In order to force cast, we add zero, except for floating point - where we really need an noop (otherwise -0.0 will be transformed - into +0.0). */ - if (!is_float(vtop->type.t)) { - vpushi(0); - gen_op('+'); - } + where we really need an noop (otherwise -0.0 will be transformed + into +0.0). */ + if (!is_float(vtop->type.t)) { + vpushi(0); + gen_op('+'); + } break; case TOK_SIZEOF: case TOK_ALIGNOF1: @@ -4050,20 +4050,20 @@ ST_FUNC void unary(void) next(); unary(); t = vtop->type.t & VT_BTYPE; - if (is_float(t)) { + if (is_float(t)) { /* In IEEE negate(x) isn't subtract(0,x), but rather - subtract(-0, x). */ - vpush(&vtop->type); - if (t == VT_FLOAT) - vtop->c.f = -0.0f; - else if (t == VT_DOUBLE) - vtop->c.d = -0.0; - else - vtop->c.ld = -0.0; - } else - vpushi(0); - vswap(); - gen_op('-'); + subtract(-0, x). */ + vpush(&vtop->type); + if (t == VT_FLOAT) + vtop->c.f = -0.0f; + else if (t == VT_DOUBLE) + vtop->c.d = -0.0; + else + vtop->c.ld = -0.0; + } else + vpushi(0); + vswap(); + gen_op('-'); break; case TOK_LAND: if (!gnu_ext) @@ -4087,7 +4087,7 @@ ST_FUNC void unary(void) vpushsym(&s->type, s); next(); break; - + // special qnan , snan and infinity values case TOK___NAN__: vpush64(VT_DOUBLE, 0x7ff8000000000000ULL); @@ -4123,7 +4123,7 @@ ST_FUNC void unary(void) #endif ) tcc_warning("implicit declaration of function '%s'", name); - s = external_global_sym(t, &func_old_type, 0); + s = external_global_sym(t, &func_old_type, 0); } if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) == (VT_STATIC | VT_INLINE | VT_FUNC)) { @@ -4142,11 +4142,11 @@ ST_FUNC void unary(void) /* if forward reference, we must point to s */ if (vtop->r & VT_SYM) { vtop->sym = s; - vtop->c.ptr_offset = 0; + vtop->c.ptr_offset = 0; } break; } - + /* post operations */ while (1) { if (tok == TOK_INC || tok == TOK_DEC) { @@ -4154,8 +4154,8 @@ ST_FUNC void unary(void) next(); } else if (tok == '.' || tok == TOK_ARROW) { int qualifiers; - /* field */ - if (tok == TOK_ARROW) + /* field */ + if (tok == TOK_ARROW) indir(); qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE); test_lvalue(); @@ -4312,10 +4312,10 @@ ST_FUNC void unary(void) size = type_size(&s->type, &align); - /* We're writing whole regs often, make sure there's enough - space. Assume register size is power of 2. */ - if (regsize > align) - align = regsize; + /* We're writing whole regs often, make sure there's enough + space. Assume register size is power of 2. */ + if (regsize > align) + align = regsize; loc = (loc - size) & -align; addr = loc; #if defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_PE) @@ -4610,16 +4610,16 @@ static void expr_cond(void) (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED)) type.t |= VT_UNSIGNED; } else if (bt1 == VT_PTR || bt2 == VT_PTR) { - /* If one is a null ptr constant the result type - is the other. */ - if (is_null_pointer (vtop)) - type = type1; - else if (is_null_pointer (&sv)) - type = type2; + /* If one is a null ptr constant the result type + is the other. */ + if (is_null_pointer (vtop)) + type = type1; + else if (is_null_pointer (&sv)) + type = type2; /* XXX: test pointer compatibility, C99 has more elaborate - rules here. */ - else - type = type1; + rules here. */ + else + type = type1; } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) { /* XXX: test function pointer compatibility */ type = bt1 == VT_FUNC ? type1 : type2; @@ -4637,7 +4637,7 @@ static void expr_cond(void) (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)) type.t |= VT_UNSIGNED; } - + /* now we convert second operand */ gen_cast(&type); if (VT_STRUCT == (vtop->type.t & VT_BTYPE)) @@ -4653,9 +4653,9 @@ static void expr_cond(void) } else if ((type.t & VT_BTYPE) == VT_LLONG) { /* for long longs, we use fixed registers to avoid having to handle a complicated move */ - rc = RC_IRET; + rc = RC_IRET; } - + r2 = gv(rc); /* this is horrible, but we must also convert first operand */ @@ -4677,7 +4677,7 @@ static void expr_cond(void) static void expr_eq(void) { int t; - + expr_cond(); if (tok == '=' || (tok >= TOK_A_MOD && tok <= TOK_A_DIV) || @@ -4783,20 +4783,21 @@ static void label_or_decl(int l) int last_tok; /* fast test first */ - if (tok >= TOK_UIDENT) { - /* no need to save tokc because tok is an identifier */ - last_tok = tok; - next(); - if (tok == ':') { - unget_tok(last_tok); - return; - } - unget_tok(last_tok); - } + if (tok >= TOK_UIDENT) + { + /* no need to save tokc because tok is an identifier */ + last_tok = tok; + next(); + if (tok == ':') { + unget_tok(last_tok); + return; + } + unget_tok(last_tok); + } decl(l); } -static void block(int *bsym, int *csym, int *case_sym, int *def_sym, +static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg, int is_expr) { int a, b, c, d; @@ -4857,7 +4858,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, frame_bottom->next = scope_stack_bottom; scope_stack_bottom = frame_bottom; llabel = local_label_stack; - + /* handle local labels declarations */ if (tok == TOK_LABEL) { next(); @@ -4890,10 +4891,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, Sym *p; switch(vtop->type.t & VT_BTYPE) { /* case VT_PTR: */ - /* this breaks a compilation of the linux kernel v2.4.26 */ - /* pmd_t *new = ({ __asm__ __volatile__("ud2\n") ; ((pmd_t *)1); }); */ - /* Look a commit a80acab: Display error on statement expressions with complex return type */ - /* A pointer is not a complex return type */ + /* this breaks a compilation of the linux kernel v2.4.26 */ + /* pmd_t *new = ({ __asm__ __volatile__("ud2\n") ; ((pmd_t *)1); }); */ + /* Look a commit a80acab: Display error on statement expressions with complex return type */ + /* A pointer is not a complex return type */ case VT_STRUCT: case VT_ENUM: case VT_FUNC: @@ -4905,14 +4906,14 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, /* pop locally defined symbols */ scope_stack_bottom = scope_stack_bottom->next; sym_pop(&local_stack, s); - + /* Pop VLA frames and restore stack pointer if required */ if (vlas_in_scope > saved_vlas_in_scope) { vla_sp_loc = saved_vlas_in_scope ? block_vla_sp_loc : vla_sp_root_loc; vla_sp_restore(); } vlas_in_scope = saved_vlas_in_scope; - + next(); } else if (tok == TOK_RETURN) { next(); @@ -5079,7 +5080,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, gsym_addr(b, c); scope_stack_bottom = scope_stack_bottom->next; sym_pop(&local_stack, s); - } else + } else if (tok == TOK_DO) { next(); a = 0; @@ -5153,7 +5154,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, skip(':'); is_expr = 0; goto block_after_label; - } else + } else if (tok == TOK_DEFAULT) { next(); skip(':'); @@ -5184,7 +5185,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, s->r = LABEL_FORWARD; } vla_sp_restore_root(); - if (s->r & LABEL_FORWARD) + if (s->r & LABEL_FORWARD) s->jnext = gjmp(s->jnext); else gjmp_addr(s->jnext); @@ -5239,8 +5240,8 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, address. cur_index/cur_field is the pointer to the current value. 'size_only' is true if only size info is needed (only used in arrays) */ -static void decl_designator(CType *type, Section *sec, unsigned long c, - int *cur_index, Sym **cur_field, +static void decl_designator(CType *type, Section *sec, unsigned long c, + int *cur_index, Sym **cur_field, int size_only) { Sym *s, *f; @@ -5264,7 +5265,7 @@ static void decl_designator(CType *type, Section *sec, unsigned long c, if (tok == TOK_DOTS && gnu_ext) { next(); index_last = expr_const(); - if (index_last < 0 || + if (index_last < 0 || (s->c >= 0 && index_last >= s->c) || index_last < index) expect("invalid index"); @@ -5360,7 +5361,7 @@ static void decl_designator(CType *type, Section *sec, unsigned long c, #define EXPR_ANY 2 /* store a value or an expression directly in global data or in local array */ -static void init_putv(CType *type, Section *sec, unsigned long c, +static void init_putv(CType *type, Section *sec, unsigned long c, int v, int expr_type) { int saved_global_expr, bt, bit_pos, bit_size; @@ -5386,7 +5387,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c, expr_eq(); break; } - + dtype = *type; dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */ @@ -5501,7 +5502,7 @@ static void init_putz(CType *t, Section *sec, unsigned long c, int size) allocation. 'first' is true if array '{' must be read (multi dimension implicit array init handling). 'size_only' is true if size only evaluation is wanted (only for arrays). */ -static void decl_initializer(CType *type, Section *sec, unsigned long c, +static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only) { int index, array_length, n, no_oblock, nb, parlevel, parlevel1, i; @@ -5511,14 +5512,14 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, if (type->t & VT_VLA) { int a; - + /* save current stack pointer */ if (vlas_in_scope == 0) { if (vla_sp_root_loc == -1) vla_sp_root_loc = (loc -= PTR_SIZE); gen_vla_sp_save(vla_sp_root_loc); } - + vla_runtime_type_size(type, &a); gen_vla_alloc(type, a); gen_vla_sp_save(c); @@ -5532,7 +5533,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, size1 = type_size(t1, &align1); no_oblock = 1; - if ((first && tok != TOK_LSTR && tok != TOK_STR) || + if ((first && tok != TOK_LSTR && tok != TOK_STR) || tok == '{') { if (tok != '{') tcc_error("character array initializer must be a literal," @@ -5543,7 +5544,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, /* only parse strings here if correct type (otherwise: handle them as ((w)char *) expressions */ - if ((tok == TOK_LSTR && + if ((tok == TOK_LSTR && #ifdef TCC_TARGET_PE (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED) #else @@ -5603,7 +5604,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, /* must put zero in holes (note that doing it that way ensures that it even works with designators) */ if (!size_only && array_length < index) { - init_putz(t1, sec, c + array_length * size1, + init_putz(t1, sec, c + array_length * size1, (index - array_length) * size1); } index++; @@ -5623,7 +5624,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, skip('}'); /* put zeros at the end */ if (!size_only && n >= 0 && array_length < n) { - init_putz(t1, sec, c + array_length * size1, + init_putz(t1, sec, c + array_length * size1, (n - array_length) * size1); } /* patch type size if needed */ @@ -5641,38 +5642,38 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, AttributeDef ad1; CType type1; next(); - if (tcc_state->old_struct_init_code) { - /* an old version of struct initialization. - It have a problems. But with a new version - linux 2.4.26 can't load ramdisk. - */ - while (tok == '(') { - par_count++; - next(); - } - if (!parse_btype(&type1, &ad1)) - expect("cast"); - type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); - #if 0 - if (!is_assignable_types(type, &type1)) - tcc_error("invalid type for cast"); - #endif - skip(')'); - } - else - { + if (tcc_state->old_struct_init_code) { + /* an old version of struct initialization. + It have a problems. But with a new version + linux 2.4.26 can't load ramdisk. + */ + while (tok == '(') { + par_count++; + next(); + } + if (!parse_btype(&type1, &ad1)) + expect("cast"); + type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); + #if 0 + if (!is_assignable_types(type, &type1)) + tcc_error("invalid type for cast"); + #endif + skip(')'); + } + else + { if (tok != '(') { - if (!parse_btype(&type1, &ad1)) - expect("cast"); - type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); - #if 0 - if (!is_assignable_types(type, &type1)) - tcc_error("invalid type for cast"); - #endif - skip(')'); - } else - unget_tok(tok); - } + if (!parse_btype(&type1, &ad1)) + expect("cast"); + type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); + #if 0 + if (!is_assignable_types(type, &type1)) + tcc_error("invalid type for cast"); + #endif + skip(')'); + } else + unget_tok(tok); + } } no_oblock = 1; @@ -5689,7 +5690,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, decl_designator(type, sec, c, NULL, &f, size_only); index = f->c; if (!size_only && array_length < index) { - init_putz(type, sec, c + array_length, + init_putz(type, sec, c + array_length, index - array_length); } index = index + type_size(&f->type, &align1); @@ -5698,28 +5699,28 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, /* gr: skip fields from same union - ugly. */ while (f->next) { - int align = 0; - int f_size = type_size(&f->type, &align); - int f_type = (f->type.t & VT_BTYPE); + int align = 0; + int f_size = type_size(&f->type, &align); + int f_type = (f->type.t & VT_BTYPE); ///printf("index: %2d %08x -- %2d %08x\n", f->c, f->type.t, f->next->c, f->next->type.t); /* test for same offset */ if (f->next->c != f->c) break; if ((f_type == VT_STRUCT) && (f_size == 0)) { - /* - Lets assume a structure of size 0 can't be a member of the union. - This allow to compile the following code from a linux kernel v2.4.26 - typedef struct { } rwlock_t; - struct fs_struct { - int count; - rwlock_t lock; - int umask; - }; - struct fs_struct init_fs = { { (1) }, (rwlock_t) {}, 0022, }; - tcc-0.9.23 can succesfully compile this version of the kernel. - gcc don't have problems with this code too. - */ + /* + Lets assume a structure of size 0 can't be a member of the union. + This allow to compile the following code from a linux kernel v2.4.26 + typedef struct { } rwlock_t; + struct fs_struct { + int count; + rwlock_t lock; + int umask; + }; + struct fs_struct init_fs = { { (1) }, (rwlock_t) {}, 0022, }; + tcc-0.9.23 can succesfully compile this version of the kernel. + gcc don't have problems with this code too. + */ break; } /* if yes, test for bitfield shift */ @@ -5742,7 +5743,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, } /* put zeros at the end */ if (!size_only && array_length < n) { - init_putz(type, sec, c + array_length, + init_putz(type, sec, c + array_length, n - array_length); } if (!no_oblock) @@ -5759,21 +5760,21 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, /* just skip expression */ parlevel = parlevel1 = 0; while ((parlevel > 0 || parlevel1 > 0 || - (tok != '}' && tok != ',')) && tok != -1) { + (tok != '}' && tok != ',')) && tok != -1) { if (tok == '(') parlevel++; else if (tok == ')') { - if (parlevel == 0 && parlevel1 == 0) - break; + if (parlevel == 0 && parlevel1 == 0) + break; parlevel--; } - else if (tok == '{') - parlevel1++; - else if (tok == '}') { - if (parlevel == 0 && parlevel1 == 0) - break; - parlevel1--; - } + else if (tok == '{') + parlevel1++; + else if (tok == '}') { + if (parlevel == 0 && parlevel1 == 0) + break; + parlevel1--; + } next(); } } else { @@ -5794,7 +5795,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, zero, then a reference to the new object is put in the value stack. If 'has_init' is 2, a special parsing is done to handle string constants. */ -static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, +static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, char *asm_label, int scope) { @@ -5825,7 +5826,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, initializers handling */ tok_str_new(&init_str); if (size < 0 || (flexible_array && has_init)) { - if (!has_init) + if (!has_init) tcc_error("unknown type size"); /* get all init string */ if (has_init == 2) { @@ -5854,7 +5855,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, } tok_str_add(&init_str, -1); tok_str_add(&init_str, 0); - + /* compute size */ save_parse_state(&saved_parse_state); @@ -5864,10 +5865,10 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, /* prepare second initializer parsing */ macro_ptr = init_str.str; next(); - + /* if still unknown size, error */ size = type_size(type, &align); - if (size < 0) + if (size < 0) tcc_error("unknown type size"); } if (flexible_array) @@ -5918,14 +5919,14 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, sym = sym_find(v); if (sym) { if (!is_compatible_types(&sym->type, type)) - tcc_error("incompatible types for redefinition of '%s'", + tcc_error("incompatible types for redefinition of '%s'", get_tok_str(v, NULL)); if (sym->type.t & VT_EXTERN) { /* if the variable is extern, it was not allocated */ sym->type.t &= ~VT_EXTERN; /* set array size if it was omitted in extern declaration */ - if ((sym->type.t & VT_ARRAY) && + if ((sym->type.t & VT_ARRAY) && sym->type.ref->c < 0 && type->ref->c >= 0) sym->type.ref->c = type->ref->c; @@ -5965,7 +5966,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, #endif sec->data_offset = data_offset; /* allocate section space to put the data */ - if (sec->sh_type != SHT_NOBITS && + if (sec->sh_type != SHT_NOBITS && data_offset > sec->data_allocated) section_realloc(sec, data_offset); /* align section if needed */ @@ -5994,12 +5995,12 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, } else { /* push global reference */ sym = get_sym_ref(type, sec, addr, size); - vpushsym(type, sym); + vpushsym(type, sym); } /* patch symbol weakness */ if (type->t & VT_WEAK) weaken_symbol(sym); - apply_visibility(sym, type); + apply_visibility(sym, type); #ifdef CONFIG_TCC_BCHECK /* handles bounds now because the symbol must be defined before for the relocation */ @@ -6035,12 +6036,12 @@ static void put_func_debug(Sym *sym) /* stabs info */ /* XXX: we put here a dummy type */ - snprintf(buf, sizeof(buf), "%s:%c1", + snprintf(buf, sizeof(buf), "%s:%c1", funcname, sym->type.t & VT_STATIC ? 'f' : 'F'); put_stabs_r(buf, N_FUN, 0, file->line_num, 0, cur_text_section, sym->c); /* //gr gdb wants a line at the function */ - put_stabn(N_SLINE, 0, file->line_num, 0); + put_stabn(N_SLINE, 0, file->line_num, 0); last_ind = 0; last_line_num = 0; } @@ -6057,10 +6058,10 @@ static void func_decl_list(Sym *func_sym) /* parse each declaration */ while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF && tok != TOK_ASM1 && tok != TOK_ASM2 && tok != TOK_ASM3) { - if (!parse_btype(&btype, &ad)) + if (!parse_btype(&btype, &ad)) expect("declaration list"); if (((btype.t & VT_BTYPE) == VT_ENUM || - (btype.t & VT_BTYPE) == VT_STRUCT) && + (btype.t & VT_BTYPE) == VT_STRUCT) && tok == ';') { /* we accept no variable after */ } else { @@ -6079,7 +6080,7 @@ static void func_decl_list(Sym *func_sym) found: /* check that no storage specifier except 'register' was given */ if (type.t & VT_STORAGE) - tcc_error("storage class specified for '%s'", get_tok_str(v, NULL)); + tcc_error("storage class specified for '%s'", get_tok_str(v, NULL)); convert_parameter_type(&type); /* we can add the type (NOTE: it could be local to the function) */ s->type = type; @@ -6139,7 +6140,7 @@ static void gen_function(Sym *sym) sym_pop(&local_stack, NULL); /* end of function */ /* patch symbol size */ - ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size = + ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size = ind - func_ind; /* patch symbol weakness (this definition overrules any prototype) */ if (sym->type.t & VT_WEAK) @@ -6233,13 +6234,13 @@ static int decl0(int l, int is_for_loop_init) btype.t = VT_INT; } if (((btype.t & VT_BTYPE) == VT_ENUM || - (btype.t & VT_BTYPE) == VT_STRUCT) && + (btype.t & VT_BTYPE) == VT_STRUCT) && tok == ';') { - if ((btype.t & VT_BTYPE) == VT_STRUCT) { - int v = btype.ref->v; - if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM) - tcc_warning("unnamed struct/union that defines no instances"); - } + if ((btype.t & VT_BTYPE) == VT_STRUCT) { + int v = btype.ref->v; + if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM) + tcc_warning("unnamed struct/union that defines no instances"); + } next(); continue; } @@ -6272,7 +6273,7 @@ static int decl0(int l, int is_for_loop_init) asm_label_instr(&astr); asm_label = tcc_strdup(astr.data); cstr_free(&astr); - + /* parse one last attribute list, after asm label */ parse_attribute(&ad); } @@ -6285,7 +6286,7 @@ static int decl0(int l, int is_for_loop_init) if (ad.a.func_export) type.t |= VT_EXPORT; #endif - type.t |= ad.a.visibility << VT_VIS_SHIFT; + type.t |= ad.a.visibility << VT_VIS_SHIFT; if (tok == '{') { if (l == VT_LOCAL) @@ -6298,11 +6299,11 @@ static int decl0(int l, int is_for_loop_init) while ((sym = sym->next) != NULL) if (!(sym->v & ~SYM_FIELD)) expect("identifier"); - + /* XXX: cannot do better now: convert extern line to static inline */ if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE)) type.t = (type.t & ~VT_EXTERN) | VT_STATIC; - + sym = sym_find(v); if (sym) { Sym *ref; @@ -6326,14 +6327,14 @@ static int decl0(int l, int is_for_loop_init) if (sym->type.t & VT_STATIC) type.t = (type.t & ~VT_EXTERN) | VT_STATIC; - /* If the definition has no visibility use the - one from prototype. */ - if (! (type.t & VT_VIS_MASK)) - type.t |= sym->type.t & VT_VIS_MASK; + /* If the definition has no visibility use the + one from prototype. */ + if (! (type.t & VT_VIS_MASK)) + type.t |= sym->type.t & VT_VIS_MASK; if (!is_compatible_types(&sym->type, &type)) { func_error1: - tcc_error("incompatible types for redefinition of '%s'", + tcc_error("incompatible types for redefinition of '%s'", get_tok_str(v, NULL)); } type.ref->a.func_proto = 0; @@ -6348,18 +6349,18 @@ static int decl0(int l, int is_for_loop_init) /* static inline functions are just recorded as a kind of macro. Their code will be emitted at the end of the compilation unit only if they are used */ - if ((type.t & (VT_INLINE | VT_STATIC)) == + if ((type.t & (VT_INLINE | VT_STATIC)) == (VT_INLINE | VT_STATIC)) { int block_level; struct InlineFunc *fn; const char *filename; - + filename = file ? file->filename : ""; fn = tcc_malloc(sizeof *fn + strlen(filename)); strcpy(fn->filename, filename); fn->sym = sym; tok_str_new(&fn->func_str); - + block_level = 0; for(;;) { int t; diff --git a/src/tcclib.h b/tcclib.h similarity index 96% rename from src/tcclib.h rename to tcclib.h index 13f2204..8d59e4c 100644 --- a/src/tcclib.h +++ b/tcclib.h @@ -1,8 +1,8 @@ -/* Simple libc header for TCC - * +/* Simple libc header for TCC + * * Add any function you want from the libc there. This file is here * only for your convenience so that you do not need to put the whole - * glibc include files on your floppy disk + * glibc include files on your floppy disk */ #ifndef _TCCLIB_H #define _TCCLIB_H diff --git a/src/tccpe.c b/tccpe.c similarity index 98% rename from src/tccpe.c rename to tccpe.c index ec2bcb1..0fd8c36 100644 --- a/src/tccpe.c +++ b/tccpe.c @@ -398,22 +398,22 @@ static int pe_find_import(TCCState * s1, ElfW(Sym) *sym) s = pe_export_name(s1, sym); if (n) { /* second try: */ - if (sym->st_other & ST_PE_STDCALL) { - /* try w/0 stdcall deco (windows API convention) */ - p = strrchr(s, '@'); - if (!p || s[0] != '_') - break; - strcpy(buffer, s+1)[p-s-1] = 0; - } else if (s[0] != '_') { /* try non-ansi function */ - buffer[0] = '_', strcpy(buffer + 1, s); - } else if (0 == memcmp(s, "__imp__", 7)) { /* mingw 2.0 */ - strcpy(buffer, s + 6); - } else if (0 == memcmp(s, "_imp___", 7)) { /* mingw 3.7 */ - strcpy(buffer, s + 6); - } else { - break; - } - s = buffer; + if (sym->st_other & ST_PE_STDCALL) { + /* try w/0 stdcall deco (windows API convention) */ + p = strrchr(s, '@'); + if (!p || s[0] != '_') + break; + strcpy(buffer, s+1)[p-s-1] = 0; + } else if (s[0] != '_') { /* try non-ansi function */ + buffer[0] = '_', strcpy(buffer + 1, s); + } else if (0 == memcmp(s, "__imp__", 7)) { /* mingw 2.0 */ + strcpy(buffer, s + 6); + } else if (0 == memcmp(s, "_imp___", 7)) { /* mingw 3.7 */ + strcpy(buffer, s + 6); + } else { + break; + } + s = buffer; } sym_index = find_elf_sym(s1->dynsymtab_section, s); // printf("find (%d) %d %s\n", n, sym_index, s); @@ -1266,7 +1266,7 @@ static int pe_check_symbols(struct pe_info *pe) put_elf_reloc(symtab_section, text_section, offset + 8, R_XXX_THUNKFIX, is->iat_index); // offset to IAT position #else - put_elf_reloc(symtab_section, text_section, + put_elf_reloc(symtab_section, text_section, offset + 2, R_XXX_THUNKFIX, is->iat_index); #endif is->thk_offset = offset; @@ -1636,7 +1636,7 @@ quit: /* ------------------------------------------------------------- */ #define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY -#include "../win32/tools/tiny_impdef.c" +#include "win32/tools/tiny_impdef.c" static int pe_load_dll(TCCState *s1, const char *dllname, int fd) { @@ -1841,13 +1841,13 @@ ST_FUNC int pe_output_file(TCCState * s1, const char *filename) pe.subsystem = s1->pe_subsystem; /* set default file/section alignment */ - if (pe.subsystem == 1) { - pe.section_align = 0x20; - pe.file_align = 0x20; - } else { - pe.section_align = 0x1000; - pe.file_align = 0x200; - } + if (pe.subsystem == 1) { + pe.section_align = 0x20; + pe.file_align = 0x20; + } else { + pe.section_align = 0x1000; + pe.file_align = 0x200; + } if (s1->section_align != 0) pe.section_align = s1->section_align; diff --git a/src/tccpp.c b/tccpp.c similarity index 99% rename from src/tccpp.c rename to tccpp.c index eed09b5..2936ef7 100644 --- a/src/tccpp.c +++ b/tccpp.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 @@ -50,7 +50,7 @@ static unsigned char isidnum_table[256 - CH_EOF]; static TokenString *macro_stack; -static const char tcc_keywords[] = +static const char tcc_keywords[] = #define DEF(id, str) str "\0" #include "tcctok.h" #undef DEF @@ -221,7 +221,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) TokenSym *ts, **ptable; int i; - if (tok_ident >= SYM_FIRST_ANOM) + if (tok_ident >= SYM_FIRST_ANOM) tcc_error("memory full (symbols)"); /* expand token table if needed */ @@ -255,7 +255,7 @@ ST_FUNC TokenSym *tok_alloc(const char *str, int len) TokenSym *ts, **pts; int i; unsigned int h; - + h = TOK_HASH_INIT; for(i=0;ibuf_ptr = p; next_nomacro(); p = file->buf_ptr; - if (a == 0 && + if (a == 0 && (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF)) goto the_end; if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF) @@ -786,7 +786,7 @@ redo_start: else if (tok == TOK_LINEFEED) goto redo_start; } else if (parse_flags & PARSE_FLAG_ASM_FILE) - p = parse_line_comment(p); + p = parse_line_comment(p); break; _default: default: @@ -930,7 +930,7 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) cstr->size = cv->cstr->size; cstr->data_allocated = NULL; cstr->size_allocated = cstr->size; - memcpy((char *)cstr + sizeof(CString), + memcpy((char *)cstr + sizeof(CString), cv->cstr->data, cstr->size); len += nb_words; } @@ -1253,14 +1253,14 @@ static int expr_preprocess(void) { int c, t; TokenString str; - + tok_str_new(&str); while (tok != TOK_LINEFEED && tok != TOK_EOF) { next(); /* do macro subst */ if (tok == TOK_DEFINED) { next_nomacro(); t = tok; - if (t == '(') + if (t == '(') next_nomacro(); c = define_find(tok) != 0; if (t == '(') @@ -1786,7 +1786,7 @@ _line_num: total_lines += file->line_num - n; file->line_num = n; if (s1->do_debug) - put_stabs(file->filename, N_BINCL, 0, 0, 0); + put_stabs(file->filename, N_BINCL, 0, 0, 0); break; case TOK_ERROR: case TOK_WARNING: @@ -1914,7 +1914,7 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long break; case '\'': case '\"': - case '\\': + case '\\': case '?': break; default: @@ -2070,7 +2070,7 @@ static void parse_number(const char *p) *q = '\0'; if (b == 16) shift = 4; - else + else shift = 1; bn_zero(bn); q = token_buf; @@ -2126,7 +2126,7 @@ static void parse_number(const char *p) 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]; @@ -2272,7 +2272,7 @@ static void parse_number(const char *p) if (n & 0xffffffff00000000LL || must_64bit) { tok = TOK_CLLONG; n1 = n >> 32; - } else { + } else { tok = TOK_CINT; n1 = n; } @@ -2363,7 +2363,7 @@ static inline void next_nomacro1(void) } else { tok_flags &= ~TOK_FLAG_EOF; /* pop include file */ - + /* test if previous '#endif' was after a #ifdef at start of file */ if (tok_flags & TOK_FLAG_ENDIF) { @@ -2400,7 +2400,7 @@ maybe_newline: case '#': /* XXX: simplify */ PEEKC(c, p); - if ((tok_flags & TOK_FLAG_BOL) && + if ((tok_flags & TOK_FLAG_BOL) && (parse_flags & PARSE_FLAG_PREPROCESS)) { file->buf_ptr = p; preprocess(tok_flags & TOK_FLAG_BOF); @@ -2420,7 +2420,7 @@ maybe_newline: } } break; - + /* dollar is allowed to start identifiers when not parsing asm */ case '$': if (!(isidnum_table[c - CH_EOF] & IS_ID) @@ -2433,14 +2433,14 @@ maybe_newline: case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': - case 'y': case 'z': + case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': - case 'I': case 'J': case 'K': + case 'I': case 'J': case 'K': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': - case 'Y': case 'Z': + case 'Y': case 'Z': case '_': parse_ident_fast: p1 = p; @@ -2538,7 +2538,7 @@ maybe_newline: } else if (c == '.') { PEEKC(c, p); if (c != '.') - expect("'.'"); + expect("'.'"); PEEKC(c, p); tok = TOK_DOTS; } else { @@ -2594,7 +2594,7 @@ maybe_newline: tok = TOK_GT; } break; - + case '&': PEEKC(c, p); if (c == '&') { @@ -2607,7 +2607,7 @@ maybe_newline: tok = '&'; } break; - + case '|': PEEKC(c, p); if (c == '|') { @@ -2633,7 +2633,7 @@ maybe_newline: tok = '+'; } break; - + case '-': PEEKC(c, p); if (c == '-') { @@ -2655,7 +2655,7 @@ maybe_newline: PARSE2('*', '*', '=', TOK_A_MUL) PARSE2('%', '%', '=', TOK_A_MOD) PARSE2('^', '^', '=', TOK_A_XOR) - + /* comments or operator */ case '/': PEEKC(c, p); @@ -2675,7 +2675,7 @@ maybe_newline: tok = '/'; } break; - + /* simple tokens */ case '(': case ')': @@ -2730,7 +2730,7 @@ ST_FUNC void next_nomacro(void) next_nomacro_spc(); } while (tok < 256 && (isidnum_table[tok - CH_EOF] & IS_SPC)); } - + static void macro_subst( TokenString *tok_str, @@ -2924,7 +2924,7 @@ static int macro_subst_tok( CValue cval; CString cstr; char buf[32]; - + /* if symbol is a macro, prepare substitution */ /* special macros */ if (tok == TOK___LINE__) { @@ -2942,10 +2942,10 @@ static int macro_subst_tok( time(&ti); tm = localtime(&ti); if (tok == TOK___DATE__) { - snprintf(buf, sizeof(buf), "%s %2d %d", + snprintf(buf, sizeof(buf), "%s %2d %d", ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900); } else { - snprintf(buf, sizeof(buf), "%02d:%02d:%02d", + snprintf(buf, sizeof(buf), "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); } cstrval = buf; @@ -3010,8 +3010,8 @@ static int macro_subst_tok( tok_str_new(&str); parlevel = spc = 0; /* NOTE: non zero sa->t indicates VA_ARGS */ - while ((parlevel > 0 || - (tok != ')' && + while ((parlevel > 0 || + (tok != ')' && (tok != ',' || sa->type.t)))) { if (tok == TOK_EOF || tok == 0) break; @@ -3143,7 +3143,7 @@ static inline int *macro_twosharps(const int *ptr0) /* given 'a##b', remove nosubsts preceding 'b' */ while ((t1 = *++ptr) == TOK_NOSUBST) ; - if (t1 && t1 != TOK_TWOSHARPS + if (t1 && t1 != TOK_TWOSHARPS && t1 != ':') /* 'a##:' don't build a new token */ { TOK_GET(&t1, &ptr, &cv1); @@ -3181,7 +3181,7 @@ static void macro_subst( int t, spc, nosubst; CValue cval; int *macro_str1 = NULL; - + /* first scan for '##' operator handling */ ptr = macro_str; spc = nosubst = 0; @@ -3334,7 +3334,7 @@ ST_FUNC void preprocess_new(void) : 0; memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *)); - + tok_ident = TOK_IDENT; p = tcc_keywords; while (*p) { diff --git a/src/tccrun.c b/tccrun.c similarity index 98% rename from src/tccrun.c rename to tccrun.c index cb98392..55db310 100644 --- a/src/tccrun.c +++ b/tccrun.c @@ -127,7 +127,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) for (i=0; iEbp; #endif if (level > 0) { - for(i = 1; i < level; i++) { - /* XXX: check address validity with program info */ - if (fp <= 0x1000 || fp >= 0xc0000000) - return -1; - fp = ((addr_t*)fp)[0]; - } + for(i=1;i= 0xc0000000) + return -1; + fp = ((addr_t*)fp)[0]; + } pc = ((addr_t*)fp)[1]; } *paddr = pc; diff --git a/src/tcctok.h b/tcctok.h similarity index 99% rename from src/tcctok.h rename to tcctok.h index 5972fd6..3de3ae2 100644 --- a/src/tcctok.h +++ b/tcctok.h @@ -36,7 +36,7 @@ DEF(TOK_RESTRICT2, "__restrict") DEF(TOK_RESTRICT3, "__restrict__") DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */ - + DEF(TOK_FLOAT, "float") DEF(TOK_DOUBLE, "double") DEF(TOK_BOOL, "_Bool") @@ -331,5 +331,5 @@ #endif #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 -#include "x86/i386-tok.h" +#include "i386-tok.h" #endif diff --git a/tests/Makefile b/tests/Makefile index f83027f..270eaa7 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -2,7 +2,7 @@ # Tiny C Compiler Makefile - tests # -TOP = ../src +TOP = .. include $(TOP)/Makefile SRCDIR = $(top_srcdir)/tests VPATH = $(SRCDIR) $(top_srcdir) @@ -60,11 +60,11 @@ ifeq ($(TARGETOS),Darwin) endif # run local version of tcc with local libraries and includes -TCCFLAGS = -B$(TOP)/../lib -I$(TOP) -I$(top_srcdir) -I$(top_srcdir)/../include -L$(TOP) +TCCFLAGS = -B$(TOP) -I$(TOP) -I$(top_srcdir) -I$(top_srcdir)/include -L$(TOP) ifdef CONFIG_WIN32 - TCCFLAGS = -B$(top_srcdir)/win32 -I$(top_srcdir) -I$(top_srcdir)/../include -L$(TOP) + TCCFLAGS = -B$(top_srcdir)/win32 -I$(top_srcdir) -I$(top_srcdir)/include -L$(TOP) endif -XTCCFLAGS = -B$(TOP)/../lib -B$(top_srcdir)/win32 -I$(TOP) -I$(top_srcdir) -I$(top_srcdir)/../include +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) @@ -73,7 +73,7 @@ DISAS = objdump -d # libtcc test ifdef LIBTCC1 - LIBTCC1:=$(TOP)/lib/$(LIBTCC1) + LIBTCC1:=$(TOP)/$(LIBTCC1) endif all test : $(TESTS) diff --git a/tests/abitest.c b/tests/abitest.c index e6e0384..23ba11c 100644 --- a/tests/abitest.c +++ b/tests/abitest.c @@ -41,7 +41,7 @@ static int run_callback(const char *src, callback_type callback) { TCCState *s; int result; void *ptr; - + s = tcc_new(); if (!s) return -1; @@ -54,14 +54,14 @@ static int run_callback(const char *src, callback_type callback) { return -1; if (tcc_relocate(s, TCC_RELOCATE_AUTO) == -1) return -1; - + ptr = tcc_get_symbol(s, "f"); if (!ptr) return -1; result = callback(ptr); - + tcc_delete(s); - + return result; } @@ -89,7 +89,7 @@ RET_PRIMITIVE_TEST(longdouble, LONG_DOUBLE, LONG_DOUBLE_LITERAL(378943892.0)) /* * ret_2float_test: - * + * * On x86-64, a struct with 2 floats should be packed into a single * SSE register (VT_DOUBLE is used for this purpose). */ @@ -117,7 +117,7 @@ static int ret_2float_test(void) { /* * ret_2double_test: - * + * * On x86-64, a struct with 2 doubles should be passed in two SSE * registers. */ @@ -281,7 +281,7 @@ static int reg_pack_test(void) { " reg_pack_test_type r = {a.x*5, a.y*3};\n" " return r;\n" "}\n"; - + return run_callback(src, reg_pack_test_callback); } @@ -307,7 +307,7 @@ static int reg_pack_longlong_test(void) { " reg_pack_longlong_test_type r = {a.x*5, a.y*3};\n" " return r;\n" "}\n"; - + return run_callback(src, reg_pack_longlong_test_callback); } @@ -365,13 +365,13 @@ static int sret_test(void) { " sret_test_type r = {x.a*35, x.b*19, x.c*21};\n" " return r;\n" "}\n"; - + return run_callback(src, sret_test_callback); } /* * one_member_union_test: - * + * * In the x86-64 ABI a union should always be passed on the stack. However * it appears that a single member union is treated by GCC as its member. */ @@ -399,7 +399,7 @@ static int one_member_union_test(void) { /* * two_member_union_test: - * + * * In the x86-64 ABI a union should always be passed on the stack. */ typedef union two_member_union_test_type_u {int x; long y;} two_member_union_test_type; @@ -430,7 +430,7 @@ static int two_member_union_test(void) { typedef struct many_struct_test_type_s {long long a, b, c;} many_struct_test_type; typedef many_struct_test_type (*many_struct_test_function_type) (many_struct_test_type,many_struct_test_type,many_struct_test_type,many_struct_test_type,many_struct_test_type,many_struct_test_type); - + static int many_struct_test_callback(void *ptr) { many_struct_test_function_type f = (many_struct_test_function_type)ptr; many_struct_test_type v = {1, 2, 3}; @@ -457,7 +457,7 @@ static int many_struct_test(void) { typedef struct many_struct_test_2_type_s {int a, b;} many_struct_test_2_type; typedef many_struct_test_2_type (*many_struct_test_2_function_type) (many_struct_test_2_type,many_struct_test_2_type,many_struct_test_2_type,many_struct_test_2_type,many_struct_test_2_type,many_struct_test_2_type); - + static int many_struct_test_2_callback(void *ptr) { many_struct_test_2_function_type f = (many_struct_test_2_function_type)ptr; many_struct_test_2_type v = {1,2}; @@ -598,7 +598,7 @@ static int arg_align_test_callback(void *ptr) { } static int arg_align_test(void) { - const char *src = + const char *src = "long double f(long double a, int b, long double c, int d, long double e) {\n" " return a + c + e;\n" "}\n"; @@ -621,7 +621,7 @@ int main(int argc, char **argv) { int i; const char *testname = NULL; int retval = EXIT_SUCCESS; - + /* if tcclib.h and libtcc1.a are not installed, where can we find them */ for (i = 1; i < argc; ++i) { if (!memcmp(argv[i], "run_test=", 9)) diff --git a/tests/pp/Makefile b/tests/pp/Makefile index 8bbf1a7..c656f9a 100644 --- a/tests/pp/Makefile +++ b/tests/pp/Makefile @@ -2,7 +2,7 @@ # credits: 01..13.c from the pcc cpp-tests suite # -TCC = ../../src/tcc +TCC = ../../tcc TESTS = $(patsubst %.c,%.test,$(wildcard *.c)) all test : $(TESTS) diff --git a/tests/tcctest.c b/tests/tcctest.c index 2570b6a..a822500 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -320,7 +320,7 @@ void macro_test(void) #line 200 printf("__LINE__=%d __FILE__=%s\n", __LINE__, __FILE__); -#line 203 "test" +#line 203 "test" printf("__LINE__=%d __FILE__=%s\n", __LINE__, __FILE__); #line 227 "tcctest.c" @@ -348,7 +348,7 @@ void macro_test(void) glue(a <, <= 2); printf("a=%d\n", a); } - + /* macro function with argument outside the macro string */ #define MF_s MF_hello #define MF_hello(msg) printf("%s\n",msg) @@ -357,7 +357,7 @@ void macro_test(void) MF_s("hi"); MF_t("hi"); - + /* test macro substituion inside args (should not eat stream) */ printf("qq=%d\n", qq(qq)(2)); @@ -398,7 +398,7 @@ void recursive_macro_test(void) printf("%d\n", ELFW(ST_INFO)(STB_WEAK, ELFW(ST_TYPE)(123))); #define WRAP(x) x - + #define print_num(x) print_num(__FILE__,__LINE__,x) print_num(123); WRAP(print_num(123)); @@ -537,7 +537,7 @@ void goto_test() /* This needs to parse as label, not as start of decl. */ typedef_and_label: s_loop: - if (i >= 10) + if (i >= 10) goto s_end; printf("%d", i); i++; @@ -688,7 +688,7 @@ int main(int argc, char **argv) callsave_test(); builtin_frame_address_test(); intdiv_test(); - return 0; + return 0; } int tab[3]; @@ -797,10 +797,10 @@ void expr_test() printf("%d\n", ~12); printf("%d\n", -12); printf("%d\n", +12); - printf("%d %d %d %d\n", - isid('a'), - isid('g'), - isid('T'), + printf("%d %d %d %d\n", + isid('a'), + isid('g'), + isid('T'), isid('(')); } @@ -984,7 +984,7 @@ void struct_test() sizeof(struct aligntest3), __alignof__(struct aligntest3)); printf("aligntest4 sizeof=%d alignof=%d\n", sizeof(struct aligntest4), __alignof__(struct aligntest4)); - + /* empty structures (GCC extension) */ printf("sizeof(struct empty) = %d\n", sizeof(struct empty)); printf("alignof(struct empty) = %d\n", __alignof__(struct empty)); @@ -999,17 +999,17 @@ void char_short_test() var1 = 0x01020304; var2 = 0xfffefdfc; - printf("s8=%d %d\n", + printf("s8=%d %d\n", *(char *)&var1, *(char *)&var2); - printf("u8=%d %d\n", + printf("u8=%d %d\n", *(unsigned char *)&var1, *(unsigned char *)&var2); - printf("s16=%d %d\n", + printf("s16=%d %d\n", *(short *)&var1, *(short *)&var2); - printf("u16=%d %d\n", + printf("u16=%d %d\n", *(unsigned short *)&var1, *(unsigned short *)&var2); - printf("s32=%d %d\n", + printf("s32=%d %d\n", *(int *)&var1, *(int *)&var2); - printf("u32=%d %d\n", + printf("u32=%d %d\n", *(unsigned int *)&var1, *(unsigned int *)&var2); *(char *)&var1 = 0x08; printf("var1=%x\n", var1); @@ -1099,7 +1099,7 @@ void bool_test() static int v1 = 34 ? : -1; /* constant case */ static int v2 = 0 ? : -1; /* constant case */ int a = 30; - + printf("%d %d\n", v1, v2); printf("%d %d\n", a - 30 ? : a * 2, a + 1 ? : a * 2); } @@ -1116,8 +1116,8 @@ static int tab_reinit[]; static int tab_reinit[10]; //int cinit1; /* a global variable can be defined several times without error ! */ -int cinit1; -int cinit1; +int cinit1; +int cinit1; int cinit1 = 0; int *cinit2 = (int []){3, 2, 1}; @@ -1157,7 +1157,7 @@ void compound_literal_test(void) for(i=0;i<3;i++) { p = (int []){1, 2, 4 + i}; - printf("%d %d %d\n", + printf("%d %d %d\n", p[0], p[1], p[2]); @@ -1188,7 +1188,7 @@ kr_test() void num(int n) { char *tab, *p; - tab = (char*)malloc(20); + tab = (char*)malloc(20); p = tab; while (1) { *p = 48 + (n % 10); @@ -1231,7 +1231,7 @@ void struct_assign_test(void) struct structa1 lsta1, lsta2; int i; } s, *ps; - + ps = &s; ps->i = 4; #if 0 @@ -1247,7 +1247,7 @@ void struct_assign_test(void) s.lsta2.f2 = 2; #endif struct_assign_test1(ps->lsta2, 3, 4.5); - + printf("before call: %d %d\n", s.lsta2.f1, s.lsta2.f2); ps->lsta2 = struct_assign_test2(ps->lsta2, ps->i); printf("after call: %d %d\n", ps->lsta2.f1, ps->lsta2.f2); @@ -1300,9 +1300,9 @@ void cast_test() printf("%d\n", a); a = (scast = 65536) + 1; printf("%d\n", a); - + printf("sizeof(c) = %d, sizeof((int)c) = %d\n", sizeof(c), sizeof((int)c)); - + /* test cast from unsigned to signed short to int */ b = 0xf000; d = (short)b; @@ -1310,7 +1310,7 @@ void cast_test() b = 0xf0f0; d = (char)b; printf("((unsigned)(char)0x%08x) = 0x%08x\n", b, d); - + /* test implicit int casting for array accesses */ c = 0; tab[1] = 2; @@ -1352,7 +1352,7 @@ char sinit8[] = "hello" "trala"; struct structinit1 sinit9 = { 1, 2, 3 }; struct structinit1 sinit10 = { .f2 = 2, 3, .f1 = 1 }; -struct structinit1 sinit11 = { .f2 = 2, 3, .f1 = 1, +struct structinit1 sinit11 = { .f2 = 2, 3, .f1 = 1, #ifdef ALL_ISOC99 .farray[0] = 10, .farray[1] = 11, @@ -1437,36 +1437,36 @@ void init_test(void) int linit15[10] = { linit1, linit1 + 1, [6] = linit1 + 2, }; struct linit16 { int a1, a2, a3, a4; } linit16 = { 1, .a3 = 2 }; int linit17 = sizeof(linit17); - + printf("init_test:\n"); printf("sinit1=%d\n", sinit1); printf("sinit2=%d\n", sinit2); - printf("sinit3=%d %d %d %d\n", + printf("sinit3=%d %d %d %d\n", sizeof(sinit3), sinit3[0], sinit3[1], sinit3[2] ); printf("sinit6=%d\n", sizeof(sinit6)); - printf("sinit7=%d %d %d %d\n", + printf("sinit7=%d %d %d %d\n", sizeof(sinit7), sinit7[0], sinit7[1], sinit7[2] ); printf("sinit8=%s\n", sinit8); - printf("sinit9=%d %d %d\n", + printf("sinit9=%d %d %d\n", sinit9.f1, sinit9.f2, sinit9.f3 ); - printf("sinit10=%d %d %d\n", + printf("sinit10=%d %d %d\n", sinit10.f1, sinit10.f2, sinit10.f3 ); - printf("sinit11=%d %d %d %d %d %d\n", + printf("sinit11=%d %d %d %d %d %d\n", sinit11.f1, sinit11.f2, sinit11.f3, @@ -1477,7 +1477,7 @@ void init_test(void) for(i=0;i<3;i++) for(j=0;j<2;j++) - printf("[%d][%d] = %d %d %d\n", + printf("[%d][%d] = %d %d %d\n", i, j, sinit4[i][j], sinit5[i][j], linit4[i][j]); printf("linit1=%d\n", linit1); printf("linit2=%d\n", linit2); @@ -1486,7 +1486,7 @@ void init_test(void) printf("sinit12=%s\n", sinit12); printf("sinit13=%d %s %s %s\n", - sizeof(sinit13), + sizeof(sinit13), sinit13[0], sinit13[1], sinit13[2]); @@ -1500,7 +1500,7 @@ void init_test(void) printf("\n"); for(i=0;i<10;i++) printf(" %d", linit15[i]); printf("\n"); - printf("%d %d %d %d\n", + printf("%d %d %d %d\n", linit16.a1, linit16.a2, linit16.a3, @@ -1599,13 +1599,13 @@ void bitfield_test(void) printf("%d %d\n", sa, ca); st1.f1 = 7; - if (st1.f1 == -1) + if (st1.f1 == -1) printf("st1.f1 == -1\n"); - else + else printf("st1.f1 != -1\n"); - if (st1.f2 == -1) + if (st1.f2 == -1) printf("st1.f2 == -1\n"); - else + else printf("st1.f2 != -1\n"); /* bit sizes below must be bigger than 32 since GCC doesn't allow @@ -1835,7 +1835,7 @@ void lloptest(long long a, long long b) a + b, a - b, a * b); - + if (b != 0) { printf("arith1: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", a / b, @@ -1856,7 +1856,7 @@ void lloptest(long long a, long long b) a > b, a >= b, a <= b); - + printf("utest: %d %d %d %d %d %d\n", ua == ub, ua != ub, @@ -1932,7 +1932,7 @@ long long llfunc1(int a) } struct S { - int id; + int id; char item; }; @@ -1953,8 +1953,8 @@ void longlong_test(void) a = ia; b = ua; printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", a, b); - printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %Lx\n", - (long long)1, + printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %Lx\n", + (long long)1, (long long)-2, 1LL, 0x1234567812345679); @@ -2049,7 +2049,7 @@ void vprintf1(const char *fmt, ...) va_start(aq, fmt); va_copy(ap, aq); - + p = fmt; for(;;) { c = *p; @@ -2250,10 +2250,10 @@ void c99_vla_test(int size1, int size2) int tab1[size][2], tab2[10][2]; void *tab1_ptr, *tab2_ptr, *bad_ptr; - /* "size" should have been 'captured' at tab1 declaration, + /* "size" should have been 'captured' at tab1 declaration, so modifying it should have no effect on VLA behaviour. */ size = size-1; - + printf("Test C99 VLA 1 (sizeof): "); printf("%s\n", (sizeof tab1 == size1 * size2 * 2 * sizeof(int)) ? "PASSED" : "FAILED"); tab1_ptr = tab1; @@ -2325,7 +2325,7 @@ void sizeof_test(void) t <<= 16; t <<= 16; t++; - /* This checks that sizeof really can be used to manipulate + /* This checks that sizeof really can be used to manipulate uintptr_t objects, without truncation. */ t2 = t & -sizeof(uintptr_t); printf ("%lu %lu\n", t, t2); @@ -2358,15 +2358,15 @@ void statement_expr_test(void) a = 0; for(i=0;i<10;i++) { - a += 1 + - ( { int b, j; - b = 0; - for(j=0;j<5;j++) - b += j; b; + a += 1 + + ( { int b, j; + b = 0; + for(j=0;j<5;j++) + b += j; b; } ); } printf("a=%d\n", a); - + } void local_label_test(void) @@ -2589,7 +2589,7 @@ void builtin_test(void) COMPAT_TYPE(char *, signed char *); COMPAT_TYPE(char *, char *); /* space is needed because tcc preprocessor introduces a space between each token */ - COMPAT_TYPE(char * *, void *); + COMPAT_TYPE(char * *, void *); #endif printf("res = %d\n", __builtin_constant_p(1)); printf("res = %d\n", __builtin_constant_p(1 + 2)); @@ -2640,7 +2640,7 @@ void __attribute__((weak)) weak_test(void) printf("weak_fpa=%d\n",&weak_fpa ? weak_fpa() : 123); printf("weak_fpb=%d\n",&weak_fpb ? weak_fpb() : 123); printf("weak_fpc=%d\n",&weak_fpc ? weak_fpc() : 123); - + printf("weak_asm_f1=%d\n", weak_asm_f1 != NULL); printf("weak_asm_f2=%d\n", weak_asm_f2 != NULL); printf("weak_asm_f3=%d\n", weak_asm_f3 != NULL); diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 980934b..254fa5c 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -1,4 +1,4 @@ -TOP = ../../src +TOP = ../.. include $(TOP)/Makefile # clear CFLAGS and LDFLAGS @@ -6,9 +6,9 @@ CFLAGS := LDFLAGS := ifdef CONFIG_WIN32 - TCCFLAGS = -B$(top_srcdir)/win32 -I$(top_srcdir)/../include -L$(TOP) + TCCFLAGS = -B$(top_srcdir)/win32 -I$(top_srcdir)/include -L$(TOP) else - TCCFLAGS = -B$(TOP)/../lib -I$(top_srcdir)/../include -lm + TCCFLAGS = -B$(TOP) -I$(top_srcdir)/include -lm endif ifeq ($(TARGETOS),Darwin) diff --git a/docs/texi2pod.pl b/texi2pod.pl old mode 100644 new mode 100755 similarity index 99% rename from docs/texi2pod.pl rename to texi2pod.pl index a8f823f..d86e176 --- a/docs/texi2pod.pl +++ b/texi2pod.pl @@ -229,7 +229,7 @@ while(<$inf>) { $inf = gensym(); # Try cwd and $ibase. - open($inf, "<" . $1) + open($inf, "<" . $1) or open($inf, "<" . $ibase . "/" . $1) or die "cannot open $1 or $ibase/$1: $!\n"; next; diff --git a/win32/tools/tiny_libmaker.c b/win32/tools/tiny_libmaker.c index 62fec98..62d2a2e 100644 --- a/win32/tools/tiny_libmaker.c +++ b/win32/tools/tiny_libmaker.c @@ -21,7 +21,7 @@ #include #include #include -#include "../../src/elf.h" +#include "../../elf.h" #ifdef TCC_TARGET_X86_64 # define ELFCLASSW ELFCLASS64 diff --git a/src/x86/x86_64-asm.h b/x86_64-asm.h similarity index 100% rename from src/x86/x86_64-asm.h rename to x86_64-asm.h diff --git a/src/x86/x86_64-gen.c b/x86_64-gen.c similarity index 97% rename from src/x86/x86_64-gen.c rename to x86_64-gen.c index ab2eb6a..5589877 100644 --- a/src/x86/x86_64-gen.c +++ b/x86_64-gen.c @@ -136,7 +136,7 @@ enum { /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ -#include "../tcc.h" +#include "tcc.h" #include ST_DATA const int reg_classes[NB_REGS] = { @@ -477,17 +477,18 @@ void load(int r, SValue *sv) gen_modrm(r, VT_LOCAL, sv->sym, fc); } else if (v == VT_CMP) { orex(0,r,0,0); - if ((fc & ~0x100) != TOK_NE) - oad(0xb8 + REG_VALUE(r), 0); /* mov $0, r */ - else - oad(0xb8 + REG_VALUE(r), 1); /* mov $1, r */ - if (fc & 0x100) { - /* This was a float compare. If the parity bit is - * set the result was unordered, meaning false for everything - * except TOK_NE, and true for TOK_NE. */ - fc &= ~0x100; - o(0x037a + (REX_BASE(r) << 8)); - } + if ((fc & ~0x100) != TOK_NE) + oad(0xb8 + REG_VALUE(r), 0); /* mov $0, r */ + else + oad(0xb8 + REG_VALUE(r), 1); /* mov $1, r */ + if (fc & 0x100) + { + /* This was a float compare. If the parity bit is + set the result was unordered, meaning false for everything + except TOK_NE, and true for TOK_NE. */ + fc &= ~0x100; + o(0x037a + (REX_BASE(r) << 8)); + } orex(0,r,0, 0x0f); /* setxx %br */ o(fc); o(0xc0 + REG_VALUE(r)); @@ -618,7 +619,7 @@ static void gcall_or_jmp(int is_jmp) { int r; if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && - ((vtop->r & VT_SYM) || (vtop->c.ll-4) == (int)(vtop->c.ll-4))) { + ((vtop->r & VT_SYM) || (vtop->c.ll-4) == (int)(vtop->c.ll-4))) { /* constant case */ if (vtop->r & VT_SYM) { /* relocation case */ @@ -680,7 +681,7 @@ ST_FUNC void gen_bounded_ptr_add(void) /* relocation offset of the bounding function call point */ - vtop->c.ull = (cur_text_section->reloc->data_offset - sizeof(ElfW(Rela))); + vtop->c.ull = (cur_text_section->reloc->data_offset - sizeof(ElfW(Rela))); } /* patch pointer addition in vtop so that pointer dereferencing is @@ -822,7 +823,7 @@ void gfunc_call(int nb_args) struct_size = args_size; for(i = 0; i < nb_args; i++) { SValue *sv; - + --arg; sv = &vtop[-i]; bt = (sv->type.t & VT_BTYPE); @@ -896,7 +897,7 @@ void gfunc_call(int nb_args) vtop->type.t = size > 4 ? VT_LLONG : size > 2 ? VT_INT : size > 1 ? VT_SHORT : VT_BYTE; } - + r = gv(RC_INT); if (arg >= REGN) { gen_offs_sp(0x89, r, arg*8); @@ -910,7 +911,7 @@ void gfunc_call(int nb_args) vtop--; } save_regs(0); - + /* Copy R10 and R11 into RCX and RDX, respectively */ if (nb_args > 0) { o(0xd1894c); /* mov %r10, %rcx */ @@ -918,7 +919,7 @@ void gfunc_call(int nb_args) o(0xda894c); /* mov %r11, %rdx */ } } - + gcall_or_jmp(0); vtop--; } @@ -1071,10 +1072,10 @@ static X86_64_Mode classify_x86_64_inner(CType *ty, int offset, int start, int e { X86_64_Mode mode; Sym *f; - + switch (ty->t & VT_BTYPE) { case VT_VOID: return x86_64_mode_none; - + case VT_INT: case VT_BYTE: case VT_SHORT: @@ -1083,12 +1084,12 @@ static X86_64_Mode classify_x86_64_inner(CType *ty, int offset, int start, int e case VT_PTR: case VT_FUNC: case VT_ENUM: return x86_64_mode_integer; - + case VT_FLOAT: case VT_DOUBLE: return x86_64_mode_sse; - + case VT_LDOUBLE: return x86_64_mode_x87; - + case VT_STRUCT: f = ty->ref; @@ -1097,10 +1098,10 @@ static X86_64_Mode classify_x86_64_inner(CType *ty, int offset, int start, int e if (f->c + offset >= start && f->c + offset < end) mode = classify_x86_64_merge(mode, classify_x86_64_inner(&f->type, f->c + offset, start, end)); } - + return mode; } - + assert(0); } @@ -1304,7 +1305,7 @@ void gfunc_call(int nb_args) args_size = 0; while (run_start != nb_args) { int run_gen_reg = gen_reg, run_sse_reg = sse_reg; - + run_end = nb_args; stack_adjust = 0; for(i = run_start; (i < nb_args) && (run_end == nb_args); i++) { @@ -1318,10 +1319,10 @@ void gfunc_call(int nb_args) stack_adjust += size; } } - + gen_reg = run_gen_reg; sse_reg = run_sse_reg; - + /* adjust stack to align SSE boundary */ if (stack_adjust &= 15) { /* fetch cpu flag before the following sub will change the value */ @@ -1333,7 +1334,7 @@ void gfunc_call(int nb_args) oad(0xec81, stack_adjust); /* sub $xxx, %rsp */ args_size += stack_adjust; } - + for(i = run_start; i < run_end;) { int arg_stored = regargs_nregs(®_args[i]) == 0; SValue tmp; @@ -1343,7 +1344,7 @@ void gfunc_call(int nb_args) ++i; continue; } - + /* Swap argument to top, it will possibly be changed here, and might use more temps. At the end of the loop we keep in on the stack and swap it back to its original position @@ -1351,7 +1352,7 @@ void gfunc_call(int nb_args) tmp = vtop[0]; vtop[0] = vtop[-i]; vtop[-i] = tmp; - + classify_x86_64_arg(&vtop->type, NULL, &size, &align, &args); switch (vtop->type.t & VT_BTYPE) { @@ -1368,11 +1369,11 @@ void gfunc_call(int nb_args) vstore(); args_size += size; break; - + case VT_LDOUBLE: assert(0); break; - + case VT_FLOAT: case VT_DOUBLE: r = gv(RC_FLOAT); @@ -1383,7 +1384,7 @@ void gfunc_call(int nb_args) o(0x24); args_size += size; break; - + default: /* simple type */ /* XXX: implicit cast ? */ @@ -1416,7 +1417,7 @@ void gfunc_call(int nb_args) break; vrotb(i+1); - + if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { gv(RC_ST0); oad(0xec8148, size); /* sub $xxx, %rsp */ @@ -1439,7 +1440,7 @@ void gfunc_call(int nb_args) vstore(); args_size += size; } - + vpop(); memmove(reg_args + i, reg_args + i + 1, (nb_args - i - 1) * sizeof *reg_args); --nb_args; @@ -1697,14 +1698,14 @@ void gfunc_prolog(CType *func_type) addr += size; } break; - + case x86_64_mode_memory: case x86_64_mode_x87: addr = (addr + align - 1) & -align; param_addr = addr; addr += size; break; - default: break; /* nothing to be done for x86_64_mode_none */ + default: break; /* nothing to be done for x86_64_mode_none */ } sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, param_addr); @@ -1716,8 +1717,8 @@ void gfunc_prolog(CType *func_type) func_bound_offset = lbounds_section->data_offset; func_bound_ind = ind; oad(0xb8, 0); /* lbound section pointer */ - o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */ - oad(0xb8, 0); /* call to function */ + o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */ + oad(0xb8, 0); /* call to function */ } #endif } @@ -1729,7 +1730,7 @@ void gfunc_epilog(void) #ifdef CONFIG_TCC_BCHECK if (tcc_state->do_bounds_check - && func_bound_offset != lbounds_section->data_offset) + && func_bound_offset != lbounds_section->data_offset) { addr_t saved_ind; addr_t *bounds_ptr; @@ -1753,7 +1754,7 @@ void gfunc_epilog(void) o(0x5250); /* save returned value, if any */ greloc(cur_text_section, sym_data, ind + 1, R_386_32); oad(0xb8, 0); /* mov xxx, %rax */ - o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */ + o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */ gen_static_call(TOK___bound_local_delete); o(0x585a); /* restore returned value, if any */ } @@ -1805,23 +1806,24 @@ int gtst(int inv, int t) v = vtop->r & VT_VALMASK; if (v == VT_CMP) { /* fast case : can jump directly since flags are set */ - if (vtop->c.i & 0x100) - { - /* This was a float compare. If the parity flag is set - the result was unordered. For anything except != this - means false and we don't jump (anding both conditions). - For != this means true (oring both). - Take care about inverting the test. We need to jump - to our target if the result was unordered and test wasn't NE, - otherwise if unordered we don't want to jump. */ - vtop->c.i &= ~0x100; - if (!inv == (vtop->c.i != TOK_NE)) - o(0x067a); /* jp +6 */ - else { - g(0x0f); - t = psym(0x8a, t); /* jp t */ - } - } + if (vtop->c.i & 0x100) + { + /* This was a float compare. If the parity flag is set + the result was unordered. For anything except != this + means false and we don't jump (anding both conditions). + For != this means true (oring both). + Take care about inverting the test. We need to jump + to our target if the result was unordered and test wasn't NE, + otherwise if unordered we don't want to jump. */ + vtop->c.i &= ~0x100; + if (!inv == (vtop->c.i != TOK_NE)) + o(0x067a); /* jp +6 */ + else + { + g(0x0f); + t = psym(0x8a, t); /* jp t */ + } + } g(0x0f); t = psym((vtop->c.i - 16) ^ inv, t); } else if (v == VT_JMP || v == VT_JMPI) { @@ -2102,7 +2104,7 @@ void gen_opf(int op) vswap(); } assert(!(vtop[-1].r & VT_LVAL)); - + if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) o(0x66); if (op == TOK_EQ || op == TOK_NE) @@ -2139,7 +2141,7 @@ void gen_opf(int op) ft = vtop->type.t; fc = vtop->c.ul; assert((ft & VT_BTYPE) != VT_LDOUBLE); - + r = vtop->r; /* if saved lvalue, then we must reload it */ if ((vtop->r & VT_VALMASK) == VT_LLOCAL) { @@ -2151,14 +2153,14 @@ void gen_opf(int op) load(r, &v1); fc = 0; } - + assert(!(vtop[-1].r & VT_LVAL)); if (swapped) { assert(vtop->r & VT_LVAL); gv(RC_FLOAT); vswap(); } - + if ((ft & VT_BTYPE) == VT_DOUBLE) { o(0xf2); } else { @@ -2166,7 +2168,7 @@ void gen_opf(int op) } o(0x0f); o(0x58 + a); - + if (vtop->r & VT_LVAL) { gen_modrm(vtop[-1].r, r, vtop->sym, fc); } else { @@ -2229,7 +2231,7 @@ void gen_cvt_ftof(int t) ft = vtop->type.t; bt = ft & VT_BTYPE; tbt = t & VT_BTYPE; - + if (bt == VT_FLOAT) { gv(RC_FLOAT); if (tbt == VT_DOUBLE) {