Changeset 331 for EcnlProtoTool/trunk/tcc-0.9.27
- Timestamp:
- Jan 21, 2018, 12:10:09 AM (6 years ago)
- Location:
- EcnlProtoTool/trunk/tcc-0.9.27
- Files:
-
- 250 added
- 1 deleted
- 57 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/tcc-0.9.27/.cproject
r279 r331 20 20 <builder buildPath="${workspace_loc:/tcc}/Debug" id="com.renesas.cdt.rz.library.project.debug.win32.builder.Id.1947549202" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.renesas.cdt.rz.library.project.debug.win32.builder.Id"/> 21 21 <tool id="com.renesas.cdt.rz.libraryProject.debug.win32.tool.compiler.Id.1351770923" name="Compiler" superClass="com.renesas.cdt.rz.libraryProject.debug.win32.tool.compiler.Id"> 22 <option defaultValue="true" id="com.renesas.cdt.core.Compiler.option.misc2.373654238" name="æ¨æºã·ã¹ãã ã»ãã£ã¬ã¯ããªã¼ã§ãããã¼ã»ãã¡ã¤ã«ãæ¤ç´¢ããªã (-nostdinc)" superClass="com.renesas.cdt.core.Compiler.option.misc2" value=" false" valueType="boolean"/>22 <option defaultValue="true" id="com.renesas.cdt.core.Compiler.option.misc2.373654238" name="æ¨æºã·ã¹ãã ã»ãã£ã¬ã¯ããªã¼ã§ãããã¼ã»ãã¡ã¤ã«ãæ¤ç´¢ããªã (-nostdinc)" superClass="com.renesas.cdt.core.Compiler.option.misc2" value="true" valueType="boolean"/> 23 23 <option id="com.renesas.cdt.rz.Debug.Compiler.option.library.dataEndian.1091726519" name="ã¨ã³ãã£ã¢ã³" superClass="com.renesas.cdt.rz.Debug.Compiler.option.library.dataEndian" value="Little-endian" valueType="enumerated"/> 24 24 <option id="com.renesas.cdt.rz.Debug.Compiler.option.library.instructionset.1331241682" name="å½ä»¤ã»ãã" superClass="com.renesas.cdt.rz.Debug.Compiler.option.library.instructionset" value="ARM" valueType="enumerated"/> … … 30 30 <option id="com.renesas.cdt.rz.Debug.Compiler.option.library.architecture.401098680" name="ã¢ã¼ããã¯ãã£ã¼" superClass="com.renesas.cdt.rz.Debug.Compiler.option.library.architecture" value="armv7-a" valueType="enumerated"/> 31 31 <option id="com.renesas.cdt.rz.Debug.Compiler.option.library.cpuType.1123397289" name="CPU ã¿ã¤ã" superClass="com.renesas.cdt.rz.Debug.Compiler.option.library.cpuType" value="cortex-a9" valueType="enumerated"/> 32 <option id="com.renesas.cdt.core.Compiler.option.stackSizeInDecimal.1138208172" name="Decimal representation of '-Ws atck-usage'" superClass="com.renesas.cdt.core.Compiler.option.stackSizeInDecimal" value="256" valueType="string"/>32 <option id="com.renesas.cdt.core.Compiler.option.stackSizeInDecimal.1138208172" name="Decimal representation of '-Wstack-usage'" superClass="com.renesas.cdt.core.Compiler.option.stackSizeInDecimal" value="256" valueType="string"/> 33 33 <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.renesas.cdt.core.Compiler.option.includeFileDir.276254572" name="ã¤ã³ã¯ã«ã¼ãã»ãã¡ã¤ã«ã»ãã£ã¬ã¯ããªã¼" superClass="com.renesas.cdt.core.Compiler.option.includeFileDir" valueType="includePath"> 34 34 <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}}""/> 35 <listOptionValue builtIn="false" value=""${workspace_loc:/musl-1.1.18/include}""/> 35 36 </option> 36 37 <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.renesas.cdt.rz.Debug.Compiler.option.library.macroDefines.1180675084" name="ãã¯ãå®ç¾©" superClass="com.renesas.cdt.rz.Debug.Compiler.option.library.macroDefines" valueType="definedSymbols"> 38 <listOptionValue builtIn="false" value="TCC_CPU_VERSION=7"/> 39 <listOptionValue builtIn="false" value="TCC_MUSL"/> 37 40 <listOptionValue builtIn="false" value="TCC_TARGET_ARM"/> 38 <listOptionValue builtIn="false" value="WITHOUT_LIBTCC"/> 41 <listOptionValue builtIn="false" value="TCC_ARM_EABI"/> 42 <listOptionValue builtIn="false" value="TCC_ARM_VFP"/> 43 <listOptionValue builtIn="false" value="TCC_ARM_HARDFLOAT"/> 44 <listOptionValue builtIn="false" value="ONE_SOURCE=0"/> 45 <listOptionValue builtIn="false" value="CONFIG_TCC_STATIC"/> 39 46 </option> 40 47 <inputType id="%Base.Compiler.C.InputType.Id.1716911779" name="C å … … 57 64 </folderInfo> 58 65 <sourceEntries> 59 <entry excluding=" tests|lib|examples|tccpe.c|tcccoff.c|x86_64-gen.c|x86_64-asm.h|il-opcodes.h|il-gen.c|i386-tok.h|i386-gen.c|i386-asm.h|i386-asm.c|c67-gen.c" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>66 <entry excluding="lib/armeabi.c|lib/alloca-arm.S|tcctools.c|lib/va_list.c|lib/libtcc1.c|lib/lib-arm64.c|lib/bcheck.c|lib/alloca86-bt.S|lib/alloca86.S|lib/alloca86_64-bt.S|lib/alloca86_64.S|i386-link.c|conftest.c|c67-link.c|win32|x86_64-link.c|arm64-link.c|arm64-gen.c|tests|examples|tccpe.c|tcccoff.c|x86_64-gen.c|x86_64-asm.h|il-opcodes.h|il-gen.c|i386-tok.h|i386-gen.c|i386-asm.h|i386-asm.c|c67-gen.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> 60 67 </sourceEntries> 61 68 </configuration> … … 71 78 </storageModule> 72 79 <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/> 80 <storageModule moduleId="refreshScope" versionNumber="2"> 81 <configuration configurationName="Debug"> 82 <resource resourceType="PROJECT" workspacePath="/tcc-0.9.27"/> 83 </configuration> 84 </storageModule> 73 85 </cproject> -
EcnlProtoTool/trunk/tcc-0.9.27/.gitignore
r279 r331 1 *~ 2 \#* 3 .#* 1 4 *.o 2 5 *.a 6 *.exe 7 *.dll 8 *.obj 9 *.pdb 10 *.lib 11 *.exp 12 *.log 13 *.bz2 14 *.zip 15 .gdb_history 16 a.out 3 17 tcc_g 4 18 tcc 5 /*-tcc 6 tc2.c 7 doc 8 tc3s.c 9 p3.c 10 tc1.c 11 error.c 12 i386-gen1.c 13 test.out1 14 test.out1b 15 test.out2 16 test.out2b 17 test.out3 18 test.out3b 19 web.sh 20 memdebug.c 21 bench 22 Makefile.uClibc 23 boundtest 24 prog.ref 25 test.ref 26 test.out 27 tcc-doc.html 28 ideas 29 tcctest.ref 30 linux.tcc 31 ldtest 32 libtcc_test 33 instr.S 34 p.c 35 p2.c 36 tcctest[1234] 37 test[1234].out 38 tests/tcclib.h 39 tests/tcctest.gcc 40 tests/weaktest.*.o.txt 41 tests2/fred.txt 42 .gdb_history 19 *-tcc 20 libtcc*.def 21 22 config*.h 23 config*.mak 24 config.texi 25 conftest* 26 tags 27 TAGS 43 28 tcc.1 44 29 tcc.pod 45 config.h 46 config.mak 47 config.texi 48 tags 49 .DS_Store 50 *.swp 51 lib/x86_64 52 lib/i386 53 lib/x86_64-win32 54 lib/i386-win32 30 tcc-doc.html 55 31 tcc-doc.info 56 conftest* 57 tiny_libmaker 58 *.dSYM 32 33 win32/doc 34 win32/libtcc 35 win32/lib/32 36 win32/lib/64 37 win32/include/float.h 38 win32/include/stdarg.h 39 win32/include/stdbool.h 40 win32/include/stddef.h 41 win32/include/varargs.h 42 win32/include/tcclib.h 43 44 tests/tcctest[1234] 45 tests/tcctest.gcc 46 tests/*.out* 47 tests/*.ref 48 tests/*.txt 49 tests/*.gcc 50 tests/*-cc* 51 tests/*-tcc* 52 tests/libtcc_test 53 tests/asm-c-connect 54 tests/asm-c-connect-sep 55 tests/vla_test 56 tests/hello 57 tests/tests2/fred.txt -
EcnlProtoTool/trunk/tcc-0.9.27/.info
r279 r331 4 4 GCC_STRING=5.2-GNUARM-NONE_v16.01 5 5 VERSION_IDE= 6 E2STUDIO_VERSION=5. 3.1.0026 E2STUDIO_VERSION=5.4.0.018 7 7 ACTIVE_CONFIGURATION=Debug -
EcnlProtoTool/trunk/tcc-0.9.27/.project
r279 r331 1 1 <?xml version="1.0" encoding="UTF-8"?> 2 2 <projectDescription> 3 <name>tcc-0.9.2 6</name>3 <name>tcc-0.9.27</name> 4 4 <comment></comment> 5 5 <projects> -
EcnlProtoTool/trunk/tcc-0.9.27/Changelog
r279 r331 1 Version 0.9.27: 2 3 User interface: 4 - -x[c|a|n] filetype option (Sergey Korshunoff) 5 - -P[1], -dD, -dM preprocessor options (Sergey Korshunoff) 6 - -Wl,-(no-)whole-archive linker option (Reuben Thomas) 7 - -mms-bitfields option (David Mertens) 8 - -include <file> option (Michael Matz) 9 - -mno-sse on x86-64 disables use of SSE instructions 10 - @listfile support (Vlad Vissoultchev) 11 - tcc -ar/-impdef - formerly tiny_xxx tools integrated (grischka) 12 - CPATH, C_INCLUDE_PATH and LIBRARY_PATH environment variables support 13 (Andrew Aladjev, Urs Janssen) 14 15 Platforms: 16 - new AARCH64 (arm64) target (Edmund Grimley Evans) 17 - vastly improved support for ARM hard float calling convention 18 (Thomas Preud'homme, Daniel Gl旦ckner) 19 - provide a runtime library for ARM (Thomas Preud'homme) 20 - many x86_64 ABI fixes incl. XMM register passing and tests (James Lyon) 21 - ABI tests with native compiler using libtcc (James Lyon) 22 - UNICODE startup code supports wmain and wWinMain (YX Hao) 23 - shared libraries for x86_64 (Michael Matz) 24 - Bootstrap native Windows 32/64 compiler using Cygwin+gcc (Christian Jullien) 25 26 Features: 27 - VLA (variable length array) improved (James Lyon, Pip Cet) 28 - import functions by ordinal in .def files on windows (YX Hao) 29 - x86/x86_64 assembler much improved (Michael Matz) 30 - simple dead code suppression (Edmund Grimley Evans, Michael Matz, grischka) 31 - implement round/fmin/fmax etc. math on windows (Avi Halachmi) 32 - #pragma once support (Sergey Korshunoff, Vlad Vissoultchev, ...) 33 - switch/case code improved (Zdenek Pavlas) 34 - ~15% faster by TinyAlloc fast memory allocator (Vlad Vissoultchev) 35 - standard conforming (and GCC compatible) struct initialization 36 (Michael Matz) 37 - bit-field layout made compatible with GCC (Michael Matz) 38 - UTF8 in string literals supported (Zdenek Pavlas) 39 _ _Generic(...) supported (Matthias Gatto) 40 41 Licensing: 42 - TinyCC partly relicensed to MIT license (See RELICENSING file). 43 1 44 version 0.9.26: 2 45 … … 11 54 - Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka) 12 55 - x86-64 assembler (Frederic Feret) 13 - Many improvements for ARM target (Daniel Gl öckner, Thomas Preud'homme)56 - Many improvements for ARM target (Daniel Gl旦ckner, Thomas Preud'homme) 14 57 - Support WinCE PE ARM (Timo VJ Lahde) 15 58 - Support ARM hardfloat calling convention (Thomas Preud'homme) … … 30 73 31 74 - first support for x86-64 target (Shinichiro Hamaji) 32 - support µClibc75 - support 袖Clibc 33 76 - split tcc.c into tcc.h libtcc.c tccpp.c tccgen.c tcc.c 34 77 - improved preprocess output with linenumbers and spaces preserved 35 78 - tcc_relocate now copies code into user buffer 36 79 - fix bitfields with non-int types and in unions 37 - improve ARM cross-compiling (Daniel Gl öckner)80 - improve ARM cross-compiling (Daniel Gl旦ckner) 38 81 - link stabstr sections from multiple objects 39 82 - better (still limited) support for multiple TCCStates … … 52 95 - Use _WIN32 for a windows hosted tcc and define it for the PE target, 53 96 otherwise define __unix / __linux (Detlef Riekenberg) 54 - Import changesets (part 3) 409,410: ARM EABI by Daniel Gl öckner97 - Import changesets (part 3) 409,410: ARM EABI by Daniel Gl旦ckner 55 98 - Some in-between fixes: 56 99 TCC -E no longer hangs with macro calls involving newlines. … … 93 136 420: Zero pad x87 tenbyte long doubles (Felix Nawothnig) 94 137 417: Make 'sizeof' unsigned (Rob Landley) 95 397: Fix save_reg for longlongs (Daniel Gl öckner)138 397: Fix save_reg for longlongs (Daniel Gl旦ckner) 96 139 396: Fix "invalid relocation entry" problem on ubuntu - (Bernhard Fischer) 97 140 … … 135 178 version 0.9.21: 136 179 137 - ARM target support (Daniel Gl öckner)180 - ARM target support (Daniel Gl旦ckner) 138 181 - added '-funsigned-char, '-fsigned-char' and 139 182 '-Wimplicit-function-declaration' -
EcnlProtoTool/trunk/tcc-0.9.27/Makefile
r279 r331 1 # -------------------------------------------------------------------------- 1 2 # 2 3 # Tiny C Compiler Makefile 3 4 # 4 5 5 TOP ?= . 6 ifndef TOP 7 TOP = . 8 INCLUDED = no 9 endif 10 6 11 include $(TOP)/config.mak 7 VPATH = $(top_srcdir) 8 9 CPPFLAGS = -I$(TOP) # for config.h 10 11 ifeq (-$(findstring gcc,$(CC))-,-gcc-) 12 ifeq (-$(findstring $(GCC_MAJOR),01)-,--) 13 CFLAGS+=-fno-strict-aliasing 14 ifeq (-$(findstring $(GCC_MAJOR),23)-,--) 15 CFLAGS+=-Wno-pointer-sign -Wno-sign-compare 16 ifeq (-$(GCC_MAJOR)-$(findstring $(GCC_MINOR),56789)-,-4--) 17 CFLAGS+=-D_FORTIFY_SOURCE=0 12 13 ifeq (-$(CC)-$(GCC_MAJOR)-$(findstring $(GCC_MINOR),56789)-,-gcc-4--) 14 CFLAGS += -D_FORTIFY_SOURCE=0 15 endif 16 17 LIBTCC = libtcc.a 18 LIBTCC1 = libtcc1.a 19 LINK_LIBTCC = 20 LIBS = 21 CFLAGS += -I$(TOP) 22 CFLAGS += $(CPPFLAGS) 23 VPATH = $(TOPSRC) 24 25 ifdef CONFIG_WIN32 26 ifneq ($(CONFIG_static),yes) 27 LIBTCC = libtcc$(DLLSUF) 28 LIBTCCDEF = libtcc.def 29 endif 30 CFGWIN = -win 31 NATIVE_TARGET = $(ARCH)-win$(if $(findstring arm,$(ARCH)),ce,32) 18 32 else 19 CFLAGS+=-Wno-unused-result 20 endif 21 endif 22 endif 23 else # not GCC 24 ifeq (-$(findstring clang,$(CC))-,-clang-) 25 # make clang accept gnuisms in libtcc1.c 26 CFLAGS+=-fheinous-gnu-extensions 27 endif 28 endif 29 30 CPPFLAGS_P=$(CPPFLAGS) -DCONFIG_TCC_STATIC 31 CFLAGS_P=$(CFLAGS) -pg -static 32 LIBS_P= 33 LDFLAGS_P=$(LDFLAGS) 34 35 ifdef CONFIG_WIN64 36 CONFIG_WIN32=yes 37 endif 38 39 ifndef CONFIG_WIN32 40 LIBS=-lm 41 ifndef CONFIG_NOLDL 42 LIBS+=-ldl 43 endif 44 endif 45 46 # make libtcc as static or dynamic library? 47 ifdef DISABLE_STATIC 48 LIBTCC=libtcc.so.1.0 49 LINK_LIBTCC=-Wl,-rpath,"$(libdir)" 50 ifdef DISABLE_RPATH 51 LINK_LIBTCC= 52 endif 53 else 54 LIBTCC=libtcc.a 55 LINK_LIBTCC= 56 endif 33 LIBS=-lm 34 ifneq ($(CONFIG_ldl),no) 35 LIBS+=-ldl 36 endif 37 # make libtcc as static or dynamic library? 38 ifeq ($(CONFIG_static),no) 39 LIBTCC=libtcc$(DLLSUF) 40 export LD_LIBRARY_PATH := $(CURDIR)/$(TOP) 41 ifneq ($(CONFIG_rpath),no) 42 LINK_LIBTCC += -Wl,-rpath,"$(libdir)" 43 endif 44 endif 45 CFGWIN =-unx 46 NATIVE_TARGET = $(ARCH) 47 ifdef CONFIG_OSX 48 NATIVE_TARGET = $(ARCH)-osx 49 LDFLAGS += -flat_namespace -undefined warning 50 export MACOSX_DEPLOYMENT_TARGET := 10.2 51 endif 52 endif 53 54 # run local version of tcc with local libraries and includes 55 TCCFLAGS-unx = -B$(TOP) -I$(TOPSRC)/include -I$(TOPSRC) -I$(TOP) 56 TCCFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include -I$(TOPSRC) -I$(TOP) -L$(TOP) 57 TCCFLAGS = $(TCCFLAGS$(CFGWIN)) 58 TCC = $(TOP)/tcc$(EXESUF) $(TCCFLAGS) 59 ifdef CONFIG_OSX 60 TCCFLAGS += -D_ANSI_SOURCE 61 endif 62 63 CFLAGS_P = $(CFLAGS) -pg -static -DCONFIG_TCC_STATIC -DTCC_PROFILE 64 LIBS_P = $(LIBS) 65 LDFLAGS_P = $(LDFLAGS) 57 66 58 67 CONFIG_$(ARCH) = yes 59 68 NATIVE_DEFINES_$(CONFIG_i386) += -DTCC_TARGET_I386 60 NATIVE_DEFINES_$(CONFIG_x86 -64) += -DTCC_TARGET_X86_6469 NATIVE_DEFINES_$(CONFIG_x86_64) += -DTCC_TARGET_X86_64 61 70 NATIVE_DEFINES_$(CONFIG_WIN32) += -DTCC_TARGET_PE 71 NATIVE_DEFINES_$(CONFIG_OSX) += -DTCC_TARGET_MACHO 62 72 NATIVE_DEFINES_$(CONFIG_uClibc) += -DTCC_UCLIBC 63 NATIVE_DEFINES_$(CONFIG_arm) += -DTCC_TARGET_ARM -DWITHOUT_LIBTCC 73 NATIVE_DEFINES_$(CONFIG_musl) += -DTCC_MUSL 74 NATIVE_DEFINES_$(CONFIG_libgcc) += -DCONFIG_USE_LIBGCC 75 NATIVE_DEFINES_$(CONFIG_selinux) += -DHAVE_SELINUX 76 NATIVE_DEFINES_$(CONFIG_arm) += -DTCC_TARGET_ARM 64 77 NATIVE_DEFINES_$(CONFIG_arm_eabihf) += -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT 65 78 NATIVE_DEFINES_$(CONFIG_arm_eabi) += -DTCC_ARM_EABI 66 79 NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP 80 NATIVE_DEFINES_$(CONFIG_arm64) += -DTCC_TARGET_ARM64 67 81 NATIVE_DEFINES += $(NATIVE_DEFINES_yes) 68 82 69 ifeq ($(TOP),.) 70 71 PROGS=tcc$(EXESUF) 72 I386_CROSS = i386-tcc$(EXESUF) 73 WIN32_CROSS = i386-win32-tcc$(EXESUF) 74 WIN64_CROSS = x86_64-win32-tcc$(EXESUF) 75 WINCE_CROSS = arm-win32-tcc$(EXESUF) 76 X64_CROSS = x86_64-tcc$(EXESUF) 77 ARM_FPA_CROSS = arm-fpa-tcc$(EXESUF) 78 ARM_FPA_LD_CROSS = arm-fpa-ld-tcc$(EXESUF) 79 ARM_VFP_CROSS = arm-vfp-tcc$(EXESUF) 80 ARM_EABI_CROSS = arm-eabi-tcc$(EXESUF) 81 ARM_CROSS = $(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CROSS) 82 C67_CROSS = c67-tcc$(EXESUF) 83 84 CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c 83 ifeq ($(INCLUDED),no) 84 # -------------------------------------------------------------------------- 85 # running top Makefile 86 87 PROGS = tcc$(EXESUF) 88 TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCCDEF) 89 TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info 90 91 all: $(PROGS) $(TCCLIBS) $(TCCDOCS) 92 93 # cross compiler targets to build 94 TCC_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince c67 95 # TCC_X += arm-fpa arm-fpa-ld arm-vfp arm-eabi 96 97 # cross libtcc1.a targets to build 98 LIBTCC1_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince 99 100 PROGS_CROSS = $(foreach X,$(TCC_X),$X-tcc$(EXESUF)) 101 LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),$X-libtcc1.a) 102 103 # build cross compilers & libs 104 cross: $(LIBTCC1_CROSS) $(PROGS_CROSS) 105 106 # build specific cross compiler & lib 107 cross-%: %-tcc$(EXESUF) %-libtcc1.a ; 108 109 install: ; @$(MAKE) --no-print-directory install$(CFGWIN) 110 install-strip: ; @$(MAKE) --no-print-directory install$(CFGWIN) CONFIG_strip=yes 111 uninstall: ; @$(MAKE) --no-print-directory uninstall$(CFGWIN) 112 113 ifdef CONFIG_cross 114 all : cross 115 endif 116 117 # -------------------------------------------- 118 119 T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown) 120 X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-) 121 122 DEF-i386 = -DTCC_TARGET_I386 123 DEF-x86_64 = -DTCC_TARGET_X86_64 124 DEF-i386-win32 = -DTCC_TARGET_PE -DTCC_TARGET_I386 125 DEF-x86_64-win32= -DTCC_TARGET_PE -DTCC_TARGET_X86_64 126 DEF-x86_64-osx = -DTCC_TARGET_MACHO -DTCC_TARGET_X86_64 127 DEF-arm-wince = -DTCC_TARGET_PE -DTCC_TARGET_ARM -DTCC_ARM_EABI -DTCC_ARM_VFP -DTCC_ARM_HARDFLOAT 128 DEF-arm64 = -DTCC_TARGET_ARM64 129 DEF-c67 = -DTCC_TARGET_C67 -w # disable warnigs 130 DEF-arm-fpa = -DTCC_TARGET_ARM 131 DEF-arm-fpa-ld = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12 132 DEF-arm-vfp = -DTCC_TARGET_ARM -DTCC_ARM_VFP 133 DEF-arm-eabi = -DTCC_TARGET_ARM -DTCC_ARM_VFP -DTCC_ARM_EABI 134 DEF-arm-eabihf = -DTCC_TARGET_ARM -DTCC_ARM_VFP -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT 135 DEF-arm = $(DEF-arm-eabihf) 136 DEF-$(NATIVE_TARGET) = $(NATIVE_DEFINES) 137 138 DEFINES += $(DEF-$T) $(DEF-all) 139 DEFINES += $(if $(ROOT-$T),-DCONFIG_SYSROOT="\"$(ROOT-$T)\"") 140 DEFINES += $(if $(CRT-$T),-DCONFIG_TCC_CRTPREFIX="\"$(CRT-$T)\"") 141 DEFINES += $(if $(LIB-$T),-DCONFIG_TCC_LIBPATHS="\"$(LIB-$T)\"") 142 DEFINES += $(if $(INC-$T),-DCONFIG_TCC_SYSINCLUDEPATHS="\"$(INC-$T)\"") 143 DEFINES += $(DEF-$(or $(findstring win,$T),unx)) 144 145 ifneq ($(X),) 146 ifeq ($(CONFIG_WIN32),yes) 147 DEF-win += -DTCC_LIBTCC1="\"$(X)libtcc1.a\"" 148 DEF-unx += -DTCC_LIBTCC1="\"lib/$(X)libtcc1.a\"" 149 else 150 DEF-all += -DTCC_LIBTCC1="\"$(X)libtcc1.a\"" 151 DEF-win += -DCONFIG_TCCDIR="\"$(tccdir)/win32\"" 152 endif 153 endif 154 155 # include custom configuration (see make help) 156 -include config-extra.mak 157 158 CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c 85 159 CORE_FILES += tcc.h config.h libtcc.h tcctok.h 86 CORE_FILES += dummy.c 87 I386_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h 88 WIN32_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h tccpe.c 89 WIN64_FILES = $(CORE_FILES) x86_64-gen.c i386-asm.c x86_64-asm.h tccpe.c 90 WINCE_FILES = $(CORE_FILES) arm-gen.c tccpe.c 91 X86_64_FILES = $(CORE_FILES) x86_64-gen.c i386-asm.c x86_64-asm.h 92 ARM_FILES = $(CORE_FILES) arm-gen.c 93 C67_FILES = $(CORE_FILES) c67-gen.c tcccoff.c 94 95 ifdef CONFIG_WIN64 96 PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF) 97 NATIVE_FILES=$(WIN64_FILES) 98 PROGS_CROSS=$(WIN32_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(C67_CROSS) 99 LIBTCC1_CROSS=lib/i386-win32/libtcc1.a 100 LIBTCC1=libtcc1.a 101 else ifdef CONFIG_WIN32 102 PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF) 103 NATIVE_FILES=$(WIN32_FILES) 104 PROGS_CROSS=$(WIN64_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(C67_CROSS) 105 LIBTCC1_CROSS=lib/x86_64-win32/libtcc1.a 106 LIBTCC1=libtcc1.a 107 else ifeq ($(ARCH),i386) 108 NATIVE_FILES=$(I386_FILES) 109 PROGS_CROSS=$(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS) 110 LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a 111 LIBTCC1=libtcc1.a 112 else ifeq ($(ARCH),x86-64) 113 NATIVE_FILES=$(X86_64_FILES) 114 PROGS_CROSS=$(I386_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS) 115 LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a lib/i386/libtcc1.a 116 LIBTCC1=libtcc1.a 117 else ifeq ($(ARCH),arm) 118 NATIVE_FILES=$(ARM_FILES) 119 PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(C67_CROSS) 120 endif 121 122 ifeq ($(TARGETOS),Darwin) 123 PROGS+=tiny_libmaker$(EXESUF) 124 endif 125 126 ifdef CONFIG_USE_LIBGCC 127 LIBTCC1= 128 endif 129 130 TCCLIBS = $(LIBTCC1) $(LIBTCC) 131 TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info 132 133 ifdef CONFIG_CROSS 134 PROGS+=$(PROGS_CROSS) 135 TCCLIBS+=$(LIBTCC1_CROSS) 136 endif 137 138 all: $(PROGS) $(TCCLIBS) $(TCCDOCS) 160 i386_FILES = $(CORE_FILES) i386-gen.c i386-link.c i386-asm.c i386-asm.h i386-tok.h 161 i386-win32_FILES = $(i386_FILES) tccpe.c 162 x86_64_FILES = $(CORE_FILES) x86_64-gen.c x86_64-link.c i386-asm.c x86_64-asm.h 163 x86_64-win32_FILES = $(x86_64_FILES) tccpe.c 164 x86_64-osx_FILES = $(x86_64_FILES) 165 arm_FILES = $(CORE_FILES) arm-gen.c arm-link.c arm-asm.c 166 arm-wince_FILES = $(arm_FILES) tccpe.c 167 arm64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c 168 c67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c 169 170 # libtcc sources 171 LIBTCC_SRC = $(filter-out tcc.c tcctools.c,$(filter %.c,$($T_FILES))) 172 173 ifeq ($(ONE_SOURCE),yes) 174 LIBTCC_OBJ = $(X)libtcc.o 175 LIBTCC_INC = $($T_FILES) 176 TCC_FILES = $(X)tcc.o 177 tcc.o : DEFINES += -DONE_SOURCE=0 178 else 179 LIBTCC_OBJ = $(patsubst %.c,$(X)%.o,$(LIBTCC_SRC)) 180 LIBTCC_INC = $(filter %.h %-gen.c %-link.c,$($T_FILES)) 181 TCC_FILES = $(X)tcc.o $(LIBTCC_OBJ) 182 $(TCC_FILES) : DEFINES += -DONE_SOURCE=0 183 endif 184 185 # target specific object rule 186 $(X)%.o : %.c $(LIBTCC_INC) 187 $(CC) -o $@ -c $< $(DEFINES) $(CFLAGS) 188 189 # additional dependencies 190 $(X)tcc.o : tcctools.c 139 191 140 192 # Host Tiny C Compiler 141 193 tcc$(EXESUF): tcc.o $(LIBTCC) 142 $(CC) -o $@ $^ $(LIBS) $( CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LINK_LIBTCC)194 $(CC) -o $@ $^ $(LIBS) $(LDFLAGS) $(LINK_LIBTCC) 143 195 144 196 # Cross Tiny C Compilers 145 %-tcc$(EXESUF): tcc.c 146 $(CC) -o $@ $< -DONE_SOURCE $(DEFINES) $(CPPFLAGS) $(CFLAGS) $(LIBS) $(LDFLAGS) 197 %-tcc$(EXESUF): FORCE 198 @$(MAKE) --no-print-directory $@ CROSS_TARGET=$* ONE_SOURCE=$(or $(ONE_SOURCE),yes) 199 200 $(CROSS_TARGET)-tcc$(EXESUF): $(TCC_FILES) 201 $(CC) -o $@ $^ $(LIBS) $(LDFLAGS) 147 202 148 203 # profiling version 149 tcc_p$(EXESUF): $(NATIVE_FILES) 150 $(CC) -o $@ $< -DONE_SOURCE $(NATIVE_DEFINES) $(CPPFLAGS_P) $(CFLAGS_P) $(LIBS_P) $(LDFLAGS_P) 151 152 $(I386_CROSS): DEFINES = -DTCC_TARGET_I386 \ 153 -DCONFIG_TCCDIR="\"$(tccdir)/i386\"" 154 $(X64_CROSS): DEFINES = -DTCC_TARGET_X86_64 155 $(WIN32_CROSS): DEFINES = -DTCC_TARGET_I386 -DTCC_TARGET_PE \ 156 -DCONFIG_TCCDIR="\"$(tccdir)/win32\"" \ 157 -DCONFIG_TCC_LIBPATHS="\"{B}/lib/32;{B}/lib\"" 158 $(WIN64_CROSS): DEFINES = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE \ 159 -DCONFIG_TCCDIR="\"$(tccdir)/win32\"" \ 160 -DCONFIG_TCC_LIBPATHS="\"{B}/lib/64;{B}/lib\"" 161 $(WINCE_CROSS): DEFINES = -DTCC_TARGET_PE 162 $(C67_CROSS): DEFINES = -DTCC_TARGET_C67 163 $(ARM_FPA_CROSS): DEFINES = -DTCC_TARGET_ARM 164 $(ARM_FPA_LD_CROSS)$(EXESUF): DEFINES = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12 165 $(ARM_VFP_CROSS): DEFINES = -DTCC_TARGET_ARM -DTCC_ARM_VFP 166 $(ARM_EABI_CROSS): DEFINES = -DTCC_TARGET_ARM -DTCC_ARM_EABI 167 168 $(I386_CROSS): $(I386_FILES) 169 $(X64_CROSS): $(X86_64_FILES) 170 $(WIN32_CROSS): $(WIN32_FILES) 171 $(WIN64_CROSS): $(WIN64_FILES) 172 $(WINCE_CROSS): $(WINCE_FILES) 173 $(C67_CROSS): $(C67_FILES) 174 $(ARM_FPA_CROSS) $(ARM_FPA_LD_CROSS) $(ARM_VFP_CROSS) $(ARM_EABI_CROSS): $(ARM_FILES) 175 176 # libtcc generation and test 177 ifndef ONE_SOURCE 178 LIBTCC_OBJ = $(filter-out tcc.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES)))) 179 LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES),$(NATIVE_FILES)) 180 else 181 LIBTCC_OBJ = libtcc.o 182 LIBTCC_INC = $(NATIVE_FILES) 183 libtcc.o : NATIVE_DEFINES += -DONE_SOURCE 184 endif 185 186 $(LIBTCC_OBJ) tcc.o : %.o : %.c $(LIBTCC_INC) 187 $(CC) -o $@ -c $< $(NATIVE_DEFINES) $(CPPFLAGS) $(CFLAGS) 188 204 tcc_p$(EXESUF): $($T_FILES) 205 $(CC) -o $@ $< $(DEFINES) $(CFLAGS_P) $(LIBS_P) $(LDFLAGS_P) 206 207 # static libtcc library 189 208 libtcc.a: $(LIBTCC_OBJ) 190 209 $(AR) rcs $@ $^ 191 210 192 libtcc.so.1.0: $(LIBTCC_OBJ) 211 # dynamic libtcc library 212 libtcc.so: $(LIBTCC_OBJ) 193 213 $(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDFLAGS) 194 214 195 libtcc.so.1.0: CFLAGS+=-fPIC 196 197 # windows utilities 198 tiny_impdef$(EXESUF): win32/tools/tiny_impdef.c 199 $(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) 200 tiny_libmaker$(EXESUF): win32/tools/tiny_libmaker.c 201 $(CC) -o $@ $< $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) 215 libtcc.so: CFLAGS+=-fPIC 216 libtcc.so: LDFLAGS+=-fPIC 217 218 # windows dynamic libtcc library 219 libtcc.dll : $(LIBTCC_OBJ) 220 $(CC) -shared -o $@ $^ $(LDFLAGS) 221 libtcc.dll : DEFINES += -DLIBTCC_AS_DLL 222 223 # import file for windows libtcc.dll 224 libtcc.def : libtcc.dll tcc$(EXESUF) 225 $(XTCC) -impdef $< -o $@ 226 XTCC ?= ./tcc$(EXESUF) 202 227 203 228 # TinyCC runtime libraries 204 libtcc1.a : FORCE 205 $(MAKE) -C lib native 206 lib/%/libtcc1.a : FORCE $(PROGS_CROSS) 207 $(MAKE) -C lib cross TARGET=$* 208 229 libtcc1.a : tcc$(EXESUF) FORCE 230 @$(MAKE) -C lib DEFINES='$(DEF-$T)' 231 232 # Cross libtcc1.a 233 %-libtcc1.a : %-tcc$(EXESUF) FORCE 234 @$(MAKE) -C lib DEFINES='$(DEF-$*)' CROSS_TARGET=$* 235 236 .PRECIOUS: %-libtcc1.a 209 237 FORCE: 210 238 211 # install 212 TCC_INCLUDES = stdarg.h stddef.h stdbool.h float.h varargs.h tcclib.h 213 INSTALL=install 214 ifdef STRIP_BINARIES 215 INSTALLBIN=$(INSTALL) -s 216 else 217 INSTALLBIN=$(INSTALL) 218 endif 219 220 ifndef CONFIG_WIN32 221 install: $(PROGS) $(TCCLIBS) $(TCCDOCS) 222 mkdir -p "$(bindir)" 223 ifeq ($(CC),tcc) 224 $(INSTALL) -m755 $(PROGS) "$(bindir)" 225 else 226 $(INSTALLBIN) -m755 $(PROGS) "$(bindir)" 227 endif 228 mkdir -p "$(mandir)/man1" 229 -$(INSTALL) tcc.1 "$(mandir)/man1" 230 mkdir -p "$(infodir)" 231 -$(INSTALL) tcc-doc.info "$(infodir)" 232 mkdir -p "$(tccdir)" 233 mkdir -p "$(tccdir)/include" 234 ifneq ($(LIBTCC1),) 235 $(INSTALL) -m644 $(LIBTCC1) "$(tccdir)" 236 endif 237 $(INSTALL) -m644 $(addprefix $(top_srcdir)/include/,$(TCC_INCLUDES)) "$(tccdir)/include" 238 mkdir -p "$(libdir)" 239 $(INSTALL) -m755 $(LIBTCC) "$(libdir)" 240 ifdef DISABLE_STATIC 241 ln -sf "$(ln_libdir)/libtcc.so.1.0" "$(libdir)/libtcc.so.1" 242 ln -sf "$(ln_libdir)/libtcc.so.1.0" "$(libdir)/libtcc.so" 243 endif 244 mkdir -p "$(includedir)" 245 $(INSTALL) -m644 $(top_srcdir)/libtcc.h "$(includedir)" 246 mkdir -p "$(docdir)" 247 -$(INSTALL) -m644 tcc-doc.html "$(docdir)" 248 ifdef CONFIG_CROSS 249 mkdir -p "$(tccdir)/win32/lib/32" 250 mkdir -p "$(tccdir)/win32/lib/64" 251 ifeq ($(ARCH),x86-64) 252 mkdir -p "$(tccdir)/i386" 253 $(INSTALL) -m644 lib/i386/libtcc1.a "$(tccdir)/i386" 254 cp -r "$(tccdir)/include" "$(tccdir)/i386" 255 endif 256 $(INSTALL) -m644 win32/lib/*.def "$(tccdir)/win32/lib" 257 $(INSTALL) -m644 lib/i386-win32/libtcc1.a "$(tccdir)/win32/lib/32" 258 $(INSTALL) -m644 lib/x86_64-win32/libtcc1.a "$(tccdir)/win32/lib/64" 259 cp -r win32/include/. "$(tccdir)/win32/include" 260 cp -r include/. "$(tccdir)/win32/include" 261 endif 262 263 uninstall: 264 rm -fv $(foreach P,$(PROGS),"$(bindir)/$P") 265 rm -fv $(foreach P,$(LIBTCC1),"$(tccdir)/$P") 266 rm -fv $(foreach P,$(TCC_INCLUDES),"$(tccdir)/include/$P") 267 rm -fv "$(docdir)/tcc-doc.html" "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info" 268 rm -fv "$(libdir)/$(LIBTCC)" "$(includedir)/libtcc.h" 269 rm -fv "$(libdir)/libtcc.so*" 270 rm -rf "$(tccdir)/win32" 271 -rmdir $(tccdir)/include 272 ifeq ($(ARCH),x86-64) 273 rm -rf "$(tccdir)/i386" 274 endif 275 else 276 # on windows 277 install: $(PROGS) $(TCCLIBS) $(TCCDOCS) 278 mkdir -p "$(tccdir)" 279 mkdir -p "$(tccdir)/lib" 280 mkdir -p "$(tccdir)/include" 281 mkdir -p "$(tccdir)/examples" 282 mkdir -p "$(tccdir)/doc" 283 mkdir -p "$(tccdir)/libtcc" 284 $(INSTALLBIN) -m755 $(PROGS) "$(tccdir)" 285 $(INSTALL) -m644 $(LIBTCC1) win32/lib/*.def "$(tccdir)/lib" 286 cp -r win32/include/. "$(tccdir)/include" 287 cp -r win32/examples/. "$(tccdir)/examples" 288 $(INSTALL) -m644 $(addprefix include/,$(TCC_INCLUDES)) "$(tccdir)/include" 289 $(INSTALL) -m644 tcc-doc.html win32/tcc-win32.txt "$(tccdir)/doc" 290 $(INSTALL) -m644 $(LIBTCC) libtcc.h "$(tccdir)/libtcc" 291 ifdef CONFIG_CROSS 292 mkdir -p "$(tccdir)/lib/32" 293 mkdir -p "$(tccdir)/lib/64" 294 -$(INSTALL) -m644 lib/i386-win32/libtcc1.a "$(tccdir)/lib/32" 295 -$(INSTALL) -m644 lib/x86_64-win32/libtcc1.a "$(tccdir)/lib/64" 296 endif 297 298 uninstall: 299 rm -rfv "$(tccdir)/*" 300 endif 301 239 # -------------------------------------------------------------------------- 302 240 # documentation and man page 303 241 tcc-doc.html: tcc-doc.texi 304 -texi2html -monolithic -number $<242 makeinfo --no-split --html --number-sections -o $@ $< || true 305 243 306 244 tcc.1: tcc-doc.texi 307 -$(top_srcdir)/texi2pod.pl $< tcc.pod 308 -pod2man --section=1 --center=" " --release=" " tcc.pod > $@ 245 $(TOPSRC)/texi2pod.pl $< tcc.pod \ 246 && pod2man --section=1 --center="Tiny C Compiler" --release="$(VERSION)" tcc.pod >tmp.1 \ 247 && mv tmp.1 $@ || rm -f tmp.1 309 248 310 249 tcc-doc.info: tcc-doc.texi 311 -makeinfo $< 312 313 # in tests subdir 314 export LIBTCC1 315 316 %est: 317 $(MAKE) -C tests $@ 318 319 clean: 320 rm -vf $(PROGS) tcc_p$(EXESUF) tcc.pod *~ *.o *.a *.so* *.out *.exe libtcc_test$(EXESUF) 321 $(MAKE) -C tests $@ 322 ifneq ($(LIBTCC1),) 323 $(MAKE) -C lib $@ 324 endif 325 326 distclean: clean 327 rm -vf config.h config.mak config.texi tcc.1 tcc-doc.info tcc-doc.html 328 329 config.mak: 330 @echo "Please run ./configure." 331 @exit 1 250 makeinfo $< || true 251 252 # -------------------------------------------------------------------------- 253 # install 254 255 INSTALL = install -m644 256 INSTALLBIN = install -m755 $(STRIP_$(CONFIG_strip)) 257 STRIP_yes = -s 258 259 LIBTCC1_W = $(filter %-win32-libtcc1.a %-wince-libtcc1.a,$(LIBTCC1_CROSS)) 260 LIBTCC1_U = $(filter-out $(LIBTCC1_W),$(LIBTCC1_CROSS)) 261 IB = $(if $1,mkdir -p $2 && $(INSTALLBIN) $1 $2) 262 IBw = $(call IB,$(wildcard $1),$2) 263 IF = $(if $1,mkdir -p $2 && $(INSTALL) $1 $2) 264 IFw = $(call IF,$(wildcard $1),$2) 265 IR = mkdir -p $2 && cp -r $1/. $2 266 267 # install progs & libs 268 install-unx: 269 $(call IBw,$(PROGS) $(PROGS_CROSS),"$(bindir)") 270 $(call IFw,$(LIBTCC1) $(LIBTCC1_U),"$(tccdir)") 271 $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include") 272 $(call $(if $(findstring .so,$(LIBTCC)),IBw,IFw),$(LIBTCC),"$(libdir)") 273 $(call IF,$(TOPSRC)/libtcc.h,"$(includedir)") 274 $(call IFw,tcc.1,"$(mandir)/man1") 275 $(call IFw,tcc-doc.info,"$(infodir)") 276 $(call IFw,tcc-doc.html,"$(docdir)") 277 ifneq "$(wildcard $(LIBTCC1_W))" "" 278 $(call IFw,$(TOPSRC)/win32/lib/*.def $(LIBTCC1_W),"$(tccdir)/win32/lib") 279 $(call IR,$(TOPSRC)/win32/include,"$(tccdir)/win32/include") 280 $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/win32/include") 281 endif 282 283 # uninstall 284 uninstall-unx: 285 @rm -fv $(foreach P,$(PROGS) $(PROGS_CROSS),"$(bindir)/$P") 286 @rm -fv "$(libdir)/libtcc.a" "$(libdir)/libtcc.so" "$(includedir)/libtcc.h" 287 @rm -fv "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info" 288 @rm -fv "$(docdir)/tcc-doc.html" 289 rm -r "$(tccdir)" 290 291 # install progs & libs on windows 292 install-win: 293 $(call IBw,$(PROGS) $(PROGS_CROSS) $(subst libtcc.a,,$(LIBTCC)),"$(bindir)") 294 $(call IF,$(TOPSRC)/win32/lib/*.def,"$(tccdir)/lib") 295 $(call IFw,libtcc1.a $(LIBTCC1_W),"$(tccdir)/lib") 296 $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include") 297 $(call IR,$(TOPSRC)/win32/include,"$(tccdir)/include") 298 $(call IR,$(TOPSRC)/win32/examples,"$(tccdir)/examples") 299 $(call IF,$(TOPSRC)/tests/libtcc_test.c,"$(tccdir)/examples") 300 $(call IFw,$(TOPSRC)/libtcc.h $(subst .dll,.def,$(LIBTCC)),"$(libdir)") 301 $(call IFw,$(TOPSRC)/win32/tcc-win32.txt tcc-doc.html,"$(docdir)") 302 ifneq "$(wildcard $(LIBTCC1_U))" "" 303 $(call IFw,$(LIBTCC1_U),"$(tccdir)/lib") 304 $(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/lib/include") 305 endif 306 307 # the msys-git shell works to configure && make except it does not have install 308 ifeq "$(and $(CONFIG_WIN32),$(shell which install >/dev/null 2>&1 || echo no))" "no" 309 install-win : INSTALL = cp 310 install-win : INSTALLBIN = cp 311 endif 312 313 # uninstall on windows 314 uninstall-win: 315 @rm -fv $(foreach P,$(PROGS) $(PROGS_CROSS) libtcc.dll,"$(bindir)/$P") 316 @rm -fv $(foreach F,tcc-doc.html tcc-win32.txt,"$(docdir)/$F") 317 @rm -fv $(foreach F,libtcc.h libtcc.def libtcc.a,"$(libdir)/$F") 318 rm -r "$(tccdir)" 319 320 # -------------------------------------------------------------------------- 321 # other stuff 322 323 TAGFILES = *.[ch] include/*.h lib/*.[chS] 324 tags : ; ctags $(TAGFILES) 325 # cannot have both tags and TAGS on windows 326 ETAGS : ; etags $(TAGFILES) 332 327 333 328 # create release tarball from *current* git branch (including tcc-doc.html 334 329 # and converting two files to CRLF) 335 TCC-VERSION := tcc-$(shell cat $(top_srcdir)/VERSION)330 TCC-VERSION = tcc-$(VERSION) 336 331 tar: tcc-doc.html 337 332 mkdir $(TCC-VERSION) … … 345 340 git reset 346 341 347 348 .PHONY: all clean tar distclean install uninstall FORCE 349 350 endif # ifeq ($(TOP),.) 342 config.mak: 343 $(if $(wildcard $@),,@echo "Please run ./configure." && exit 1) 344 345 # run all tests 346 test: 347 $(MAKE) -C tests 348 # run test(s) from tests2 subdir (see make help) 349 tests2.%: 350 $(MAKE) -C tests/tests2 $@ 351 352 clean: 353 rm -f tcc$(EXESUF) tcc_p$(EXESUF) *-tcc$(EXESUF) tcc.pod 354 rm -f *~ *.o *.a *.so* *.out *.log lib*.def *.exe *.dll a.out tags TAGS 355 @$(MAKE) -C lib $@ 356 @$(MAKE) -C tests $@ 357 358 distclean: clean 359 rm -f config.h config.mak config.texi tcc.1 tcc-doc.info tcc-doc.html 360 361 .PHONY: all clean test tar tags ETAGS distclean install uninstall FORCE 362 363 help: 364 @echo "make" 365 @echo " build native compiler (from separate objects)" 366 @echo "" 367 @echo "make cross" 368 @echo " build cross compilers (from one source)" 369 @echo "" 370 @echo "make ONE_SOURCE=yes / no" 371 @echo " force building from one source / separate objects" 372 @echo "" 373 @echo "make cross-TARGET" 374 @echo " build one specific cross compiler for 'TARGET', as in" 375 @echo " $(TCC_X)" 376 @echo "" 377 @echo "Custom configuration:" 378 @echo " The makefile includes a file 'config-extra.mak' if it is present." 379 @echo " This file may contain some custom configuration. For example:" 380 @echo "" 381 @echo " NATIVE_DEFINES += -D..." 382 @echo "" 383 @echo " Or for example to configure the search paths for a cross-compiler" 384 @echo " that expects the linux files in <tccdir>/i386-linux:" 385 @echo "" 386 @echo " ROOT-i386 = {B}/i386-linux" 387 @echo " CRT-i386 = {B}/i386-linux/usr/lib" 388 @echo " LIB-i386 = {B}/i386-linux/lib:{B}/i386-linux/usr/lib" 389 @echo " INC-i386 = {B}/lib/include:{B}/i386-linux/usr/include" 390 @echo " DEF-i386 += -D__linux__" 391 @echo "" 392 @echo "make test" 393 @echo " run all tests" 394 @echo "" 395 @echo "make tests2.all / make tests2.37 / make tests2.37+" 396 @echo " run all/single test(s) from tests2, optionally update .expect" 397 @echo "" 398 @echo "Other supported make targets:" 399 @echo " install install-strip tags ETAGS tar clean distclean help" 400 @echo "" 401 402 # -------------------------------------------------------------------------- 403 endif # ($(INCLUDED),no) -
EcnlProtoTool/trunk/tcc-0.9.27/README
r279 r331 29 29 ------------- 30 30 31 1) Installation on a i386 Linux host (for Windows read tcc-win32.txt)31 1) Installation on a i386/x86_64/arm Linux/OSX/FreeBSD host 32 32 33 33 ./configure … … 36 36 make install 37 37 38 Alternatively, out-of-tree builds are supported: you may use different 39 directories to hold build objects, kept separate from your source tree: 38 Notes: For OSX and FreeBSD, gmake should be used instead of make. 39 For Windows read tcc-win32.txt. 40 40 41 mkdir _build 42 cd _build 43 ../configure 44 make 45 make test 46 make install 47 48 By default, tcc is installed in /usr/local/bin. 49 ./configure --help shows configuration options. 41 makeinfo must be installed to compile the doc. By default, tcc is 42 installed in /usr/local/bin. ./configure --help shows configuration 43 options. 50 44 51 45 -
EcnlProtoTool/trunk/tcc-0.9.27/TODO
r279 r331 3 3 Bugs: 4 4 5 - fix macro substitution with nested definitions (ShangHongzhang)5 - i386 fastcall is mostly wrong 6 6 - FPU st(0) is left unclean (kwisatz haderach). Incompatible with 7 7 optimized gcc/msc code 8 9 - constructors10 - cast bug (Peter Wang)11 - define incomplete type if defined several times (Peter Wang).12 - configure --cc=tcc (still one bug in libtcc1.c)13 - test binutils/gcc compile14 - tci patch + argument.15 - see -lxxx bug (Michael Charity).16 8 - see transparent union pb in /urs/include/sys/socket.h 17 9 - precise behaviour of typeof with arrays ? (__put_user macro) … … 22 14 (net/ipv4/ip_output.c) 23 15 - fix function pointer type display 24 - check lcc test suite -> fix bitfield binary operations25 16 - check section alignment in C 26 17 - fix invalid cast in comparison 'if (v == (int8_t)v)' … … 28 19 - fix static functions declared inside block 29 20 - fix multiple unions init 30 - sizeof, alignof, typeof can still generate code in some cases.31 - Fix the remaining libtcc memory leaks.32 21 - make libtcc fully reentrant (except for the compilation stage itself). 22 - struct/union/enum definitions in nested scopes (see also Debian bug #770657) 23 - __STDC_IEC_559__: float f(void) { static float x = 0.0 / 0.0; return x; } 24 - memory may be leaked after errors (longjmp). 25 26 Portability: 27 28 - it is assumed that int is 32-bit and sizeof(int) == 4 29 - int is used when host or target size_t would make more sense 30 - TCC handles target floating-point (fp) values using the host's fp 31 arithmetic, which is simple and fast but may lead to exceptions 32 and inaccuracy and wrong representations when cross-compiling 33 34 Linking: 35 36 - static linking (-static) does not work 33 37 34 38 Bound checking: 35 39 36 - '-b' bug.37 40 - fix bound exit on RedHat 7.3 38 41 - setjmp is not supported properly in bound checking. … … 46 49 - disable-asm and disable-bcheck options 47 50 - __builtin_expect() 48 - improve '-E' option.49 51 - atexit (Nigel Horne) 50 - packed attribute51 52 - C99: add complex types (gcc 3.2 testsuite issue) 52 53 - postfix compound literals (see 20010124-1.c) 54 - interactive mode / integrated debugger 53 55 54 56 Optimizations: … … 66 68 boolean variable to tell if compound literal was already 67 69 initialized). 68 - add PowerPC or ARM codegenerator and improve codegen for RISC (need70 - add PowerPC generator and improve codegen for RISC (need 69 71 to suppress VT_LOCAL and use a base register instead). 70 - interactive mode / integrated debugger71 72 - fix preprocessor symbol redefinition 72 - better constant opt (&&, ||, ?:)73 73 - add portable byte code generator and interpreter for other 74 74 unsupported architectures. … … 77 77 check exception code (exception filter func). 78 78 - handle void (__attribute__() *ptr)() 79 - VLAs are implemented in a way that is not compatible with signals: 80 http://lists.gnu.org/archive/html/tinycc-devel/2015-11/msg00018.html 79 81 80 82 Fixed (probably): … … 92 94 - function pointers/lvalues in ? : (linux kernel net/core/dev.c) 93 95 - win32: add __stdcall, check GetModuleHandle for dlls. 96 - macro substitution with nested definitions (ShangHongzhang) 97 - with "-run" and libtcc, a PLT is now built. 98 - '-E' option was improved 99 - packed attribute is now supported 100 - ARM and ARM64 code generators have been added. -
EcnlProtoTool/trunk/tcc-0.9.27/VERSION
r279 r331 1 0.9.2 61 0.9.27 -
EcnlProtoTool/trunk/tcc-0.9.27/arm-gen.c
r321 r331 1 1 /* 2 2 * ARMv4 code generator for TCC 3 * 3 * 4 4 * Copyright (c) 2003 Daniel Glöckner 5 5 * Copyright (c) 2012 Thomas Preud'homme … … 24 24 #ifdef TARGET_DEFS_ONLY 25 25 26 #ifdef TCC_ARM_EABI 27 #ifndef TCC_ARM_VFP // Avoid useless warning 28 #define TCC_ARM_VFP 29 #endif 26 #if defined(TCC_ARM_EABI) && !defined(TCC_ARM_VFP) 27 #error "Currently TinyCC only supports float computation with VFP instructions" 30 28 #endif 31 29 … … 37 35 #endif 38 36 39 #ifndef TCC_ ARM_VERSION40 # define TCC_ ARM_VERSION 537 #ifndef TCC_CPU_VERSION 38 # define TCC_CPU_VERSION 5 41 39 #endif 42 40 … … 47 45 #define RC_FLOAT 0x0002 /* generic float register */ 48 46 #define RC_R0 0x0004 49 #define RC_R1 0x0008 47 #define RC_R1 0x0008 50 48 #define RC_R2 0x0010 51 49 #define RC_R3 0x0020 … … 82 80 TREG_F7, 83 81 #endif 82 TREG_SP = 13, 83 TREG_LR, 84 84 }; 85 85 … … 105 105 /* defined if structures are passed as pointers. Otherwise structures 106 106 are directly pushed on stack. */ 107 / /#define FUNC_STRUCT_PARAM_AS_PTR107 /* #define FUNC_STRUCT_PARAM_AS_PTR */ 108 108 109 109 /* pointer size, in bytes */ … … 131 131 132 132 /******************************************************/ 133 /* ELF defines */134 135 #define EM_TCC_TARGET EM_ARM136 137 /* relocation type for 32 bit data relocation */138 #define R_DATA_32 R_ARM_ABS32139 #define R_DATA_PTR R_ARM_ABS32140 #define R_JMP_SLOT R_ARM_JUMP_SLOT141 #define R_COPY R_ARM_COPY142 143 #define ELF_START_ADDR 0x00008000144 #define ELF_PAGE_SIZE 0x1000145 146 /******************************************************/147 133 #else /* ! TARGET_DEFS_ONLY */ 148 134 /******************************************************/ 149 135 #include "tcc.h" 136 137 enum float_abi float_abi; 150 138 151 139 ST_DATA const int reg_classes[NB_REGS] = { … … 172 160 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) 173 161 static CType float_type, double_type, func_float_type, func_double_type; 174 ST_FUNC void arm_init _types(void)162 ST_FUNC void arm_init(struct TCCState *s) 175 163 { 176 164 float_type.t = VT_FLOAT; … … 180 168 func_double_type.t = VT_FUNC; 181 169 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD); 170 171 float_abi = s->float_abi; 172 #ifndef TCC_ARM_HARDFLOAT 173 tcc_warning("soft float ABI currently not supported: default to softfp"); 174 #endif 182 175 } 183 176 #else … … 185 178 #define func_double_type func_old_type 186 179 #define func_ldouble_type func_old_type 187 ST_FUNC void arm_init_types(void) {} 180 ST_FUNC void arm_init(struct TCCState *s) 181 { 182 #if 0 183 #if !defined (TCC_ARM_VFP) 184 tcc_warning("Support for FPA is deprecated and will be removed in next" 185 " release"); 186 #endif 187 #if !defined (TCC_ARM_EABI) 188 tcc_warning("Support for OABI is deprecated and will be removed in next" 189 " release"); 190 #endif 191 #endif 192 } 188 193 #endif 189 194 … … 198 203 /******************************************************/ 199 204 200 void o(unsigned int i) 205 #if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP) 206 const char *default_elfinterp(struct TCCState *s) 207 { 208 if (s->float_abi == ARM_HARD_FLOAT) 209 return "/lib/ld-linux-armhf.so.3"; 210 else 211 return "/lib/ld-linux.so.3"; 212 } 213 #endif 214 215 void o(uint32_t i) 201 216 { 202 217 /* this is a good place to start adding big-endian support*/ 203 218 int ind1; 204 219 if (nocode_wanted) 220 return; 205 221 ind1 = ind + 4; 206 222 if (!cur_text_section) … … 212 228 i>>=8; 213 229 cur_text_section->data[ind++] = i&255; 214 i>>=8; 230 i>>=8; 215 231 cur_text_section->data[ind++] = i&255; 216 232 i>>=8; … … 328 344 } 329 345 330 ST_FUNCuint32_t encbranch(int pos, int addr, int fail)346 uint32_t encbranch(int pos, int addr, int fail) 331 347 { 332 348 addr-=pos+8; … … 377 393 if(r<TREG_F0 || r>TREG_F7) 378 394 tcc_error("compiler error! register %i is no vfp register",r); 379 return r -5;395 return r - TREG_F0; 380 396 } 381 397 #else … … 384 400 if(r<TREG_F0 || r>TREG_F3) 385 401 tcc_error("compiler error! register %i is no fpa register",r); 386 return r -5;402 return r - TREG_F0; 387 403 } 388 404 #endif … … 390 406 static uint32_t intr(int r) 391 407 { 392 if(r ==4)408 if(r == TREG_R12) 393 409 return 12; 394 if((r<0 || r>4) && r!=14) 395 tcc_error("compiler error! register %i is no int register",r); 396 return r; 410 if(r >= TREG_R0 && r <= TREG_R3) 411 return r - TREG_R0; 412 if (r >= TREG_SP && r <= TREG_LR) 413 return r + (13 - TREG_SP); 414 tcc_error("compiler error! register %i is no int register",r); 397 415 } 398 416 … … 499 517 fr = sv->r; 500 518 ft = sv->type.t; 501 fc = sv->c. ul;519 fc = sv->c.i; 502 520 503 521 if(fc>=0) … … 507 525 fc=-fc; 508 526 } 509 527 510 528 v = fr & VT_VALMASK; 511 529 if (fr & VT_LVAL) { … … 514 532 v1.type.t = VT_PTR; 515 533 v1.r = VT_LOCAL | VT_LVAL; 516 v1.c.ul = sv->c.ul; 517 load(base=14 /* lr */, &v1); 534 v1.c.i = sv->c.i; 535 load(TREG_LR, &v1); 536 base = 14; /* lr */ 518 537 fc=sign=0; 519 538 v=VT_LOCAL; … … 521 540 v1.type.t = VT_PTR; 522 541 v1.r = fr&~VT_LVAL; 523 v1.c. ul = sv->c.ul;542 v1.c.i = sv->c.i; 524 543 v1.sym=sv->sym; 525 load(base=14, &v1); 544 load(TREG_LR, &v1); 545 base = 14; /* lr */ 526 546 fc=sign=0; 527 547 v=VT_LOCAL; … … 572 592 if(!sign) 573 593 op|=0x800000; 574 if ((ft & VT_BTYPE) == VT_BYTE )594 if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) 575 595 op|=0x400000; 576 596 o(op|(intr(r)<<12)|fc|(base<<16)); … … 580 600 } else { 581 601 if (v == VT_CONST) { 582 op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c. ul);602 op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.i); 583 603 if (fr & VT_SYM || !op) { 584 604 o(0xE59F0000|(intr(r)<<12)); … … 586 606 if(fr & VT_SYM) 587 607 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); 588 o(sv->c. ul);608 o(sv->c.i); 589 609 } else 590 610 o(op); 591 611 return; 592 612 } else if (v == VT_LOCAL) { 593 op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c. ul);613 op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.i); 594 614 if (fr & VT_SYM || !op) { 595 615 o(0xE59F0000|(intr(r)<<12)); … … 597 617 if(fr & VT_SYM) // needed ? 598 618 greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); 599 o(sv->c. ul);619 o(sv->c.i); 600 620 o(0xE08B0000|(intr(r)<<12)|intr(r)); 601 621 } else … … 603 623 return; 604 624 } else if(v == VT_CMP) { 605 o(mapcc(sv->c. ul)|0x3A00001|(intr(r)<<12));606 o(mapcc(negcc(sv->c. ul))|0x3A00000|(intr(r)<<12));625 o(mapcc(sv->c.i)|0x3A00001|(intr(r)<<12)); 626 o(mapcc(negcc(sv->c.i))|0x3A00000|(intr(r)<<12)); 607 627 return; 608 628 } else if (v == VT_JMP || v == VT_JMPI) { … … 611 631 o(0xE3A00000|(intr(r)<<12)|t); 612 632 o(0xEA000000); 613 gsym(sv->c. ul);633 gsym(sv->c.i); 614 634 o(0xE3A00000|(intr(r)<<12)|(t^1)); 615 635 return; … … 638 658 fr = sv->r; 639 659 ft = sv->type.t; 640 fc = sv->c. ul;660 fc = sv->c.i; 641 661 642 662 if(fc>=0) … … 646 666 fc=-fc; 647 667 } 648 649 v = fr & VT_VALMASK; 668 669 v = fr & VT_VALMASK; 650 670 if (fr & VT_LVAL || fr == VT_LOCAL) { 651 uint32_t base = 0xb; 671 uint32_t base = 0xb; /* fp */ 652 672 if(v < VT_CONST) { 653 673 base=intr(v); … … 657 677 v1.type.t = ft; 658 678 v1.r = fr&~VT_LVAL; 659 v1.c. ul = sv->c.ul;679 v1.c.i = sv->c.i; 660 680 v1.sym=sv->sym; 661 load(base=14, &v1); 681 load(TREG_LR, &v1); 682 base = 14; /* lr */ 662 683 fc=sign=0; 663 v=VT_LOCAL; 684 v=VT_LOCAL; 664 685 } 665 686 if(v == VT_LOCAL) { … … 668 689 #ifdef TCC_ARM_VFP 669 690 op=0xED000A00; /* fsts */ 670 if(!sign) 671 op|=0x800000; 672 if ((ft & VT_BTYPE) != VT_FLOAT) 691 if(!sign) 692 op|=0x800000; 693 if ((ft & VT_BTYPE) != VT_FLOAT) 673 694 op|=0x100; /* fsts -> fstd */ 674 695 o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16)); … … 700 721 if(!sign) 701 722 op|=0x800000; 702 if ((ft & VT_BTYPE) == VT_BYTE )723 if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) 703 724 op|=0x400000; 704 725 o(op|(intr(r)<<12)|fc|(base<<16)); … … 722 743 uint32_t x; 723 744 /* constant case */ 724 x=encbranch(ind,ind+vtop->c. ul,0);745 x=encbranch(ind,ind+vtop->c.i,0); 725 746 if(x) { 726 747 if (vtop->r & VT_SYM) { … … 736 757 if (vtop->r & VT_SYM) 737 758 greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32); 738 o(vtop->c. ul);759 o(vtop->c.i); 739 760 } 740 761 } else { … … 747 768 } 748 769 749 #ifdef TCC_ARM_HARDFLOAT 750 static int is_float_hgen_aggr(CType *type) 770 static int unalias_ldbl(int btype) 771 { 772 #if LDOUBLE_SIZE == 8 773 if (btype == VT_LDOUBLE) 774 btype = VT_DOUBLE; 775 #endif 776 return btype; 777 } 778 779 /* Return whether a structure is an homogeneous float aggregate or not. 780 The answer is true if all the elements of the structure are of the same 781 primitive float type and there is less than 4 elements. 782 783 type: the type corresponding to the structure to be tested */ 784 static int is_hgen_float_aggr(CType *type) 751 785 { 752 786 if ((type->t & VT_BTYPE) == VT_STRUCT) { … … 754 788 int btype, nb_fields = 0; 755 789 756 ref = type->ref ;757 btype = ref->type.t & VT_BTYPE;790 ref = type->ref->next; 791 btype = unalias_ldbl(ref->type.t & VT_BTYPE); 758 792 if (btype == VT_FLOAT || btype == VT_DOUBLE) { 759 for(; ref && btype == (ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);793 for(; ref && btype == unalias_ldbl(ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++); 760 794 return !ref && nb_fields <= 4; 761 795 } … … 765 799 766 800 struct avail_regs { 767 /* worst case: f(float, double, 3 float struct, double, 3 float struct, double) */ 768 signed char avail[3]; 769 int first_hole; 770 int last_hole; 771 int first_free_reg; 801 signed char avail[3]; /* 3 holes max with only float and double alignments */ 802 int first_hole; /* first available hole */ 803 int last_hole; /* last available hole (none if equal to first_hole) */ 804 int first_free_reg; /* next free register in the sequence, hole excluded */ 772 805 }; 773 806 774 807 #define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 } 775 808 776 /* Assign a register for a CPRC param with correct size and alignment 777 * size and align are in bytes, as returned by type_size */ 778 int assign_fpreg(struct avail_regs *avregs, int align, int size) 809 /* Find suitable registers for a VFP Co-Processor Register Candidate (VFP CPRC 810 param) according to the rules described in the procedure call standard for 811 the ARM architecture (AAPCS). If found, the registers are assigned to this 812 VFP CPRC parameter. Registers are allocated in sequence unless a hole exists 813 and the parameter is a single float. 814 815 avregs: opaque structure to keep track of available VFP co-processor regs 816 align: alignment constraints for the param, as returned by type_size() 817 size: size of the parameter, as returned by type_size() */ 818 int assign_vfpreg(struct avail_regs *avregs, int align, int size) 779 819 { 780 820 int first_reg = 0; … … 782 822 if (avregs->first_free_reg == -1) 783 823 return -1; 784 if (align >> 3) { / / alignment needed (base type: double)824 if (align >> 3) { /* double alignment */ 785 825 first_reg = avregs->first_free_reg; 826 /* alignment constraint not respected so use next reg and record hole */ 786 827 if (first_reg & 1) 787 828 avregs->avail[avregs->last_hole++] = first_reg++; 788 } else { 829 } else { /* no special alignment (float or array of float) */ 830 /* if single float and a hole is available, assign the param to it */ 789 831 if (size == 4 && avregs->first_hole != avregs->last_hole) 790 832 return avregs->avail[avregs->first_hole++]; … … 799 841 return -1; 800 842 } 801 #endif 802 803 /* Generate function call. The function address is pushed first, then 804 all the parameters in call order. This functions pops all the 805 parameters and the function address. */ 806 void gfunc_call(int nb_args) 807 { 808 int size, align, r, args_size, i, ncrn, ncprn, argno, vfp_argno; 809 signed char plan[4][2]={{-1,-1},{-1,-1},{-1,-1},{-1,-1}}; 810 SValue *before_stack = NULL; /* SValue before first on stack argument */ 811 SValue *before_vfpreg_hfa = NULL; /* SValue before first in VFP reg hfa argument */ 812 #ifdef TCC_ARM_HARDFLOAT 843 844 /* Returns whether all params need to be passed in core registers or not. 845 This is the case for function part of the runtime ABI. */ 846 int floats_in_core_regs(SValue *sval) 847 { 848 if (!sval->sym) 849 return 0; 850 851 switch (sval->sym->v) { 852 case TOK___floatundisf: 853 case TOK___floatundidf: 854 case TOK___fixunssfdi: 855 case TOK___fixunsdfdi: 856 #ifndef TCC_ARM_VFP 857 case TOK___fixunsxfdi: 858 #endif 859 case TOK___floatdisf: 860 case TOK___floatdidf: 861 case TOK___fixsfdi: 862 case TOK___fixdfdi: 863 return 1; 864 865 default: 866 return 0; 867 } 868 } 869 870 /* Return the number of registers needed to return the struct, or 0 if 871 returning via struct pointer. */ 872 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) { 873 #ifdef TCC_ARM_EABI 874 int size, align; 875 size = type_size(vt, &align); 876 if (float_abi == ARM_HARD_FLOAT && !variadic && 877 (is_float(vt->t) || is_hgen_float_aggr(vt))) { 878 *ret_align = 8; 879 *regsize = 8; 880 ret->ref = NULL; 881 ret->t = VT_DOUBLE; 882 return (size + 7) >> 3; 883 } else if (size <= 4) { 884 *ret_align = 4; 885 *regsize = 4; 886 ret->ref = NULL; 887 ret->t = VT_INT; 888 return 1; 889 } else 890 return 0; 891 #else 892 return 0; 893 #endif 894 } 895 896 /* Parameters are classified according to how they are copied to their final 897 destination for the function call. Because the copying is performed class 898 after class according to the order in the union below, it is important that 899 some constraints about the order of the members of this union are respected: 900 - CORE_STRUCT_CLASS must come after STACK_CLASS; 901 - CORE_CLASS must come after STACK_CLASS, CORE_STRUCT_CLASS and 902 VFP_STRUCT_CLASS; 903 - VFP_STRUCT_CLASS must come after VFP_CLASS. 904 See the comment for the main loop in copy_params() for the reason. */ 905 enum reg_class { 906 STACK_CLASS = 0, 907 CORE_STRUCT_CLASS, 908 VFP_CLASS, 909 VFP_STRUCT_CLASS, 910 CORE_CLASS, 911 NB_CLASSES 912 }; 913 914 struct param_plan { 915 int start; /* first reg or addr used depending on the class */ 916 int end; /* last reg used or next free addr depending on the class */ 917 SValue *sval; /* pointer to SValue on the value stack */ 918 struct param_plan *prev; /* previous element in this class */ 919 }; 920 921 struct plan { 922 struct param_plan *pplans; /* array of all the param plans */ 923 struct param_plan *clsplans[NB_CLASSES]; /* per class lists of param plans */ 924 }; 925 926 #define add_param_plan(plan,pplan,class) \ 927 do { \ 928 pplan.prev = plan->clsplans[class]; \ 929 plan->pplans[plan ## _nb] = pplan; \ 930 plan->clsplans[class] = &plan->pplans[plan ## _nb++]; \ 931 } while(0) 932 933 /* Assign parameters to registers and stack with alignment according to the 934 rules in the procedure call standard for the ARM architecture (AAPCS). 935 The overall assignment is recorded in an array of per parameter structures 936 called parameter plans. The parameter plans are also further organized in a 937 number of linked lists, one per class of parameter (see the comment for the 938 definition of union reg_class). 939 940 nb_args: number of parameters of the function for which a call is generated 941 float_abi: float ABI in use for this function call 942 plan: the structure where the overall assignment is recorded 943 todo: a bitmap that record which core registers hold a parameter 944 945 Returns the amount of stack space needed for parameter passing 946 947 Note: this function allocated an array in plan->pplans with tcc_malloc. It 948 is the responsibility of the caller to free this array once used (ie not 949 before copy_params). */ 950 static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo) 951 { 952 int i, size, align; 953 int ncrn /* next core register number */, nsaa /* next stacked argument address*/; 954 int plan_nb = 0; 955 struct param_plan pplan; 813 956 struct avail_regs avregs = AVAIL_REGS_INITIALIZER; 814 signed char vfp_plan[16]; 815 int plan2[4+16]; 816 int variadic; 817 #else 818 int plan2[4]={0,0,0,0}; 819 #endif 820 int vfp_todo=0; 821 int todo=0, keep; 822 823 #ifdef TCC_ARM_HARDFLOAT 824 memset(vfp_plan, -1, sizeof(vfp_plan)); 825 memset(plan2, 0, sizeof(plan2)); 826 variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); 827 #endif 828 r = vtop->r & VT_VALMASK; 829 if (r == VT_CMP || (r & ~1) == VT_JMP) 830 gv(RC_INT); 831 #ifdef TCC_ARM_EABI 832 if((vtop[-nb_args].type.ref->type.t & VT_BTYPE) == VT_STRUCT 833 && type_size(&vtop[-nb_args].type.ref->type, &align) <= 4) { 834 SValue tmp; 835 tmp=vtop[-nb_args]; 836 vtop[-nb_args]=vtop[-nb_args+1]; 837 vtop[-nb_args+1]=tmp; 838 --nb_args; 839 } 840 841 vpushi(0), nb_args++; 842 vtop->type.t = VT_LLONG; 843 #endif 844 ncrn = ncprn = argno = vfp_argno = args_size = 0; 845 /* Assign argument to registers and stack with alignment. 846 If, considering alignment constraints, enough registers of the correct type 847 (core or VFP) are free for the current argument, assign them to it, else 848 allocate on stack with correct alignment. Whenever a structure is allocated 849 in registers or on stack, it is always put on the stack at this stage. The 850 stack is divided in 3 zones. The zone are, from low addresses to high 851 addresses: structures to be loaded in core registers, structures to be 852 loaded in VFP registers, argument allocated to stack. SValue's representing 853 structures in the first zone are moved just after the SValue pointed by 854 before_vfpreg_hfa. SValue's representing structures in the second zone are 855 moved just after the SValue pointer by before_stack. */ 957 958 ncrn = nsaa = 0; 959 *todo = 0; 960 plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans)); 961 memset(plan->clsplans, 0, sizeof(plan->clsplans)); 856 962 for(i = nb_args; i-- ;) { 857 int j, assigned_vfpreg = 0; 858 size = type_size(&vtop[-i].type, &align); 963 int j, start_vfpreg = 0; 964 CType type = vtop[-i].type; 965 type.t &= ~VT_ARRAY; 966 size = type_size(&type, &align); 967 size = (size + 3) & ~3; 968 align = (align + 3) & ~3; 859 969 switch(vtop[-i].type.t & VT_BTYPE) { 860 970 case VT_STRUCT: … … 862 972 case VT_DOUBLE: 863 973 case VT_LDOUBLE: 864 #ifdef TCC_ARM_HARDFLOAT 865 if (!variadic) { 866 int hfa = 0; /* Homogeneous float aggregate */ 974 if (float_abi == ARM_HARD_FLOAT) { 975 int is_hfa = 0; /* Homogeneous float aggregate */ 867 976 868 977 if (is_float(vtop[-i].type.t) 869 || (hfa = is_float_hgen_aggr(&vtop[-i].type))) { 870 int end_reg; 871 872 assigned_vfpreg = assign_fpreg(&avregs, align, size); 873 end_reg = assigned_vfpreg + (size - 1) / 4; 874 if (assigned_vfpreg >= 0) { 875 vfp_plan[vfp_argno++]=TREG_F0 + assigned_vfpreg/2; 876 if (hfa) { 877 /* before_stack can only have been set because all core registers 878 are assigned, so no need to care about before_vfpreg_hfa if 879 before_stack is set */ 880 if (before_stack) { 881 vrote(&vtop[-i], &vtop[-i] - before_stack); 882 before_stack++; 883 } else if (!before_vfpreg_hfa) 884 before_vfpreg_hfa = &vtop[-i-1]; 885 for (j = assigned_vfpreg; j <= end_reg; j++) 886 vfp_todo|=(1<<j); 887 } 978 || (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) { 979 int end_vfpreg; 980 981 start_vfpreg = assign_vfpreg(&avregs, align, size); 982 end_vfpreg = start_vfpreg + ((size - 1) >> 2); 983 if (start_vfpreg >= 0) { 984 pplan = (struct param_plan) {start_vfpreg, end_vfpreg, &vtop[-i]}; 985 if (is_hfa) 986 add_param_plan(plan, pplan, VFP_STRUCT_CLASS); 987 else 988 add_param_plan(plan, pplan, VFP_CLASS); 888 989 continue; 889 } else { 890 if (!hfa) 891 vfp_argno++; 892 /* No need to update before_stack as no more hfa can be allocated in 893 VFP regs */ 894 if (!before_vfpreg_hfa) 895 before_vfpreg_hfa = &vtop[-i-1]; 990 } else 896 991 break; 897 }898 992 } 899 993 } 900 #endif 901 ncrn = (ncrn + (align-1)/4) & -(align/4); 902 size = (size + 3) & -4; 903 if (ncrn + size/4 <= 4 || (ncrn < 4 && assigned_vfpreg != -1)) { 904 /* Either there is HFA in VFP registers, or there is arguments on stack, 905 it cannot be both. Hence either before_stack already points after 906 the slot where the vtop[-i] SValue is moved, or before_stack will not 907 be used */ 908 if (before_vfpreg_hfa) { 909 vrote(&vtop[-i], &vtop[-i] - before_vfpreg_hfa); 910 before_vfpreg_hfa++; 911 } 994 ncrn = (ncrn + (align-1)/4) & ~((align/4) - 1); 995 if (ncrn + size/4 <= 4 || (ncrn < 4 && start_vfpreg != -1)) { 996 /* The parameter is allocated both in core register and on stack. As 997 * such, it can be of either class: it would either be the last of 998 * CORE_STRUCT_CLASS or the first of STACK_CLASS. */ 912 999 for (j = ncrn; j < 4 && j < ncrn + size / 4; j++) 913 todo|=(1<<j); 914 ncrn+=size/4; 915 if (ncrn > 4) { 916 args_size = (ncrn - 4) * 4; 917 if (!before_stack) 918 before_stack = &vtop[-i-1]; 919 } 920 } 921 else { 1000 *todo|=(1<<j); 1001 pplan = (struct param_plan) {ncrn, j, &vtop[-i]}; 1002 add_param_plan(plan, pplan, CORE_STRUCT_CLASS); 1003 ncrn += size/4; 1004 if (ncrn > 4) 1005 nsaa = (ncrn - 4) * 4; 1006 } else { 922 1007 ncrn = 4; 923 /* No need to set before_vfpreg_hfa if not set since there will no924 longer be any structure assigned to core registers */925 if (!before_stack)926 before_stack = &vtop[-i-1];927 1008 break; 928 1009 } 929 1010 continue; 930 1011 default: 931 #ifdef TCC_ARM_EABI932 if (!i) {933 break;934 }935 #endif936 1012 if (ncrn < 4) { 937 1013 int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG; … … 939 1015 if (is_long) { 940 1016 ncrn = (ncrn + 1) & -2; 941 if (ncrn == 4) { 942 argno++; 1017 if (ncrn == 4) 943 1018 break; 1019 } 1020 pplan = (struct param_plan) {ncrn, ncrn, &vtop[-i]}; 1021 ncrn++; 1022 if (is_long) 1023 pplan.end = ncrn++; 1024 add_param_plan(plan, pplan, CORE_CLASS); 1025 continue; 1026 } 1027 } 1028 nsaa = (nsaa + (align - 1)) & ~(align - 1); 1029 pplan = (struct param_plan) {nsaa, nsaa + size, &vtop[-i]}; 1030 add_param_plan(plan, pplan, STACK_CLASS); 1031 nsaa += size; /* size already rounded up before */ 1032 } 1033 return nsaa; 1034 } 1035 1036 #undef add_param_plan 1037 1038 /* Copy parameters to their final destination (core reg, VFP reg or stack) for 1039 function call. 1040 1041 nb_args: number of parameters the function take 1042 plan: the overall assignment plan for parameters 1043 todo: a bitmap indicating what core reg will hold a parameter 1044 1045 Returns the number of SValue added by this function on the value stack */ 1046 static int copy_params(int nb_args, struct plan *plan, int todo) 1047 { 1048 int size, align, r, i, nb_extra_sval = 0; 1049 struct param_plan *pplan; 1050 int pass = 0; 1051 1052 /* Several constraints require parameters to be copied in a specific order: 1053 - structures are copied to the stack before being loaded in a reg; 1054 - floats loaded to an odd numbered VFP reg are first copied to the 1055 preceding even numbered VFP reg and then moved to the next VFP reg. 1056 1057 It is thus important that: 1058 - structures assigned to core regs must be copied after parameters 1059 assigned to the stack but before structures assigned to VFP regs because 1060 a structure can lie partly in core registers and partly on the stack; 1061 - parameters assigned to the stack and all structures be copied before 1062 parameters assigned to a core reg since copying a parameter to the stack 1063 require using a core reg; 1064 - parameters assigned to VFP regs be copied before structures assigned to 1065 VFP regs as the copy might use an even numbered VFP reg that already 1066 holds part of a structure. */ 1067 again: 1068 for(i = 0; i < NB_CLASSES; i++) { 1069 for(pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) { 1070 1071 if (pass 1072 && (i != CORE_CLASS || pplan->sval->r < VT_CONST)) 1073 continue; 1074 1075 vpushv(pplan->sval); 1076 pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */ 1077 switch(i) { 1078 case STACK_CLASS: 1079 case CORE_STRUCT_CLASS: 1080 case VFP_STRUCT_CLASS: 1081 if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) { 1082 int padding = 0; 1083 size = type_size(&pplan->sval->type, &align); 1084 /* align to stack align size */ 1085 size = (size + 3) & ~3; 1086 if (i == STACK_CLASS && pplan->prev) 1087 padding = pplan->start - pplan->prev->end; 1088 size += padding; /* Add padding if any */ 1089 /* allocate the necessary size on stack */ 1090 gadd_sp(-size); 1091 /* generate structure store */ 1092 r = get_reg(RC_INT); 1093 o(0xE28D0000|(intr(r)<<12)|padding); /* add r, sp, padding */ 1094 vset(&vtop->type, r | VT_LVAL, 0); 1095 vswap(); 1096 vstore(); /* memcpy to current sp + potential padding */ 1097 1098 /* Homogeneous float aggregate are loaded to VFP registers 1099 immediately since there is no way of loading data in multiple 1100 non consecutive VFP registers as what is done for other 1101 structures (see the use of todo). */ 1102 if (i == VFP_STRUCT_CLASS) { 1103 int first = pplan->start, nb = pplan->end - first + 1; 1104 /* vpop.32 {pplan->start, ..., pplan->end} */ 1105 o(0xECBD0A00|(first&1)<<22|(first>>1)<<12|nb); 1106 /* No need to write the register used to a SValue since VFP regs 1107 cannot be used for gcall_or_jmp */ 1108 } 1109 } else { 1110 if (is_float(pplan->sval->type.t)) { 1111 #ifdef TCC_ARM_VFP 1112 r = vfpr(gv(RC_FLOAT)) << 12; 1113 if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) 1114 size = 4; 1115 else { 1116 size = 8; 1117 r |= 0x101; /* vpush.32 -> vpush.64 */ 1118 } 1119 o(0xED2D0A01 + r); /* vpush */ 1120 #else 1121 r = fpr(gv(RC_FLOAT)) << 12; 1122 if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) 1123 size = 4; 1124 else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE) 1125 size = 8; 1126 else 1127 size = LDOUBLE_SIZE; 1128 1129 if (size == 12) 1130 r |= 0x400000; 1131 else if(size == 8) 1132 r|=0x8000; 1133 1134 o(0xED2D0100|r|(size>>2)); /* some kind of vpush for FPA */ 1135 #endif 1136 } else { 1137 /* simple type (currently always same size) */ 1138 /* XXX: implicit cast ? */ 1139 size=4; 1140 if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { 1141 lexpand_nr(); 1142 size = 8; 1143 r = gv(RC_INT); 1144 o(0xE52D0004|(intr(r)<<12)); /* push r */ 1145 vtop--; 1146 } 1147 r = gv(RC_INT); 1148 o(0xE52D0004|(intr(r)<<12)); /* push r */ 1149 } 1150 if (i == STACK_CLASS && pplan->prev) 1151 gadd_sp(pplan->prev->end - pplan->start); /* Add padding if any */ 944 1152 } 1153 break; 1154 1155 case VFP_CLASS: 1156 gv(regmask(TREG_F0 + (pplan->start >> 1))); 1157 if (pplan->start & 1) { /* Must be in upper part of double register */ 1158 o(0xEEF00A40|((pplan->start>>1)<<12)|(pplan->start>>1)); /* vmov.f32 s(n+1), sn */ 1159 vtop->r = VT_CONST; /* avoid being saved on stack by gv for next float */ 1160 } 1161 break; 1162 1163 case CORE_CLASS: 1164 if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { 1165 lexpand_nr(); 1166 gv(regmask(pplan->end)); 1167 pplan->sval->r2 = vtop->r; 1168 vtop--; 1169 } 1170 gv(regmask(pplan->start)); 1171 /* Mark register as used so that gcall_or_jmp use another one 1172 (regs >=4 are free as never used to pass parameters) */ 1173 pplan->sval->r = vtop->r; 1174 break; 1175 } 1176 vtop--; 1177 } 1178 } 1179 1180 /* second pass to restore registers that were saved on stack by accident. 1181 Maybe redundant after the "lvalue_save" patch in tccgen.c:gv() */ 1182 if (++pass < 2) 1183 goto again; 1184 1185 /* Manually free remaining registers since next parameters are loaded 1186 * manually, without the help of gv(int). */ 1187 save_regs(nb_args); 1188 1189 if(todo) { 1190 o(0xE8BD0000|todo); /* pop {todo} */ 1191 for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) { 1192 int r; 1193 pplan->sval->r = pplan->start; 1194 /* An SValue can only pin 2 registers at best (r and r2) but a structure 1195 can occupy more than 2 registers. Thus, we need to push on the value 1196 stack some fake parameter to have on SValue for each registers used 1197 by a structure (r2 is not used). */ 1198 for (r = pplan->start + 1; r <= pplan->end; r++) { 1199 if (todo & (1 << r)) { 1200 nb_extra_sval++; 1201 vpushi(0); 1202 vtop->r = r; 945 1203 } 946 plan[argno++][0]=ncrn++; 947 if (is_long) { 948 plan[argno-1][1]=ncrn++; 949 } 950 continue; 951 } 952 argno++; 953 } 1204 } 1205 } 1206 } 1207 return nb_extra_sval; 1208 } 1209 1210 /* Generate function call. The function address is pushed first, then 1211 all the parameters in call order. This functions pops all the 1212 parameters and the function address. */ 1213 void gfunc_call(int nb_args) 1214 { 1215 int r, args_size; 1216 int def_float_abi = float_abi; 1217 int todo; 1218 struct plan plan; 1219 954 1220 #ifdef TCC_ARM_EABI 955 if(args_size & (align-1)) { 956 vpushi(0); 957 vtop->type.t = VT_VOID; /* padding */ 958 vrott(i+2); 959 args_size += 4; 960 nb_args++; 961 argno++; 962 } 963 #endif 964 args_size += (size + 3) & -4; 965 } 1221 int variadic; 1222 1223 if (float_abi == ARM_HARD_FLOAT) { 1224 variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS); 1225 if (variadic || floats_in_core_regs(&vtop[-nb_args])) 1226 float_abi = ARM_SOFTFP_FLOAT; 1227 } 1228 #endif 1229 /* cannot let cpu flags if other instruction are generated. Also avoid leaving 1230 VT_JMP anywhere except on the top of the stack because it would complicate 1231 the code generator. */ 1232 r = vtop->r & VT_VALMASK; 1233 if (r == VT_CMP || (r & ~1) == VT_JMP) 1234 gv(RC_INT); 1235 1236 args_size = assign_regs(nb_args, float_abi, &plan, &todo); 1237 966 1238 #ifdef TCC_ARM_EABI 967 vtop--, nb_args--; 968 #endif 969 args_size = keep = 0; 970 for(i = 0;i < nb_args; i++) { 971 vrotb(keep+1); 972 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { 973 size = type_size(&vtop->type, &align); 974 /* align to stack align size */ 975 size = (size + 3) & -4; 976 /* allocate the necessary size on stack */ 977 gadd_sp(-size); 978 /* generate structure store */ 979 r = get_reg(RC_INT); 980 o(0xE1A0000D|(intr(r)<<12)); 981 vset(&vtop->type, r | VT_LVAL, 0); 982 vswap(); 983 vstore(); 984 vtop--; 985 args_size += size; 986 } else if (is_float(vtop->type.t)) { 987 #ifdef TCC_ARM_HARDFLOAT 988 if (!variadic && --vfp_argno<16 && vfp_plan[vfp_argno]!=-1) { 989 plan2[keep++]=vfp_plan[vfp_argno]; 990 continue; 991 } 992 #endif 993 #ifdef TCC_ARM_VFP 994 r=vfpr(gv(RC_FLOAT))<<12; 995 size=4; 996 if ((vtop->type.t & VT_BTYPE) != VT_FLOAT) 997 { 998 size=8; 999 r|=0x101; /* fstms -> fstmd */ 1000 } 1001 o(0xED2D0A01+r); 1002 #else 1003 r=fpr(gv(RC_FLOAT))<<12; 1004 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) 1005 size = 4; 1006 else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) 1007 size = 8; 1008 else 1009 size = LDOUBLE_SIZE; 1010 1011 if (size == 12) 1012 r|=0x400000; 1013 else if(size == 8) 1014 r|=0x8000; 1015 1016 o(0xED2D0100|r|(size>>2)); 1017 #endif 1018 vtop--; 1019 args_size += size; 1020 } else { 1021 int s; 1022 /* simple type (currently always same size) */ 1023 /* XXX: implicit cast ? */ 1024 size=4; 1025 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) { 1026 lexpand_nr(); 1027 s=-1; 1028 if(--argno<4 && plan[argno][1]!=-1) 1029 s=plan[argno][1]; 1030 argno++; 1031 size = 8; 1032 if(s==-1) { 1033 r = gv(RC_INT); 1034 o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */ 1035 vtop--; 1036 } else { 1037 size=0; 1038 plan2[keep]=s; 1039 keep++; 1040 vswap(); 1041 } 1042 } 1043 s=-1; 1044 if(--argno<4 && plan[argno][0]!=-1) 1045 s=plan[argno][0]; 1046 #ifdef TCC_ARM_EABI 1047 if(vtop->type.t == VT_VOID) { 1048 if(s == -1) 1049 o(0xE24DD004); /* sub sp,sp,#4 */ 1050 vtop--; 1051 } else 1052 #endif 1053 if(s == -1) { 1054 r = gv(RC_INT); 1055 o(0xE52D0004|(intr(r)<<12)); /* str r,[sp,#-4]! */ 1056 vtop--; 1057 } else { 1058 size=0; 1059 plan2[keep]=s; 1060 keep++; 1061 } 1062 args_size += size; 1063 } 1064 } 1065 for(i = 0; i < keep; i++) { 1066 vrotb(keep); 1067 gv(regmask(plan2[i])); 1068 #ifdef TCC_ARM_HARDFLOAT 1069 /* arg is in s(2d+1): plan2[i]<plan2[i+1] => alignment occured (ex f,d,f) */ 1070 if (i < keep - 1 && is_float(vtop->type.t) && (plan2[i] <= plan2[i + 1])) { 1071 o(0xEEF00A40|(vfpr(plan2[i])<<12)|vfpr(plan2[i])); 1072 } 1073 #endif 1074 } 1075 save_regs(keep); /* save used temporary registers */ 1076 keep++; 1077 if(ncrn) { 1078 int nb_regs=0; 1079 if (ncrn>4) 1080 ncrn=4; 1081 todo&=((1<<ncrn)-1); 1082 if(todo) { 1083 int i; 1084 o(0xE8BD0000|todo); 1085 for(i=0;i<4;i++) 1086 if(todo&(1<<i)) { 1087 vpushi(0); 1088 vtop->r=i; 1089 keep++; 1090 nb_regs++; 1091 } 1092 } 1093 args_size-=nb_regs*4; 1094 } 1095 if(vfp_todo) { 1096 int nb_fregs=0; 1097 1098 for(i=0;i<16;i++) 1099 if(vfp_todo&(1<<i)) { 1100 o(0xED9D0A00|(i&1)<<22|(i>>1)<<12|nb_fregs); 1101 vpushi(0); 1102 /* There might be 2 floats in a double VFP reg but that doesn't seem 1103 to matter */ 1104 if (!(i%2)) 1105 vtop->r=TREG_F0+i/2; 1106 keep++; 1107 nb_fregs++; 1108 } 1109 if (nb_fregs) { 1110 gadd_sp(nb_fregs*4); 1111 args_size-=nb_fregs*4; 1112 } 1113 } 1114 vrotb(keep); 1239 if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */ 1240 args_size = (args_size + 7) & ~7; 1241 o(0xE24DD004); /* sub sp, sp, #4 */ 1242 } 1243 #endif 1244 1245 nb_args += copy_params(nb_args, &plan, todo); 1246 tcc_free(plan.pplans); 1247 1248 /* Move fct SValue on top as required by gcall_or_jmp */ 1249 vrotb(nb_args + 1); 1115 1250 gcall_or_jmp(0); 1116 1251 if (args_size) 1117 gadd_sp(args_size); 1118 #ifdef TCC_ARM_EABI 1119 if((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT 1120 && type_size(&vtop->type.ref->type, &align) <= 4) 1121 { 1122 store(REG_IRET,vtop-keep); 1123 ++keep; 1124 } 1125 #ifdef TCC_ARM_VFP 1126 #ifdef TCC_ARM_HARDFLOAT 1127 else if(variadic && is_float(vtop->type.ref->type.t)) { 1128 #else 1129 else if(is_float(vtop->type.ref->type.t)) { 1130 #endif 1252 gadd_sp(args_size); /* pop all parameters passed on the stack */ 1253 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) 1254 if(float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) { 1131 1255 if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) { 1132 o(0xEE000A10); /* fmsr s0,r0 */1256 o(0xEE000A10); /*vmov s0, r0 */ 1133 1257 } else { 1134 o(0xEE000B10); /* fmdlr d0,r0 */1135 o(0xEE201B10); /* fmdhr d0,r1 */1136 } 1137 } 1138 #endif 1139 #endif 1140 vtop-=keep;1141 leaffunc = 0;1258 o(0xEE000B10); /* vmov.32 d0[0], r0 */ 1259 o(0xEE201B10); /* vmov.32 d0[1], r1 */ 1260 } 1261 } 1262 #endif 1263 vtop -= nb_args + 1; /* Pop all params and fct address from value stack */ 1264 leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */ 1265 float_abi = def_float_abi; 1142 1266 } 1143 1267 … … 1146 1270 { 1147 1271 Sym *sym,*sym2; 1148 int n,nf,size,align, variadic, struct_ret = 0; 1149 #ifdef TCC_ARM_HARDFLOAT 1272 int n, nf, size, align, rs, struct_ret = 0; 1273 int addr, pn, sn; /* pn=core, sn=stack */ 1274 CType ret_type; 1275 1276 #ifdef TCC_ARM_EABI 1150 1277 struct avail_regs avregs = AVAIL_REGS_INITIALIZER; 1151 1278 #endif … … 1153 1280 sym = func_type->ref; 1154 1281 func_vt = sym->type; 1282 func_var = (func_type->ref->f.func_type == FUNC_ELLIPSIS); 1155 1283 1156 1284 n = nf = 0; 1157 variadic = (func_type->ref->c == FUNC_ELLIPSIS); 1158 if((func_vt.t & VT_BTYPE) == VT_STRUCT 1159 && type_size(&func_vt,&align) > 4) 1285 if ((func_vt.t & VT_BTYPE) == VT_STRUCT && 1286 !gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs)) 1160 1287 { 1161 1288 n++; … … 1163 1290 func_vc = 12; /* Offset from fp of the place to store the result */ 1164 1291 } 1165 for(sym2 =sym->next;sym2 && (n<4 || nf<16);sym2=sym2->next) {1292 for(sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) { 1166 1293 size = type_size(&sym2->type, &align); 1167 #ifdef TCC_ARM_HARDFLOAT 1168 if (!variadic && (is_float(sym2->type.t) 1169 || is_float_hgen_aggr(&sym2->type))) { 1170 int tmpnf = assign_fpreg(&avregs, align, size) + 1; 1294 #ifdef TCC_ARM_EABI 1295 if (float_abi == ARM_HARD_FLOAT && !func_var && 1296 (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) { 1297 int tmpnf = assign_vfpreg(&avregs, align, size); 1298 tmpnf += (size + 3) / 4; 1171 1299 nf = (tmpnf > nf) ? tmpnf : nf; 1172 1300 } else … … 1176 1304 } 1177 1305 o(0xE1A0C00D); /* mov ip,sp */ 1178 if (variadic)1306 if (func_var) 1179 1307 n=4; 1180 if (n) {1308 if (n) { 1181 1309 if(n>4) 1182 1310 n=4; … … 1195 1323 o(0xE1A0B00D); /* mov fp, sp */ 1196 1324 func_sub_sp_offset = ind; 1197 o(0xE1A00000); /* nop, leave space for stack adjustment in epilog ue*/1198 { 1199 int addr, pn = struct_ret, sn = 0; /* pn=core, sn=stack */ 1200 1201 #ifdef TCC_ARM_HARDFLOAT 1325 o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */ 1326 1327 #ifdef TCC_ARM_EABI 1328 if (float_abi == ARM_HARD_FLOAT) { 1329 func_vc += nf * 4; 1202 1330 avregs = AVAIL_REGS_INITIALIZER; 1203 #endif 1204 while ((sym = sym->next)) { 1205 CType *type; 1206 type = &sym->type; 1207 size = type_size(type, &align); 1208 size = (size + 3) >> 2; 1209 align = (align + 3) & ~3; 1210 #ifdef TCC_ARM_HARDFLOAT 1211 if (!variadic && (is_float(sym->type.t) 1212 || is_float_hgen_aggr(&sym->type))) { 1213 int fpn = assign_fpreg(&avregs, align, size << 2); 1214 if (fpn >= 0) { 1215 addr = fpn * 4; 1216 } else 1217 goto from_stack; 1218 } else 1219 #endif 1220 if (pn < 4) { 1331 } 1332 #endif 1333 pn = struct_ret, sn = 0; 1334 while ((sym = sym->next)) { 1335 CType *type; 1336 type = &sym->type; 1337 size = type_size(type, &align); 1338 size = (size + 3) >> 2; 1339 align = (align + 3) & ~3; 1340 #ifdef TCC_ARM_EABI 1341 if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym->type.t) 1342 || is_hgen_float_aggr(&sym->type))) { 1343 int fpn = assign_vfpreg(&avregs, align, size << 2); 1344 if (fpn >= 0) 1345 addr = fpn * 4; 1346 else 1347 goto from_stack; 1348 } else 1349 #endif 1350 if (pn < 4) { 1221 1351 #ifdef TCC_ARM_EABI 1222 1352 pn = (pn + (align-1)/4) & -(align/4); 1223 1353 #endif 1224 1225 1226 1227 1228 1229 #ifdef TCC_ARM_ HARDFLOAT1354 addr = (nf + pn) * 4; 1355 pn += size; 1356 if (!sn && pn > 4) 1357 sn = (pn - 4); 1358 } else { 1359 #ifdef TCC_ARM_EABI 1230 1360 from_stack: 1231 #endif1232 #ifdef TCC_ARM_EABI1233 1361 sn = (sn + (align-1)/4) & -(align/4); 1234 1362 #endif 1235 1236 1237 1238 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr+12);1239 }1363 addr = (n + nf + sn) * 4; 1364 sn += size; 1365 } 1366 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), 1367 addr + 12); 1240 1368 } 1241 1369 last_itod_magic=0; … … 1249 1377 uint32_t x; 1250 1378 int diff; 1251 #ifdef TCC_ARM_EABI 1252 /* Useless but harmless copy of the float result into main register(s) in case1253 of variadic function in the hardfloat variant */ 1254 if (is_float(func_vt.t)) {1379 /* Copy float return value to core register if base standard is used and 1380 float computation is made with VFP */ 1381 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) 1382 if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) { 1255 1383 if((func_vt.t & VT_BTYPE) == VT_FLOAT) 1256 1384 o(0xEE100A10); /* fmrs r0, s0 */ … … 1287 1415 { 1288 1416 int r; 1417 if (nocode_wanted) 1418 return t; 1289 1419 r=ind; 1290 1420 o(0xE0000000|encbranch(r,t,1)); … … 1303 1433 int v, r; 1304 1434 uint32_t op; 1435 1305 1436 v = vtop->r & VT_VALMASK; 1306 1437 r=ind; 1307 if (v == VT_CMP) { 1438 1439 if (nocode_wanted) { 1440 ; 1441 } else if (v == VT_CMP) { 1308 1442 op=mapcc(inv?negcc(vtop->c.i):vtop->c.i); 1309 1443 op|=encbranch(r,t,1); … … 1332 1466 gsym(vtop->c.i); 1333 1467 } 1334 } else {1335 if (is_float(vtop->type.t)) {1336 r=gv(RC_FLOAT);1337 #ifdef TCC_ARM_VFP1338 o(0xEEB50A40|(vfpr(r)<<12)|T2CPR(vtop->type.t)); /* fcmpzX */1339 o(0xEEF1FA10); /* fmstat */1340 #else1341 o(0xEE90F118|(fpr(r)<<16));1342 #endif1343 vtop->r = VT_CMP;1344 vtop->c.i = TOK_NE;1345 return gtst(inv, t);1346 } else if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {1347 /* constant jmp optimization */1348 if ((vtop->c.i != 0) != inv)1349 t = gjmp(t);1350 } else {1351 v = gv(RC_INT);1352 o(0xE3300000|(intr(v)<<16));1353 vtop->r = VT_CMP;1354 vtop->c.i = TOK_NE;1355 return gtst(inv, t);1356 }1357 1468 } 1358 1469 vtop--; … … 1543 1654 1544 1655 /* generate a floating point operation 'v = t1 op t2' instruction. The 1545 * two operands are guarante d to have the same floating point type */1656 * two operands are guaranteed to have the same floating point type */ 1546 1657 void gen_opf(int op) 1547 1658 { … … 1612 1723 case TOK_UGT: op=TOK_GT; break; 1613 1724 } 1614 1725 1615 1726 vtop->r = VT_CMP; 1616 1727 vtop->c.i = op; … … 1673 1784 1674 1785 /* generate a floating point operation 'v = t1 op t2' instruction. The 1675 two operands are guarante d to have the same floating point type */1786 two operands are guaranteed to have the same floating point type */ 1676 1787 void gen_opf(int op) 1677 1788 { … … 1763 1874 vswap(); 1764 1875 r2=fpr(gv(RC_FLOAT)); 1765 } 1876 } 1766 1877 break; 1767 1878 default: … … 1775 1886 case TOK_ULE: 1776 1887 case TOK_UGT: 1777 tcc_error("unsigned comparis ion on floats?");1888 tcc_error("unsigned comparison on floats?"); 1778 1889 break; 1779 1890 case TOK_LT: … … 2000 2111 } 2001 2112 2113 /* Save the stack pointer onto the stack and return the location of its address */ 2114 ST_FUNC void gen_vla_sp_save(int addr) { 2115 SValue v; 2116 v.type.t = VT_PTR; 2117 v.r = VT_LOCAL | VT_LVAL; 2118 v.c.i = addr; 2119 store(TREG_SP, &v); 2120 } 2121 2122 /* Restore the SP from a location on the stack */ 2123 ST_FUNC void gen_vla_sp_restore(int addr) { 2124 SValue v; 2125 v.type.t = VT_PTR; 2126 v.r = VT_LOCAL | VT_LVAL; 2127 v.c.i = addr; 2128 load(TREG_SP, &v); 2129 } 2130 2131 /* Subtract from the stack pointer, and push the resulting value onto the stack */ 2132 ST_FUNC void gen_vla_alloc(CType *type, int align) { 2133 int r = intr(gv(RC_INT)); 2134 o(0xE04D0000|(r<<12)|r); /* sub r, sp, r */ 2135 #ifdef TCC_ARM_EABI 2136 if (align < 8) 2137 align = 8; 2138 #else 2139 if (align < 4) 2140 align = 4; 2141 #endif 2142 if (align & (align - 1)) 2143 tcc_error("alignment is not a power of 2: %i", align); 2144 o(stuff_const(0xE3C0D000|(r<<16), align - 1)); /* bic sp, r, #align-1 */ 2145 vpop(); 2146 } 2147 2002 2148 /* end of ARM code generator */ 2003 2149 /*************************************************************/ -
EcnlProtoTool/trunk/tcc-0.9.27/c67-gen.c
r321 r331 21 21 #ifdef TARGET_DEFS_ONLY 22 22 23 / /#define ASSEMBLY_LISTING_C6723 /* #define ASSEMBLY_LISTING_C67 */ 24 24 25 25 /* number of available registers */ … … 94 94 95 95 /* defined if function parameters must be evaluated in reverse order */ 96 / /#define INVERT_FUNC_PARAMS96 /* #define INVERT_FUNC_PARAMS */ 97 97 98 98 /* defined if structures are passed as pointers. Otherwise structures 99 99 are directly pushed on stack. */ 100 / /#define FUNC_STRUCT_PARAM_AS_PTR100 /* #define FUNC_STRUCT_PARAM_AS_PTR */ 101 101 102 102 /* pointer size, in bytes */ … … 108 108 /* maximum alignment (for aligned attribute support) */ 109 109 #define MAX_ALIGN 8 110 111 /******************************************************/112 /* ELF defines */113 114 #define EM_TCC_TARGET EM_C60115 116 /* relocation type for 32 bit data relocation */117 #define R_DATA_32 R_C60_32118 #define R_DATA_PTR R_C60_32119 #define R_JMP_SLOT R_C60_JMP_SLOT120 #define R_COPY R_C60_COPY121 122 #define ELF_START_ADDR 0x00000400123 #define ELF_PAGE_SIZE 0x1000124 110 125 111 /******************************************************/ … … 197 183 { 198 184 int ind1; 199 185 if (nocode_wanted) 186 return; 200 187 #ifdef ASSEMBLY_LISTING_C67 201 188 fprintf(f, " %08X", c); … … 246 233 247 234 // these are regs that tcc doesn't really know about, 248 // but as ign them unique values so the mapping routines249 // can distin quish them235 // but assign them unique values so the mapping routines 236 // can distinguish them 250 237 251 238 #define C67_A0 105 … … 254 241 #define C67_FP 108 255 242 #define C67_B2 109 256 #define C67_CREG_ZERO -1 / / Special code for no condition reg test243 #define C67_CREG_ZERO -1 /* Special code for no condition reg test */ 257 244 258 245 … … 1568 1555 fr = sv->r; 1569 1556 ft = sv->type.t; 1570 fc = sv->c. ul;1557 fc = sv->c.i; 1571 1558 1572 1559 v = fr & VT_VALMASK; … … 1575 1562 v1.type.t = VT_INT; 1576 1563 v1.r = VT_LOCAL | VT_LVAL; 1577 v1.c. ul= fc;1564 v1.c.i = fc; 1578 1565 load(r, &v1); 1579 1566 fr = r; … … 1727 1714 1728 1715 ft = v->type.t; 1729 fc = v->c. ul;1716 fc = v->c.i; 1730 1717 fr = v->r & VT_VALMASK; 1731 1718 bt = ft & VT_BTYPE; … … 1880 1867 } 1881 1868 1869 /* Return the number of registers needed to return the struct, or 0 if 1870 returning via struct pointer. */ 1871 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) { 1872 *ret_align = 1; // Never have to re-align return values for x86-64 1873 return 0; 1874 } 1875 1882 1876 /* generate function call with address in (vtop->t, vtop->c) and free function 1883 1877 context. Stack entry is popped */ … … 1894 1888 for (i = 0; i < nb_args; i++) { 1895 1889 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { 1896 ALWAYS_ASSERT(FALSE);1897 } else if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {1898 1890 ALWAYS_ASSERT(FALSE); 1899 1891 } else { … … 1960 1952 1961 1953 sym = func_type->ref; 1962 func_call = sym-> r;1954 func_call = sym->f.func_call; 1963 1955 addr = 8; 1964 1956 /* if the function returns a structure, then add an 1965 1957 implicit pointer parameter */ 1966 1958 func_vt = sym->type; 1959 func_var = (sym->f.func_type == FUNC_ELLIPSIS); 1967 1960 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { 1968 1961 func_vc = addr; … … 2047 2040 { 2048 2041 int ind1 = ind; 2042 if (nocode_wanted) 2043 return t; 2049 2044 2050 2045 C67_MVKL(C67_A0, t); //r=reg to load, constant … … 2079 2074 2080 2075 v = vtop->r & VT_VALMASK; 2081 if (v == VT_CMP) { 2076 if (nocode_wanted) { 2077 ; 2078 } else if (v == VT_CMP) { 2082 2079 /* fast case : can jump directly since flags are set */ 2083 2080 // C67 uses B2 sort of as flags register … … 2101 2098 if ((v & 1) == inv) { 2102 2099 /* insert vtop->c jump list in t */ 2103 p = &vtop->c.i;2104 2100 2105 2101 // I guess the idea is to traverse to the … … 2107 2103 // there 2108 2104 2109 n = *p;2105 n = vtop->c.i; 2110 2106 while (n != 0) { 2111 2107 p = (int *) (cur_text_section->data + n); … … 2122 2118 t = gjmp(t); 2123 2119 gsym(vtop->c.i); 2124 }2125 } else {2126 if (is_float(vtop->type.t)) {2127 vpushi(0);2128 gen_op(TOK_NE);2129 }2130 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {2131 /* constant jmp optimization */2132 if ((vtop->c.i != 0) != inv)2133 t = gjmp(t);2134 } else {2135 // I think we need to get the value on the stack2136 // into a register, test it, and generate a branch2137 // return the address of the branch, so it can be2138 // later patched2139 2140 v = gv(RC_INT); // get value into a reg2141 ind1 = ind;2142 C67_MVKL(C67_A0, t); //r=reg to load, constant2143 C67_MVKH(C67_A0, t); //r=reg to load, constant2144 2145 if (v != TREG_EAX && // check if not already in a conditional test reg2146 v != TREG_EDX && v != TREG_ST0 && v != C67_B2) {2147 C67_MV(v, C67_B2);2148 v = C67_B2;2149 }2150 2151 C67_IREG_B_REG(inv, v, C67_A0); // [!R] B.S2x A02152 C67_NOP(5);2153 t = ind1; //return where we need to patch2154 ind1 = ind;2155 2120 } 2156 2121 } … … 2261 2226 fr = vtop[0].r; 2262 2227 vtop--; 2263 C67_MPYI(fr, r); // 32 bit bultiply fr,r,fr2228 C67_MPYI(fr, r); // 32 bit multiply fr,r,fr 2264 2229 C67_NOP(8); // NOP 8 for worst case 2265 2230 break; … … 2318 2283 2319 2284 /* generate a floating point operation 'v = t1 op t2' instruction. The 2320 two operands are guarante d to have the same floating point type */2285 two operands are guaranteed to have the same floating point type */ 2321 2286 /* XXX: need to use ST1 too */ 2322 2287 void gen_opf(int op) … … 2330 2295 2331 2296 ft = vtop->type.t; 2332 fc = vtop->c. ul;2297 fc = vtop->c.i; 2333 2298 r = vtop->r; 2334 2299 fr = vtop[-1].r; … … 2555 2520 } 2556 2521 2522 /* Save the stack pointer onto the stack and return the location of its address */ 2523 ST_FUNC void gen_vla_sp_save(int addr) { 2524 tcc_error("variable length arrays unsupported for this target"); 2525 } 2526 2527 /* Restore the SP from a location on the stack */ 2528 ST_FUNC void gen_vla_sp_restore(int addr) { 2529 tcc_error("variable length arrays unsupported for this target"); 2530 } 2531 2532 /* Subtract from the stack pointer, and push the resulting value onto the stack */ 2533 ST_FUNC void gen_vla_alloc(CType *type, int align) { 2534 tcc_error("variable length arrays unsupported for this target"); 2535 } 2536 2557 2537 /* end of C67 code generator */ 2558 2538 /*************************************************************/ -
EcnlProtoTool/trunk/tcc-0.9.27/coff.h
r321 r331 23 23 #define F_RELFLG 0x01 /* relocation info stripped from file */ 24 24 #define F_EXEC 0x02 /* file is executable (no unresolved refs) */ 25 #define F_LNNO 0x04 /* line nu nbers stripped from file */25 #define F_LNNO 0x04 /* line numbers stripped from file */ 26 26 #define F_LSYMS 0x08 /* local symbols stripped from file */ 27 27 #define F_GSP10 0x10 /* 34010 version */ … … 38 38 #define FILHDR struct filehdr 39 39 40 / /#define FILHSZ sizeof(FILHDR)41 #define FILHSZ 22 / / above rounds to align on 4 bytes which causes problems40 /* #define FILHSZ sizeof(FILHDR) */ 41 #define FILHSZ 22 /* above rounds to align on 4 bytes which causes problems */ 42 42 43 43 #define COFF_C67_MAGIC 0x00c2 … … 154 154 /* Define constants for names of "special" sections */ 155 155 /*------------------------------------------------------------------------*/ 156 / /#define _TEXT ".text"156 /* #define _TEXT ".text" */ 157 157 #define _DATA ".data" 158 158 #define _BSS ".bss" -
EcnlProtoTool/trunk/tcc-0.9.27/config.h
r321 r331 1 1 /* Automatically generated by configure - do not modify */ 2 2 #ifndef CONFIG_TCCDIR 3 # define CONFIG_TCCDIR " 0:/lib/tcc"3 # define CONFIG_TCCDIR "1:/lib" 4 4 #endif 5 #define GCC_MAJOR 6 #define GCC_MINOR 7 #define HOST_ARM 1 8 #define TCC_ARM_VERSION 7 9 #define TCC_VERSION "0.9.26" 10 #define CONFIG_TCC_STATIC 5 #define CONFIG_TCC_CRTPREFIX "1:/lib" 6 #define CONFIG_TCC_SYSINCLUDEPATHS "1:/include" 7 #define TCC_VERSION "0.9.27" -
EcnlProtoTool/trunk/tcc-0.9.27/config.mak
r279 r331 1 1 # Automatically generated by configure - do not modify 2 prefix=0: 3 bindir=$(DESTDIR)0:/bin 4 tccdir=$(DESTDIR)0:/lib/tcc 5 libdir=$(DESTDIR)0:/lib 6 ln_libdir=0:/lib 7 includedir=$(DESTDIR)0:/include 8 mandir=$(DESTDIR)0:/share/man 9 infodir=$(DESTDIR)0:/share/info 10 docdir=$(DESTDIR)0:/share/doc/tcc 2 prefix=1: 3 bindir=$(DESTDIR)1: 4 tccdir=$(DESTDIR)1: 5 libdir=$(DESTDIR)1:/libtcc 6 includedir=$(DESTDIR) 7 mandir=$(DESTDIR) 8 infodir=$(DESTDIR) 9 docdir=$(DESTDIR)1:/doc 11 10 CC=arm-none-eabi-gcc 12 GCC_MAJOR= 13 GCC_MINOR= 14 HOST_CC=gcc 11 GCC_MAJOR=0 12 GCC_MINOR=0 15 13 AR=arm-none-eabi-ar 16 14 STRIP=arm-none-eabi-strip -s -R .comment -R .note 17 CFLAGS=-Wall -g -O 218 LDFLAGS= 15 CFLAGS=-Wall -g -Og -nostdinc -I$(TOP)/../musl-1.1.18/include -mcpu=cortex-a9 -march=armv7-a -mlittle-endian -marm -mthumb-interwork -mfloat-abi=hard -mfpu=vfp -Dtcc_main=main -Wdeclaration-after-statement -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result 16 LDFLAGS=-Wl,-e_start_c -nostdlib $(TOP)/../musl-1.1.18/lib/crtn.o $(TOP)/../musl-1.1.18/lib/crti.o $(TOP)/../musl-1.1.18/lib/rcrt1.o -L$(TOP)/../musl-1.1.18/lib -L. -lc -lgcc 19 17 LIBSUF=.a 20 EXESUF= 18 EXESUF=.elf 19 DLLSUF=.so 20 NATIVE_DEFINES+=-DTCC_CPU_VERSION=7 21 21 ARCH=arm 22 22 TARGETOS= 23 VERSION=0.9.26 24 SRC_PATH=. 25 top_srcdir=$(TOP) 26 top_builddir=$(TOP)27 CONFIG_NOLDL=yes23 #CONFIG_libgcc=yes 24 CONFIG_musl=yes 25 VERSION = 0.9.27 26 TOPSRC=$(TOP) 27 arm-libtcc1-usegcc=yes -
EcnlProtoTool/trunk/tcc-0.9.27/config.texi
r279 r331 1 @set VERSION 0.9.2 61 @set VERSION 0.9.27 -
EcnlProtoTool/trunk/tcc-0.9.27/configure
r279 r331 18 18 19 19 # default parameters 20 build_cross="no"21 use_libgcc="no"22 20 prefix="" 23 21 execprefix="" … … 31 29 cross_prefix="" 32 30 cc="gcc" 33 host_cc="gcc"34 31 ar="ar" 35 32 strip="strip" 36 cygwin="no"37 gprof="no"38 33 bigendian="no" 39 34 mingw32="no" 40 35 LIBSUF=".a" 41 36 EXESUF="" 37 DLLSUF=".so" 42 38 tcc_sysincludepaths="" 43 39 tcc_libpaths="" 44 40 tcc_crtprefix="" 45 41 tcc_elfinterp="" 42 triplet= 46 43 tcc_lddir= 47 44 confvars= 48 49 #cpu=`uname -m` 50 cpu="armv7a" 45 suggest="yes" 46 cpu= 47 cpuver= 48 gcc_major=0 49 gcc_minor=0 51 50 52 51 # OS specific 53 #targetos=`uname -s` 54 targetos="" 52 targetos=`uname` 55 53 case $targetos in 56 MINGW32*) mingw32=yes;; 57 DragonFly) noldl=yes;; 58 OpenBSD) noldl=yes;; 59 *) ;; 54 Darwin) 55 confvars="$confvars OSX" 56 DLLSUF=".dylib" 57 ;; 58 MINGW*|MSYS*|CYGWIN*) 59 mingw32=yes 60 ;; 61 DragonFly|OpenBSD|FreeBSD|NetBSD) 62 confvars="$confvars ldl=no" 63 ;; 64 *) 65 ;; 60 66 esac 61 67 62 68 # find source path 63 # XXX: we assume an absolute path is given when launching configure,64 # except in './configure' case.65 69 source_path=${0%configure} 66 70 source_path=${source_path%/} … … 71 75 fi 72 76 73 case "$cpu" in74 i386|i486|i586|i686|i86pc|BePC|i686-AT386)75 cpu="x86"76 ;;77 x86_64)78 cpu="x86-64"79 ;;80 arm*)81 case "$cpu" in82 arm|armv4l)83 cpuver=484 ;;85 armv5tel|armv5tejl)86 cpuver=587 ;;88 armv6j|armv6l)89 cpuver=690 ;;91 armv7a|armv7l)92 cpuver=793 ;;94 esac95 cpu="armv4l"96 ;;97 alpha)98 cpu="alpha"99 ;;100 "Power Macintosh"|ppc|ppc64)101 cpu="powerpc"102 ;;103 mips)104 cpu="mips"105 ;;106 s390)107 cpu="s390"108 ;;109 *)110 cpu="unknown"111 ;;112 esac113 114 77 for opt do 115 78 eval opt=\"$opt\" … … 143 106 --cc=*) cc=`echo $opt | cut -d '=' -f 2` 144 107 ;; 108 --ar=*) ar=`echo $opt | cut -d '=' -f 2` 109 ;; 145 110 --extra-cflags=*) CFLAGS="${opt#--extra-cflags=}" 146 111 ;; 147 112 --extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}" 148 113 ;; 149 --extra-libs=*) extralibs= ${opt#--extra-libs=}114 --extra-libs=*) extralibs="${opt#--extra-libs=}" 150 115 ;; 151 116 --sysincludepaths=*) tcc_sysincludepaths=`echo $opt | cut -d '=' -f 2` … … 157 122 --elfinterp=*) tcc_elfinterp=`echo $opt | cut -d '=' -f 2` 158 123 ;; 124 --triplet=*) triplet=`echo $opt | cut -d '=' -f 2` 125 ;; 159 126 --cpu=*) cpu=`echo $opt | cut -d '=' -f 2` 160 127 ;; 161 --enable- gprof) gprof="yes"162 ;; 163 -- enable-mingw32) mingw32="yes" ; cross_prefix="i686-pc-mingw32-" ; cpu=x86164 ;; 165 --enable- cygwin) mingw32="yes" ; cygwin="yes" ; cross_prefix="mingw32-" ; cpu=x86166 ;; 167 -- enable-cross) build_cross="yes"168 ;; 169 -- disable-static) disable_static="yes"170 ;; 171 -- disable-rpath) disable_rpath="yes"172 ;; 173 -- strip-binaries) strip_binaries="yes"174 ;; 175 -- with-libgcc) use_libgcc="yes"176 ;; 177 -- with-selinux) have_selinux="yes"128 --enable-cross) confvars="$confvars cross" 129 ;; 130 --disable-static) confvars="$confvars static=no" 131 ;; 132 --enable-static) confvars="$confvars static" 133 ;; 134 --disable-rpath) confvars="$confvars rpath=no" 135 ;; 136 --strip-binaries) confvars="$confvars strip" 137 ;; 138 --with-libgcc) confvars="$confvars libgcc" 139 ;; 140 --with-selinux) confvars="$confvars selinux" 141 ;; 142 --config-mingw32*) mingw32=$(echo "$opt=yes" | cut -d '=' -f 2) 143 ;; 144 --config-*) confvars="$confvars ${opt#--config-}"; suggest="no" 178 145 ;; 179 146 --help|-h) show_help="yes" … … 183 150 esac 184 151 done 152 153 if test -z "$cpu" ; then 154 if test -n "$ARCH" ; then 155 cpu="$ARCH" 156 else 157 cpu=`uname -m` 158 fi 159 fi 160 161 case "$cpu" in 162 x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386) 163 cpu="i386" 164 ;; 165 x86_64|amd64|x86-64) 166 cpu="x86_64" 167 ;; 168 arm*) 169 case "$cpu" in 170 arm|armv4l) 171 cpuver=4 172 ;; 173 armv5tel|armv5tejl) 174 cpuver=5 175 ;; 176 armv6j|armv6l) 177 cpuver=6 178 ;; 179 armv7a|armv7l) 180 cpuver=7 181 ;; 182 esac 183 cpu="arm" 184 ;; 185 aarch64) 186 cpu="aarch64" 187 ;; 188 alpha) 189 cpu="alpha" 190 ;; 191 "Power Macintosh"|ppc|ppc64) 192 cpu="ppc" 193 ;; 194 mips) 195 cpu="mips" 196 ;; 197 s390) 198 cpu="s390" 199 ;; 200 *) 201 echo "Unsupported CPU" 202 exit 1 203 ;; 204 esac 185 205 186 206 # Checking for CFLAGS … … 190 210 191 211 if test "$mingw32" = "yes" ; then 192 if test x"$tccdir" = x""; then 193 tccdir="tcc" 194 fi 195 if test -z "$prefix" ; then 196 prefix="C:/Program Files/${tccdir}" 197 fi 198 if test -z "$sharedir" ; then 199 sharedir="${prefix}" 200 fi 201 execprefix="$prefix" 202 bindir="${prefix}" 203 tccdir="${prefix}" 204 libdir="${prefix}/lib" 205 docdir="${sharedir}/doc" 206 mandir="${sharedir}/man" 207 infodir="${sharedir}/info" 212 if test "$source_path_used" = "no"; then 213 source_path="." 214 fi 215 if test "$cc" = gcc; then 216 test -z "$LDFLAGS" && LDFLAGS="-static" 217 fi 218 test -z "$prefix" && prefix="C:/Program Files/tcc" 219 test -z "$tccdir" && tccdir="${prefix}" 220 test -z "$bindir" && bindir="${tccdir}" 221 test -z "$docdir" && docdir="${tccdir}/doc" 222 test -z "$libdir" && libdir="${tccdir}/libtcc" 223 confvars="$confvars WIN32" 208 224 LIBSUF=".lib" 209 225 EXESUF=".exe" 226 DLLSUF=".dll" 210 227 else 211 228 if test -z "$prefix" ; then 212 prefix="/usr/local"229 prefix="/usr/local" 213 230 fi 214 231 if test -z "$sharedir" ; then 215 sharedir="${prefix}/share"232 sharedir="${prefix}/share" 216 233 fi 217 234 if test x"$execprefix" = x""; then 218 execprefix="${prefix}"235 execprefix="${prefix}" 219 236 fi 220 237 if test x"$libdir" = x""; then 221 libdir="${execprefix}/lib"238 libdir="${execprefix}/lib" 222 239 fi 223 240 if test x"$bindir" = x""; then 224 bindir="${execprefix}/bin" 241 bindir="${execprefix}/bin" 242 fi 243 if test x"$docdir" = x""; then 244 docdir="${sharedir}/doc" 245 fi 246 if test x"$mandir" = x""; then 247 mandir="${sharedir}/man" 248 fi 249 if test x"$infodir" = x""; then 250 infodir="${sharedir}/info" 225 251 fi 226 252 if test x"$tccdir" = x""; then 227 tccdir="tcc" 228 fi 229 if test x"$docdir" = x""; then 230 docdir="${sharedir}/doc/${tccdir}" 231 fi 232 if test x"$mandir" = x""; then 233 mandir="${sharedir}/man" 234 fi 235 if test x"$infodir" = x""; then 236 infodir="${sharedir}/info" 237 fi 238 tccdir="${libdir}/${tccdir}" 253 tccdir="${libdir}/tcc" 254 fi 255 if test x"$includedir" = x""; then 256 includedir="${prefix}/include" 257 fi 239 258 fi # mingw32 240 241 if test x"$includedir" = x""; then242 includedir="${prefix}/include"243 fi244 259 245 260 if test x"$show_help" = "xyes" ; then … … 252 267 --prefix=PREFIX install in PREFIX [$prefix] 253 268 --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX 254 269 [same as prefix] 255 270 --bindir=DIR user executables in DIR [EPREFIX/bin] 256 271 --libdir=DIR object code libraries in DIR [EPREFIX/lib] … … 267 282 --sysroot=PREFIX prepend PREFIX to library/include paths [] 268 283 --cc=CC use C compiler CC [$cc] 284 --ar=AR create archives using AR [$ar] 269 285 --extra-cflags= specify compiler flags [$CFLAGS] 270 286 --extra-ldflags= specify linker options [] 287 --cpu=CPU CPU [$cpu] 271 288 --strip-binaries strip symbol tables from resulting binaries 272 289 --disable-static make libtcc.so instead of libtcc.a 290 --enable-static make libtcc.a instead of libtcc.dll (win32) 273 291 --disable-rpath disable use of -rpath with the above 274 --with-libgcc use /lib/libgcc_s.so.1 instead of libtcc.a 275 --enable-mingw32 build windows version on linux with mingw32 276 --enable-cygwin build windows version on windows with cygwin 292 --with-libgcc use libgcc_s.so.1 instead of libtcc1.a 277 293 --enable-cross build cross compilers 278 --with-selinux use mmap for exec mem [needs writable /tmp]294 --with-selinux use mmap for executable memory (with tcc -run) 279 295 --sysincludepaths=... specify system include paths, colon separated 280 296 --libpaths=... specify system library paths, colon separated 281 297 --crtprefix=... specify locations of crt?.o, colon separated 282 298 --elfinterp=... specify elf interpreter 299 --triplet=... specify system library/include directory triplet 300 --config-uClibc,-musl,-mingw32... enable system specific configurations 283 301 EOF 284 302 #echo "NOTE: The object files are build at the place where configure is launched" … … 290 308 strip="${cross_prefix}${strip}" 291 309 292 CONFTEST=./conftest$EXESUF293 294 310 if test -z "$cross_prefix" ; then 311 CONFTEST=./conftest$EXESUF 295 312 if ! $cc -o $CONFTEST $source_path/conftest.c 2>/dev/null ; then 296 313 echo "configure: error: '$cc' failed to compile conftest.c." 297 314 else 298 bigendian="$($CONFTEST bigendian)"299 315 gcc_major="$($CONFTEST version)" 300 316 gcc_minor="$($CONFTEST minor)" 301 if test "$mingw32" = "no" ; then 302 triplet="$($CONFTEST triplet)" 303 if test -f "/usr/lib/$triplet/crti.o" ; then 304 tcc_lddir="lib/$triplet" 305 multiarch_triplet="$triplet" 306 elif test -f "/usr/lib64/crti.o" ; then 307 tcc_lddir="lib64" 308 fi 309 310 if test "$cpu" = "armv4l" ; then 311 if test "${triplet%eabihf}" != "$triplet" ; then 312 confvars="$confvars arm_eabihf" 313 elif test "${triplet%eabi}" != "$triplet" ; then 314 confvars="$confvars arm_eabi" 315 fi 316 if grep -s -q "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo ; then 317 confvars="$confvars arm_vfp" 317 fi 318 bigendian="$($CONFTEST bigendian)" 319 if test "$mingw32" = "no" ; then 320 321 if test -z "$triplet"; then 322 tt="$($CONFTEST triplet)" 323 if test -n "$tt" -a -f "/usr/lib/$tt/crti.o" ; then 324 triplet="$tt" 318 325 fi 319 326 fi 320 327 321 # multiarch_triplet=${libc_dir#*/} 322 # multiarch_triplet=${multiarch_triplet%/} 323 # tcc_lddir="${libc_dir%%/*}" 324 # if test -n "$multiarch_triplet" ; then 325 # tcc_lddir="$tcc_lddir/$multiarch_triplet" 326 # fi 327 328 if test -f "/lib/ld-uClibc.so.0" ; then 329 confvars="$confvars uClibc" 328 if test -z "$triplet"; then 329 if test $cpu = "x86_64" -o $cpu = "aarch64" ; then 330 if test -f "/usr/lib64/crti.o" ; then 331 tcc_lddir="lib64" 332 fi 333 fi 330 334 fi 331 # gr: maybe for after the release: 332 # tcc_elfinterp="$(ldd $CONFTEST | grep 'ld.*.so' | sed 's,\s*\(\S\+\).*,\1,')" 333 # echo "elfinterp $tcc_elfinterp" 334 335 fi 335 336 if test "$cpu" = "arm" ; then 337 if test "${triplet%eabihf}" != "$triplet" ; then 338 confvars="$confvars arm_eabihf" 339 elif test "${triplet%eabi}" != "$triplet" ; then 340 confvars="$confvars arm_eabi" 341 fi 342 if grep -s -q "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo ; then 343 confvars="$confvars arm_vfp" 344 fi 345 fi 346 347 if test "$suggest" = "yes"; then 348 if test -f "/lib/ld-uClibc.so.0" ; then 349 echo "Perhaps you want ./configure --config-uClibc" 350 fi 351 if test -f "/lib/ld-musl-$cpu.so.1"; then 352 echo "Perhaps you want ./configure --config-musl" 353 fi 354 fi 336 355 fi 337 356 else 338 357 # if cross compiling, cannot launch a program, so make a static guess 339 358 case $cpu in 340 p owerpc|mips|s390) bigendian=yes;;359 ppc|mips|s390) bigendian=yes;; 341 360 esac 342 361 fi 343 362 344 cat <<EOF 345 Binary directory $bindir 346 TinyCC directory $tccdir 347 Library directory $libdir 348 Include directory $includedir 349 Manual directory $mandir 350 Info directory $infodir 351 Doc directory $docdir 352 Target root prefix $sysroot 353 Source path $source_path 354 C compiler $cc 355 Target OS $targetos 356 CPU $cpu 357 Big Endian $bigendian 358 gprof enabled $gprof 359 cross compilers $build_cross 360 use libgcc $use_libgcc 361 EOF 362 363 if test "$bigendian" = "yes" ; then 364 confvars="$confvars BIGENDIAN" 365 fi 366 367 # a final configuration tuning 368 if ! echo "$cc" | grep -q "tcc"; then 369 OPT1="-Wdeclaration-after-statement -fno-strict-aliasing" 370 # we want -Wno- but gcc does not always reject unknown -Wno- options 371 OPT2="-Wpointer-sign -Wsign-compare -Wunused-result" 372 if echo "$cc" | grep -q "clang"; then 373 OPT1="$OPT1 -fheinous-gnu-extensions" 374 OPT2="$OPT2 -Wstring-plus-int" 375 fi 376 $cc $OPT1 $OPT2 -o a.out -c -xc - < /dev/null > cc_msg.txt 2>&1 377 for o in $OPT1; do # enable these options 378 if ! grep -q -- $o cc_msg.txt; then CFLAGS="$CFLAGS $o"; fi 379 done 380 for o in $OPT2; do # disable these options 381 if ! grep -q -- $o cc_msg.txt; then CFLAGS="$CFLAGS -Wno-${o#-W*}"; fi 382 done 383 # cat cc_msg.txt 384 # echo $CFLAGS 385 rm -f cc_msg.txt a.out 386 fi 387 388 fcho() { if test -n "$2"; then echo "$1$2"; fi } 389 390 fcho "Binary directory " "$bindir" 391 fcho "TinyCC directory " "$tccdir" 392 fcho "Library directory " "$libdir" 393 fcho "Include directory " "$includedir" 394 fcho "Manual directory " "$mandir" 395 fcho "Info directory " "$infodir" 396 fcho "Doc directory " "$docdir" 397 fcho "Target root prefix " "$sysroot" 398 echo "Source path $source_path" 399 echo "C compiler $cc ($gcc_major.$gcc_minor)" 400 echo "Target OS $targetos" 401 echo "CPU $cpu" 402 fcho "Triplet " "$triplet" 403 fcho "Config " "${confvars# }" 363 404 echo "Creating config.mak and config.h" 364 405 … … 369 410 tccdir=\$(DESTDIR)$tccdir 370 411 libdir=\$(DESTDIR)$libdir 371 ln_libdir=$libdir372 412 includedir=\$(DESTDIR)$includedir 373 413 mandir=\$(DESTDIR)$mandir … … 377 417 GCC_MAJOR=$gcc_major 378 418 GCC_MINOR=$gcc_minor 379 HOST_CC=$host_cc380 419 AR=$ar 381 420 STRIP=$strip -s -R .comment -R .note … … 384 423 LIBSUF=$LIBSUF 385 424 EXESUF=$EXESUF 425 DLLSUF=$DLLSUF 386 426 EOF 387 427 … … 393 433 fi 394 434 } 435 395 436 print_mak() { 396 437 if test -n "$2"; then 397 438 echo "NATIVE_DEFINES+=-D$1=\"\\\"$2\\\"\"" >> config.mak 439 fi 440 } 441 442 print_mak_int() { 443 if test -n "$2"; then 444 echo "NATIVE_DEFINES+=-D$1=$2" >> config.mak 398 445 fi 399 446 } … … 408 455 print_mak CONFIG_TCC_ELFINTERP "$tcc_elfinterp" 409 456 print_mak CONFIG_LDDIR "$tcc_lddir" 410 print_mak CONFIG_MULTIARCHDIR "$multiarch_triplet" 411 412 echo "#define GCC_MAJOR $gcc_major" >> $TMPH 413 echo "#define GCC_MINOR $gcc_minor" >> $TMPH 414 415 if test "$cpu" = "x86" ; then 416 echo "ARCH=i386" >> config.mak 417 echo "#define HOST_I386 1" >> $TMPH 418 elif test "$cpu" = "x86-64" ; then 419 echo "ARCH=x86-64" >> config.mak 420 echo "#define HOST_X86_64 1" >> $TMPH 421 elif test "$cpu" = "armv4l" ; then 422 echo "ARCH=arm" >> config.mak 423 echo "#define HOST_ARM 1" >> $TMPH 424 echo "#define TCC_ARM_VERSION $cpuver" >> $TMPH 425 elif test "$cpu" = "powerpc" ; then 426 echo "ARCH=ppc" >> config.mak 427 echo "#define HOST_PPC 1" >> $TMPH 428 elif test "$cpu" = "mips" ; then 429 echo "ARCH=mips" >> config.mak 430 echo "#define HOST_MIPS 1" >> $TMPH 431 elif test "$cpu" = "s390" ; then 432 echo "ARCH=s390" >> config.mak 433 echo "#define HOST_S390 1" >> $TMPH 434 elif test "$cpu" = "alpha" ; then 435 echo "ARCH=alpha" >> config.mak 436 echo "#define HOST_ALPHA 1" >> $TMPH 457 print_mak CONFIG_TRIPLET "$triplet" 458 print_mak_int TCC_CPU_VERSION "$cpuver" 459 460 if test "$cpu" = "aarch64" ; then 461 echo "ARCH=arm64" >> config.mak 437 462 else 438 echo "Unsupported CPU" 439 exit 1 440 fi 441 463 echo "ARCH=$cpu" >> config.mak 464 fi 442 465 echo "TARGETOS=$targetos" >> config.mak 443 466 444 467 for v in $confvars ; do 445 echo "CONFIG_$v=yes" >> config.mak 468 if test "${v%=*}" = "$v"; then 469 echo "CONFIG_$v=yes" >> config.mak 470 else 471 echo "CONFIG_$v" >> config.mak 472 fi 446 473 done 447 if test "$noldl" = "yes" ; then448 echo "CONFIG_NOLDL=yes" >> config.mak449 fi450 if test "$mingw32" = "yes" ; then451 echo "CONFIG_WIN32=yes" >> config.mak452 echo "#define CONFIG_WIN32 1" >> $TMPH453 fi454 if test "$cygwin" = "yes" ; then455 echo "#ifndef _WIN32" >> $TMPH456 echo "# define _WIN32" >> $TMPH457 echo "#endif" >> $TMPH458 echo "AR=ar" >> config.mak459 fi460 if test "$bigendian" = "yes" ; then461 echo "WORDS_BIGENDIAN=yes" >> config.mak462 echo "#define WORDS_BIGENDIAN 1" >> $TMPH463 fi464 if test "$gprof" = "yes" ; then465 echo "TARGET_GPROF=yes" >> config.mak466 echo "#define HAVE_GPROF 1" >> $TMPH467 fi468 if test "$build_cross" = "yes" ; then469 echo "CONFIG_CROSS=yes" >> config.mak470 fi471 if test "$disable_static" = "yes" ; then472 echo "DISABLE_STATIC=yes" >> config.mak473 fi474 if test "$disable_rpath" = "yes" ; then475 echo "DISABLE_RPATH=yes" >> config.mak476 fi477 if test "$strip_binaries" = "yes" ; then478 echo "STRIP_BINARIES=yes" >> config.mak479 fi480 if test "$use_libgcc" = "yes" ; then481 echo "#define CONFIG_USE_LIBGCC" >> $TMPH482 echo "CONFIG_USE_LIBGCC=yes" >> config.mak483 fi484 if test "$have_selinux" = "yes" ; then485 echo "#define HAVE_SELINUX" >> $TMPH486 echo "HAVE_SELINUX=yes" >> config.mak487 fi488 474 489 475 version=`head $source_path/VERSION` 490 echo "VERSION =$version" >>config.mak476 echo "VERSION = $version" >> config.mak 491 477 echo "#define TCC_VERSION \"$version\"" >> $TMPH 492 478 echo "@set VERSION $version" > config.texi 493 echo "SRC_PATH=$source_path" >>config.mak494 479 495 480 if test "$source_path_used" = "yes" ; then 496 481 case $source_path in 497 /*) echo " top_srcdir=$source_path";;498 *) echo "top_srcdir=\$(TOP)/$source_path";;482 /*) echo "TOPSRC=$source_path";; 483 *) echo "TOPSRC=\$(TOP)/$source_path";; 499 484 esac >>config.mak 500 485 else 501 echo 'top_srcdir=$(TOP)' >>config.mak 502 fi 503 echo 'top_builddir=$(TOP)' >>config.mak 486 echo 'TOPSRC=$(TOP)' >>config.mak 487 fi 504 488 505 489 diff $TMPH config.h >/dev/null 2>&1 … … 520 504 case $2 in 521 505 */*) dn=${2%/*} 522 523 524 525 526 527 528 529 530 506 test -d $dn || mkdir -p $dn 507 case $1 in 508 /*) ;; 509 *) while test $dn ; do 510 tgt=../$tgt; dn=${dn#${dn%%/*}}; dn=${dn#/} 511 done 512 ;; 513 esac 514 ;; 531 515 esac 532 ln -sfn $tgt $2 516 517 ln -sfn $tgt $2 || ( echo "ln failed. Using cp instead."; cp -f $1/$2 $2 ) 533 518 } 534 519 535 520 if test "$source_path_used" = "yes" ; then 536 FILES="Makefile lib/Makefile tests/Makefile tests/tests2/Makefile "521 FILES="Makefile lib/Makefile tests/Makefile tests/tests2/Makefile tests/pp/Makefile" 537 522 for f in $FILES ; do 538 523 fn_makelink $source_path $f -
EcnlProtoTool/trunk/tcc-0.9.27/conftest.c
r321 r331 2 2 3 3 /* Define architecture */ 4 #if defined(__i386__) 4 #if defined(__i386__) || defined _M_IX86 5 5 # define TRIPLET_ARCH "i386" 6 #elif defined(__x86_64__) 6 #elif defined(__x86_64__) || defined _M_AMD64 7 7 # define TRIPLET_ARCH "x86_64" 8 8 #elif defined(__arm__) 9 9 # define TRIPLET_ARCH "arm" 10 #elif defined(__aarch64__) 11 # define TRIPLET_ARCH "aarch64" 10 12 #else 11 13 # define TRIPLET_ARCH "unknown" … … 17 19 #elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__) 18 20 # define TRIPLET_OS "kfreebsd" 21 #elif defined _WIN32 22 # define TRIPLET_OS "win32" 19 23 #elif !defined (__GNU__) 20 24 # define TRIPLET_OS "unknown" … … 32 36 #endif 33 37 34 #ifdef __GNU__ 38 #if defined _WIN32 39 # define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS 40 #elif defined __GNU__ 35 41 # define TRIPLET TRIPLET_ARCH "-" TRIPLET_ABI 36 42 #else 37 43 # define TRIPLET TRIPLET_ARCH "-" TRIPLET_OS "-" TRIPLET_ABI 44 #endif 45 46 #if defined(_WIN32) 47 int _CRT_glob = 0; 38 48 #endif 39 49 … … 54 64 printf("%d\n", __GNUC__); 55 65 break; 66 #elif defined __TINYC__ 67 case 'v': 68 puts("0"); 69 break; 70 case 'm': 71 printf("%d\n", __TINYC__); 72 break; 56 73 #else 57 74 case 'm': … … 63 80 puts(TRIPLET); 64 81 break; 65 case -1: 66 /* to test -Wno-unused-result */ 67 fread(NULL, 1, 1, NULL); 82 83 default: 68 84 break; 69 85 } -
EcnlProtoTool/trunk/tcc-0.9.27/elf.h
r321 r331 1 1 /* This file defines standard ELF types, structures, and macros. 2 Copyright (C) 1995 , 1996, 1997, 1998, 1999Free Software Foundation, Inc.2 Copyright (C) 1995-2012 Free Software Foundation, Inc. 3 3 This file is part of the GNU C Library. 4 Contributed by Ian Lance Taylor <ian@cygnus.com>.5 4 6 5 The GNU C Library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU L ibrary General Public License as8 published by the Free Software Foundation; either version 2 of the9 License, or (at your option) any later version.6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 10 9 11 10 The GNU C Library is distributed in the hope that it will be useful, 12 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Library General Public License for more details. 15 16 You should have received a copy of the GNU Library General Public 17 License along with the GNU C Library; see the file COPYING.LIB. If not, 18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 Boston, MA 02111-1307, USA. */ 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <http://www.gnu.org/licenses/>. */ 20 18 21 19 #ifndef _ELF_H 22 #define 20 #define _ELF_H 1 23 21 24 22 #ifndef _WIN32 … … 31 29 typedef int int32_t; 32 30 typedef long long int int64_t; 33 #endif34 35 31 typedef unsigned char uint8_t; 36 32 typedef unsigned short int uint16_t; … … 38 34 typedef unsigned long long int uint64_t; 39 35 #endif 36 #endif 40 37 41 38 /* Standard ELF types. */ … … 47 44 /* Types for signed and unsigned 32-bit quantities. */ 48 45 typedef uint32_t Elf32_Word; 49 typedef 46 typedef int32_t Elf32_Sword; 50 47 typedef uint32_t Elf64_Word; 51 typedef 48 typedef int32_t Elf64_Sword; 52 49 53 50 /* Types for signed and unsigned 64-bit quantities. */ 54 51 typedef uint64_t Elf32_Xword; 55 typedef 52 typedef int64_t Elf32_Sxword; 56 53 typedef uint64_t Elf64_Xword; 57 typedef 54 typedef int64_t Elf64_Sxword; 58 55 59 56 /* Type of addresses. */ … … 69 66 typedef uint16_t Elf64_Section; 70 67 71 /* Type of symbol indices. */72 typedef uint32_t Elf32_Symndx;73 typedef uint64_t Elf64_Symndx;68 /* Type for version symbol information. */ 69 typedef Elf32_Half Elf32_Versym; 70 typedef Elf64_Half Elf64_Versym; 74 71 75 72 … … 80 77 typedef struct 81 78 { 82 unsigned char e_ident[EI_NIDENT];/* Magic number and other info */83 Elf32_Half e_type;/* Object file type */84 Elf32_Half e_machine;/* Architecture */85 Elf32_Word e_version;/* Object file version */86 Elf32_Addr e_entry;/* Entry point virtual address */87 Elf32_Off e_phoff;/* Program header table file offset */88 Elf32_Off e_shoff;/* Section header table file offset */89 Elf32_Word e_flags;/* Processor-specific flags */90 Elf32_Half e_ehsize;/* ELF header size in bytes */91 Elf32_Half e_phentsize;/* Program header table entry size */92 Elf32_Half e_phnum;/* Program header table entry count */93 Elf32_Half e_shentsize;/* Section header table entry size */94 Elf32_Half e_shnum;/* Section header table entry count */95 Elf32_Half e_shstrndx;/* Section header string table index */96 } Elf32_Ehdr;97 98 typedef struct 99 { 100 unsigned char e_ident[EI_NIDENT];/* Magic number and other info */101 Elf64_Half e_type;/* Object file type */102 Elf64_Half e_machine;/* Architecture */103 Elf64_Word e_version;/* Object file version */104 Elf64_Addr e_entry;/* Entry point virtual address */105 Elf64_Off e_phoff;/* Program header table file offset */106 Elf64_Off e_shoff;/* Section header table file offset */107 Elf64_Word e_flags;/* Processor-specific flags */108 Elf64_Half e_ehsize;/* ELF header size in bytes */109 Elf64_Half e_phentsize;/* Program header table entry size */110 Elf64_Half e_phnum;/* Program header table entry count */111 Elf64_Half e_shentsize;/* Section header table entry size */112 Elf64_Half e_shnum;/* Section header table entry count */113 Elf64_Half e_shstrndx;/* Section header string table index */114 } Elf64_Ehdr;79 unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ 80 Elf32_Half e_type; /* Object file type */ 81 Elf32_Half e_machine; /* Architecture */ 82 Elf32_Word e_version; /* Object file version */ 83 Elf32_Addr e_entry; /* Entry point virtual address */ 84 Elf32_Off e_phoff; /* Program header table file offset */ 85 Elf32_Off e_shoff; /* Section header table file offset */ 86 Elf32_Word e_flags; /* Processor-specific flags */ 87 Elf32_Half e_ehsize; /* ELF header size in bytes */ 88 Elf32_Half e_phentsize; /* Program header table entry size */ 89 Elf32_Half e_phnum; /* Program header table entry count */ 90 Elf32_Half e_shentsize; /* Section header table entry size */ 91 Elf32_Half e_shnum; /* Section header table entry count */ 92 Elf32_Half e_shstrndx; /* Section header string table index */ 93 } __attribute__((packed)) Elf32_Ehdr; 94 95 typedef struct 96 { 97 unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ 98 Elf64_Half e_type; /* Object file type */ 99 Elf64_Half e_machine; /* Architecture */ 100 Elf64_Word e_version; /* Object file version */ 101 Elf64_Addr e_entry; /* Entry point virtual address */ 102 Elf64_Off e_phoff; /* Program header table file offset */ 103 Elf64_Off e_shoff; /* Section header table file offset */ 104 Elf64_Word e_flags; /* Processor-specific flags */ 105 Elf64_Half e_ehsize; /* ELF header size in bytes */ 106 Elf64_Half e_phentsize; /* Program header table entry size */ 107 Elf64_Half e_phnum; /* Program header table entry count */ 108 Elf64_Half e_shentsize; /* Section header table entry size */ 109 Elf64_Half e_shnum; /* Section header table entry count */ 110 Elf64_Half e_shstrndx; /* Section header string table index */ 111 } __attribute__((packed)) Elf64_Ehdr; 115 112 116 113 /* Fields in the e_ident array. The EI_* macros are indices into the … … 118 115 may have. */ 119 116 120 #define EI_MAG0 0/* File identification byte 0 index */121 #define ELFMAG0 0x7f/* Magic number byte 0 */122 123 #define EI_MAG1 1/* File identification byte 1 index */124 #define ELFMAG1 'E'/* Magic number byte 1 */125 126 #define EI_MAG2 2/* File identification byte 2 index */127 #define ELFMAG2 'L'/* Magic number byte 2 */128 129 #define EI_MAG3 3/* File identification byte 3 index */130 #define ELFMAG3 'F'/* Magic number byte 3 */117 #define EI_MAG0 0 /* File identification byte 0 index */ 118 #define ELFMAG0 0x7f /* Magic number byte 0 */ 119 120 #define EI_MAG1 1 /* File identification byte 1 index */ 121 #define ELFMAG1 'E' /* Magic number byte 1 */ 122 123 #define EI_MAG2 2 /* File identification byte 2 index */ 124 #define ELFMAG2 'L' /* Magic number byte 2 */ 125 126 #define EI_MAG3 3 /* File identification byte 3 index */ 127 #define ELFMAG3 'F' /* Magic number byte 3 */ 131 128 132 129 /* Conglomeration of the identification bytes, for easy testing as a word. */ 133 #define ELFMAG "\177ELF" 134 #define SELFMAG 4 135 136 #define EI_CLASS 4 /* File class byte index */ 137 #define ELFCLASSNONE 0 /* Invalid class */ 138 #define ELFCLASS32 1 /* 32-bit objects */ 139 #define ELFCLASS64 2 /* 64-bit objects */ 140 #define ELFCLASSNUM 3 141 142 #define EI_DATA 5 /* Data encoding byte index */ 143 #define ELFDATANONE 0 /* Invalid data encoding */ 144 #define ELFDATA2LSB 1 /* 2's complement, little endian */ 145 #define ELFDATA2MSB 2 /* 2's complement, big endian */ 146 #define ELFDATANUM 3 147 148 #define EI_VERSION 6 /* File version byte index */ 149 /* Value must be EV_CURRENT */ 150 151 #define EI_OSABI 7 /* OS ABI identification */ 152 #define ELFOSABI_SYSV 0 /* UNIX System V ABI */ 153 #define ELFOSABI_HPUX 1 /* HP-UX */ 154 #define ELFOSABI_FREEBSD 9 /* Free BSD */ 155 #define ELFOSABI_ARM 97 /* ARM */ 156 #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ 157 158 #define EI_ABIVERSION 8 /* ABI version */ 159 160 #define EI_PAD 9 /* Byte index of padding bytes */ 130 #define ELFMAG "\177ELF" 131 #define SELFMAG 4 132 133 #define EI_CLASS 4 /* File class byte index */ 134 #define ELFCLASSNONE 0 /* Invalid class */ 135 #define ELFCLASS32 1 /* 32-bit objects */ 136 #define ELFCLASS64 2 /* 64-bit objects */ 137 #define ELFCLASSNUM 3 138 139 #define EI_DATA 5 /* Data encoding byte index */ 140 #define ELFDATANONE 0 /* Invalid data encoding */ 141 #define ELFDATA2LSB 1 /* 2's complement, little endian */ 142 #define ELFDATA2MSB 2 /* 2's complement, big endian */ 143 #define ELFDATANUM 3 144 145 #define EI_VERSION 6 /* File version byte index */ 146 /* Value must be EV_CURRENT */ 147 148 #define EI_OSABI 7 /* OS ABI identification */ 149 #define ELFOSABI_NONE 0 /* UNIX System V ABI */ 150 #define ELFOSABI_SYSV 0 /* Alias. */ 151 #define ELFOSABI_HPUX 1 /* HP-UX */ 152 #define ELFOSABI_NETBSD 2 /* NetBSD. */ 153 #define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */ 154 #define ELFOSABI_LINUX ELFOSABI_GNU /* Compatibility alias. */ 155 #define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ 156 #define ELFOSABI_AIX 7 /* IBM AIX. */ 157 #define ELFOSABI_IRIX 8 /* SGI Irix. */ 158 #define ELFOSABI_FREEBSD 9 /* FreeBSD. */ 159 #define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ 160 #define ELFOSABI_MODESTO 11 /* Novell Modesto. */ 161 #define ELFOSABI_OPENBSD 12 /* OpenBSD. */ 162 #define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ 163 #define ELFOSABI_ARM 97 /* ARM */ 164 #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ 165 166 #define EI_ABIVERSION 8 /* ABI version */ 167 168 #define EI_PAD 9 /* Byte index of padding bytes */ 161 169 162 170 /* Legal values for e_type (object file type). */ 163 171 164 #define ET_NONE 0 /* No file type */ 165 #define ET_REL 1 /* Relocatable file */ 166 #define ET_EXEC 2 /* Executable file */ 167 #define ET_DYN 3 /* Shared object file */ 168 #define ET_CORE 4 /* Core file */ 169 #define ET_NUM 5 /* Number of defined types */ 170 #define ET_LOPROC 0xff00 /* Processor-specific */ 171 #define ET_HIPROC 0xffff /* Processor-specific */ 172 #define ET_NONE 0 /* No file type */ 173 #define ET_REL 1 /* Relocatable file */ 174 #define ET_EXEC 2 /* Executable file */ 175 #define ET_DYN 3 /* Shared object file */ 176 #define ET_CORE 4 /* Core file */ 177 #define ET_NUM 5 /* Number of defined types */ 178 #define ET_LOOS 0xfe00 /* OS-specific range start */ 179 #define ET_HIOS 0xfeff /* OS-specific range end */ 180 #define ET_LOPROC 0xff00 /* Processor-specific range start */ 181 #define ET_HIPROC 0xffff /* Processor-specific range end */ 172 182 173 183 /* Legal values for e_machine (architecture). */ 174 184 175 #define EM_NONE 0 /* No machine */ 176 #define EM_M32 1 /* AT&T WE 32100 */ 177 #define EM_SPARC 2 /* SUN SPARC */ 178 #define EM_386 3 /* Intel 80386 */ 179 #define EM_68K 4 /* Motorola m68k family */ 180 #define EM_88K 5 /* Motorola m88k family */ 181 #define EM_486 6 /* Intel 80486 */ 182 #define EM_860 7 /* Intel 80860 */ 183 #define EM_MIPS 8 /* MIPS R3000 big-endian */ 184 #define EM_S370 9 /* Amdahl */ 185 #define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ 186 #define EM_RS6000 11 /* RS6000 */ 187 188 #define EM_PARISC 15 /* HPPA */ 189 #define EM_nCUBE 16 /* nCUBE */ 190 #define EM_VPP500 17 /* Fujitsu VPP500 */ 191 #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ 192 #define EM_960 19 /* Intel 80960 */ 193 #define EM_PPC 20 /* PowerPC */ 194 195 #define EM_V800 36 /* NEC V800 series */ 196 #define EM_FR20 37 /* Fujitsu FR20 */ 197 #define EM_RH32 38 /* TRW RH32 */ 198 #define EM_RCE 39 /* Motorola RCE */ 199 #define EM_ARM 40 /* ARM */ 200 #define EM_FAKE_ALPHA 41 /* Digital Alpha */ 201 #define EM_SH 42 /* Hitachi SH */ 202 #define EM_SPARCV9 43 /* SPARC v9 64-bit */ 203 #define EM_TRICORE 44 /* Siemens Tricore */ 204 #define EM_ARC 45 /* Argonaut RISC Core */ 205 #define EM_H8_300 46 /* Hitachi H8/300 */ 206 #define EM_H8_300H 47 /* Hitachi H8/300H */ 207 #define EM_H8S 48 /* Hitachi H8S */ 208 #define EM_H8_500 49 /* Hitachi H8/500 */ 209 #define EM_IA_64 50 /* Intel Merced */ 210 #define EM_MIPS_X 51 /* Stanford MIPS-X */ 211 #define EM_COLDFIRE 52 /* Motorola Coldfire */ 212 #define EM_68HC12 53 /* Motorola M68HC12 */ 213 #define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ 214 #define EM_PCP 55 /* Siemens PCP */ 215 #define EM_NCPU 56 /* Sony nCPU embeeded RISC */ 216 #define EM_NDR1 57 /* Denso NDR1 microprocessor */ 217 #define EM_STARCORE 58 /* Motorola Start*Core processor */ 218 #define EM_ME16 59 /* Toyota ME16 processor */ 219 #define EM_ST100 60 /* STMicroelectronic ST100 processor */ 220 #define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ 221 #define EM_X86_64 62 /* AMD x86-64 architecture */ 222 #define EM_PDSP 63 /* Sony DSP Processor */ 223 #define EM_FX66 66 /* Siemens FX66 microcontroller */ 224 #define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ 225 #define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ 226 #define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ 227 #define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ 228 #define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ 229 #define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ 230 #define EM_SVX 73 /* Silicon Graphics SVx */ 231 #define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ 232 #define EM_VAX 75 /* Digital VAX */ 233 #define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ 234 #define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ 235 #define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ 236 #define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ 237 #define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ 238 #define EM_HUANY 81 /* Harvard University machine-independent object files */ 239 #define EM_PRISM 82 /* SiTera Prism */ 240 #define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ 241 #define EM_FR30 84 /* Fujitsu FR30 */ 242 #define EM_D10V 85 /* Mitsubishi D10V */ 243 #define EM_D30V 86 /* Mitsubishi D30V */ 244 #define EM_V850 87 /* NEC v850 */ 245 #define EM_M32R 88 /* Mitsubishi M32R */ 246 #define EM_MN10300 89 /* Matsushita MN10300 */ 247 #define EM_MN10200 90 /* Matsushita MN10200 */ 248 #define EM_PJ 91 /* picoJava */ 249 #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ 250 #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ 251 #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ 252 #define EM_NUM 95 185 #define EM_NONE 0 /* No machine */ 186 #define EM_M32 1 /* AT&T WE 32100 */ 187 #define EM_SPARC 2 /* SUN SPARC */ 188 #define EM_386 3 /* Intel 80386 */ 189 #define EM_68K 4 /* Motorola m68k family */ 190 #define EM_88K 5 /* Motorola m88k family */ 191 #define EM_860 7 /* Intel 80860 */ 192 #define EM_MIPS 8 /* MIPS R3000 big-endian */ 193 #define EM_S370 9 /* IBM System/370 */ 194 #define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ 195 196 #define EM_PARISC 15 /* HPPA */ 197 #define EM_VPP500 17 /* Fujitsu VPP500 */ 198 #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ 199 #define EM_960 19 /* Intel 80960 */ 200 #define EM_PPC 20 /* PowerPC */ 201 #define EM_PPC64 21 /* PowerPC 64-bit */ 202 #define EM_S390 22 /* IBM S390 */ 203 204 #define EM_V800 36 /* NEC V800 series */ 205 #define EM_FR20 37 /* Fujitsu FR20 */ 206 #define EM_RH32 38 /* TRW RH-32 */ 207 #define EM_RCE 39 /* Motorola RCE */ 208 #define EM_ARM 40 /* ARM */ 209 #define EM_FAKE_ALPHA 41 /* Digital Alpha */ 210 #define EM_SH 42 /* Hitachi SH */ 211 #define EM_SPARCV9 43 /* SPARC v9 64-bit */ 212 #define EM_TRICORE 44 /* Siemens Tricore */ 213 #define EM_ARC 45 /* Argonaut RISC Core */ 214 #define EM_H8_300 46 /* Hitachi H8/300 */ 215 #define EM_H8_300H 47 /* Hitachi H8/300H */ 216 #define EM_H8S 48 /* Hitachi H8S */ 217 #define EM_H8_500 49 /* Hitachi H8/500 */ 218 #define EM_IA_64 50 /* Intel Merced */ 219 #define EM_MIPS_X 51 /* Stanford MIPS-X */ 220 #define EM_COLDFIRE 52 /* Motorola Coldfire */ 221 #define EM_68HC12 53 /* Motorola M68HC12 */ 222 #define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ 223 #define EM_PCP 55 /* Siemens PCP */ 224 #define EM_NCPU 56 /* Sony nCPU embedded RISC */ 225 #define EM_NDR1 57 /* Denso NDR1 microprocessor */ 226 #define EM_STARCORE 58 /* Motorola Start*Core processor */ 227 #define EM_ME16 59 /* Toyota ME16 processor */ 228 #define EM_ST100 60 /* STMicroelectronic ST100 processor */ 229 #define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ 230 #define EM_X86_64 62 /* AMD x86-64 architecture */ 231 #define EM_PDSP 63 /* Sony DSP Processor */ 232 233 #define EM_FX66 66 /* Siemens FX66 microcontroller */ 234 #define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ 235 #define EM_ST7 68 /* STMicroelectronics ST7 8 bit mc */ 236 #define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ 237 #define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ 238 #define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ 239 #define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ 240 #define EM_SVX 73 /* Silicon Graphics SVx */ 241 #define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ 242 #define EM_VAX 75 /* Digital VAX */ 243 #define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ 244 #define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ 245 #define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ 246 #define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ 247 #define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ 248 #define EM_HUANY 81 /* Harvard University machine-independent object files */ 249 #define EM_PRISM 82 /* SiTera Prism */ 250 #define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ 251 #define EM_FR30 84 /* Fujitsu FR30 */ 252 #define EM_D10V 85 /* Mitsubishi D10V */ 253 #define EM_D30V 86 /* Mitsubishi D30V */ 254 #define EM_V850 87 /* NEC v850 */ 255 #define EM_M32R 88 /* Mitsubishi M32R */ 256 #define EM_MN10300 89 /* Matsushita MN10300 */ 257 #define EM_MN10200 90 /* Matsushita MN10200 */ 258 #define EM_PJ 91 /* picoJava */ 259 #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ 260 #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ 261 #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ 262 #define EM_AARCH64 183 /* ARM AARCH64 */ 263 #define EM_TILEPRO 188 /* Tilera TILEPro */ 264 #define EM_TILEGX 191 /* Tilera TILE-Gx */ 265 #define EM_NUM 192 253 266 254 267 /* If it is necessary to assign new unofficial EM_* values, please … … 256 269 chances of collision with official or non-GNU unofficial values. */ 257 270 258 #define EM_ALPHA 259 #define EM_C60 271 #define EM_ALPHA 0x9026 272 #define EM_C60 0x9c60 260 273 261 274 /* Legal values for e_version (version). */ 262 275 263 #define EV_NONE 0/* Invalid ELF version */264 #define EV_CURRENT 1/* Current version */265 #define EV_NUM 276 #define EV_NONE 0 /* Invalid ELF version */ 277 #define EV_CURRENT 1 /* Current version */ 278 #define EV_NUM 2 266 279 267 280 /* Section header. */ … … 269 282 typedef struct 270 283 { 271 Elf32_Word sh_name;/* Section name (string tbl index) */272 Elf32_Word sh_type;/* Section type */273 Elf32_Word sh_flags;/* Section flags */274 Elf32_Addr sh_addr;/* Section virtual addr at execution */275 Elf32_Off sh_offset;/* Section file offset */276 Elf32_Word sh_size;/* Section size in bytes */277 Elf32_Word sh_link;/* Link to another section */278 Elf32_Word sh_info;/* Additional section information */279 Elf32_Word sh_addralign;/* Section alignment */280 Elf32_Word sh_entsize;/* Entry size if section holds table */281 } Elf32_Shdr;282 283 typedef struct 284 { 285 Elf64_Word sh_name;/* Section name (string tbl index) */286 Elf64_Word sh_type;/* Section type */287 Elf64_Xword sh_flags;/* Section flags */288 Elf64_Addr sh_addr;/* Section virtual addr at execution */289 Elf64_Off sh_offset;/* Section file offset */290 Elf64_Xword sh_size;/* Section size in bytes */291 Elf64_Word sh_link;/* Link to another section */292 Elf64_Word sh_info;/* Additional section information */293 Elf64_Xword sh_addralign;/* Section alignment */294 Elf64_Xword sh_entsize;/* Entry size if section holds table */295 } Elf64_Shdr;284 Elf32_Word sh_name; /* Section name (string tbl index) */ 285 Elf32_Word sh_type; /* Section type */ 286 Elf32_Word sh_flags; /* Section flags */ 287 Elf32_Addr sh_addr; /* Section virtual addr at execution */ 288 Elf32_Off sh_offset; /* Section file offset */ 289 Elf32_Word sh_size; /* Section size in bytes */ 290 Elf32_Word sh_link; /* Link to another section */ 291 Elf32_Word sh_info; /* Additional section information */ 292 Elf32_Word sh_addralign; /* Section alignment */ 293 Elf32_Word sh_entsize; /* Entry size if section holds table */ 294 } __attribute__((packed)) Elf32_Shdr; 295 296 typedef struct 297 { 298 Elf64_Word sh_name; /* Section name (string tbl index) */ 299 Elf64_Word sh_type; /* Section type */ 300 Elf64_Xword sh_flags; /* Section flags */ 301 Elf64_Addr sh_addr; /* Section virtual addr at execution */ 302 Elf64_Off sh_offset; /* Section file offset */ 303 Elf64_Xword sh_size; /* Section size in bytes */ 304 Elf64_Word sh_link; /* Link to another section */ 305 Elf64_Word sh_info; /* Additional section information */ 306 Elf64_Xword sh_addralign; /* Section alignment */ 307 Elf64_Xword sh_entsize; /* Entry size if section holds table */ 308 } __attribute__((packed)) Elf64_Shdr; 296 309 297 310 /* Special section indices. */ 298 311 299 #define SHN_UNDEF 0 /* Undefined section */ 300 #define SHN_LORESERVE 0xff00 /* Start of reserved indices */ 301 #define SHN_LOPROC 0xff00 /* Start of processor-specific */ 302 #define SHN_HIPROC 0xff1f /* End of processor-specific */ 303 #define SHN_ABS 0xfff1 /* Associated symbol is absolute */ 304 #define SHN_COMMON 0xfff2 /* Associated symbol is common */ 305 #define SHN_HIRESERVE 0xffff /* End of reserved indices */ 312 #define SHN_UNDEF 0 /* Undefined section */ 313 #define SHN_LORESERVE 0xff00 /* Start of reserved indices */ 314 #define SHN_LOPROC 0xff00 /* Start of processor-specific */ 315 #define SHN_BEFORE 0xff00 /* Order section before all others 316 (Solaris). */ 317 #define SHN_AFTER 0xff01 /* Order section after all others 318 (Solaris). */ 319 #define SHN_HIPROC 0xff1f /* End of processor-specific */ 320 #define SHN_LOOS 0xff20 /* Start of OS-specific */ 321 #define SHN_HIOS 0xff3f /* End of OS-specific */ 322 #define SHN_ABS 0xfff1 /* Associated symbol is absolute */ 323 #define SHN_COMMON 0xfff2 /* Associated symbol is common */ 324 #define SHN_XINDEX 0xffff /* Index is in extra table. */ 325 #define SHN_HIRESERVE 0xffff /* End of reserved indices */ 306 326 307 327 /* Legal values for sh_type (section type). */ 308 328 309 #define SHT_NULL 0 /* Section header table entry unused */ 310 #define SHT_PROGBITS 1 /* Program data */ 311 #define SHT_SYMTAB 2 /* Symbol table */ 312 #define SHT_STRTAB 3 /* String table */ 313 #define SHT_RELA 4 /* Relocation entries with addends */ 314 #define SHT_HASH 5 /* Symbol hash table */ 315 #define SHT_DYNAMIC 6 /* Dynamic linking information */ 316 #define SHT_NOTE 7 /* Notes */ 317 #define SHT_NOBITS 8 /* Program space with no data (bss) */ 318 #define SHT_REL 9 /* Relocation entries, no addends */ 319 #define SHT_SHLIB 10 /* Reserved */ 320 #define SHT_DYNSYM 11 /* Dynamic linker symbol table */ 321 #define SHT_INIT_ARRAY 14 /* Array of constructors */ 322 #define SHT_FINI_ARRAY 15 /* Array of destructors */ 323 #define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ 324 #define SHT_GROUP 17 /* Section group */ 325 #define SHT_SYMTAB_SHNDX 18 /* Extended section indices */ 326 #define SHT_NUM 19 /* Number of defined types. */ 327 #define SHT_LOOS 0x60000000 /* Start OS-specific */ 328 #define SHT_LOSUNW 0x6ffffffb /* Sun-specific low bound. */ 329 #define SHT_SUNW_COMDAT 0x6ffffffb 330 #define SHT_SUNW_syminfo 0x6ffffffc 331 #define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ 332 #define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ 333 #define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ 334 #define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ 335 #define SHT_HIOS 0x6fffffff /* End OS-specific type */ 336 #define SHT_LOPROC 0x70000000 /* Start of processor-specific */ 337 #define SHT_ARM_EXIDX 0x70000001 /* Exception Index table */ 338 #define SHT_ARM_PREEMPTMAP 0x70000002 /* dynamic linking pre-emption map */ 339 #define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility attrs */ 340 #define SHT_HIPROC 0x7fffffff /* End of processor-specific */ 341 #define SHT_LOUSER 0x80000000 /* Start of application-specific */ 342 #define SHT_HIUSER 0x8fffffff /* End of application-specific */ 329 #define SHT_NULL 0 /* Section header table entry unused */ 330 #define SHT_PROGBITS 1 /* Program data */ 331 #define SHT_SYMTAB 2 /* Symbol table */ 332 #define SHT_STRTAB 3 /* String table */ 333 #define SHT_RELA 4 /* Relocation entries with addends */ 334 #define SHT_HASH 5 /* Symbol hash table */ 335 #define SHT_DYNAMIC 6 /* Dynamic linking information */ 336 #define SHT_NOTE 7 /* Notes */ 337 #define SHT_NOBITS 8 /* Program space with no data (bss) */ 338 #define SHT_REL 9 /* Relocation entries, no addends */ 339 #define SHT_SHLIB 10 /* Reserved */ 340 #define SHT_DYNSYM 11 /* Dynamic linker symbol table */ 341 #define SHT_INIT_ARRAY 14 /* Array of constructors */ 342 #define SHT_FINI_ARRAY 15 /* Array of destructors */ 343 #define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ 344 #define SHT_GROUP 17 /* Section group */ 345 #define SHT_SYMTAB_SHNDX 18 /* Extended section indices */ 346 #define SHT_NUM 19 /* Number of defined types. */ 347 #define SHT_LOOS 0x60000000 /* Start OS-specific. */ 348 #define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ 349 #define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ 350 #define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ 351 #define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ 352 #define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ 353 #define SHT_SUNW_move 0x6ffffffa 354 #define SHT_SUNW_COMDAT 0x6ffffffb 355 #define SHT_SUNW_syminfo 0x6ffffffc 356 #define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ 357 #define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ 358 #define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ 359 #define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ 360 #define SHT_HIOS 0x6fffffff /* End OS-specific type */ 361 #define SHT_LOPROC 0x70000000 /* Start of processor-specific */ 362 #define SHT_HIPROC 0x7fffffff /* End of processor-specific */ 363 #define SHT_LOUSER 0x80000000 /* Start of application-specific */ 364 #define SHT_HIUSER 0x8fffffff /* End of application-specific */ 343 365 344 366 /* Legal values for sh_flags (section flags). */ 345 367 346 #define SHF_WRITE (1 << 0) /* Writable */ 347 #define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ 348 #define SHF_EXECINSTR (1 << 2) /* Executable */ 349 #define SHF_MASKPROC 0xf0000000 /* Processor-specific */ 350 351 #define SHF_MERGE 0x10 352 #define SHF_STRINGS 0x20 353 #define SHF_INFO_LINK 0x40 354 #define SHF_LINK_ORDER 0x80 355 #define SHF_OS_NONCONFORMING 0x100 356 #define SHF_GROUP 0x200 357 #define SHF_TLS 0x400 358 #define SHF_MASKOS 0x0ff00000 359 #define SHF_ORDERED 0x40000000 360 #define SHF_EXCLUDE 0x80000000 368 #define SHF_WRITE (1 << 0) /* Writable */ 369 #define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ 370 #define SHF_EXECINSTR (1 << 2) /* Executable */ 371 #define SHF_MERGE (1 << 4) /* Might be merged */ 372 #define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ 373 #define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ 374 #define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ 375 #define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling 376 required */ 377 #define SHF_GROUP (1 << 9) /* Section is member of a group. */ 378 #define SHF_TLS (1 << 10) /* Section hold thread-local data. */ 379 #define SHF_COMPRESSED (1 << 11) /* Section with compressed data. */ 380 #define SHF_MASKOS 0x0ff00000 /* OS-specific. */ 381 #define SHF_MASKPROC 0xf0000000 /* Processor-specific */ 382 #define SHF_ORDERED (1 << 30) /* Special ordering requirement 383 (Solaris). */ 384 #define SHF_EXCLUDE (1 << 31) /* Section is excluded unless 385 referenced or allocated (Solaris).*/ 386 387 /* Section group handling. */ 388 #define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ 361 389 362 390 /* Symbol table entry. */ … … 364 392 typedef struct 365 393 { 366 Elf32_Word st_name;/* Symbol name (string tbl index) */367 Elf32_Addr st_value;/* Symbol value */368 Elf32_Word st_size;/* Symbol size */369 unsigned char st_info;/* Symbol type and binding */370 unsigned char st_other; /* No defined meaning, 0*/371 Elf32_Section st_shndx;/* Section index */372 } Elf32_Sym;373 374 typedef struct 375 { 376 Elf64_Word st_name;/* Symbol name (string tbl index) */377 unsigned char st_info;/* Symbol type and binding */378 unsigned char st_other; /* No defined meaning, 0*/379 Elf64_Section st_shndx;/* Section index */380 Elf64_Addr st_value;/* Symbol value */381 Elf64_Xword st_size;/* Symbol size */382 } Elf64_Sym;394 Elf32_Word st_name; /* Symbol name (string tbl index) */ 395 Elf32_Addr st_value; /* Symbol value */ 396 Elf32_Word st_size; /* Symbol size */ 397 unsigned char st_info; /* Symbol type and binding */ 398 unsigned char st_other; /* Symbol visibility */ 399 Elf32_Section st_shndx; /* Section index */ 400 } __attribute__((packed)) Elf32_Sym; 401 402 typedef struct 403 { 404 Elf64_Word st_name; /* Symbol name (string tbl index) */ 405 unsigned char st_info; /* Symbol type and binding */ 406 unsigned char st_other; /* Symbol visibility */ 407 Elf64_Section st_shndx; /* Section index */ 408 Elf64_Addr st_value; /* Symbol value */ 409 Elf64_Xword st_size; /* Symbol size */ 410 } __attribute__((packed)) Elf64_Sym; 383 411 384 412 /* The syminfo section if available contains additional information about … … 387 415 typedef struct 388 416 { 389 Elf32_Half si_boundto; 390 Elf32_Half si_flags; 391 } Elf32_Syminfo;392 393 typedef struct 394 { 395 Elf64_Half si_boundto; 396 Elf64_Half si_flags; 397 } Elf64_Syminfo;417 Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ 418 Elf32_Half si_flags; /* Per symbol flags */ 419 } __attribute__((packed)) Elf32_Syminfo; 420 421 typedef struct 422 { 423 Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ 424 Elf64_Half si_flags; /* Per symbol flags */ 425 } __attribute__((packed)) Elf64_Syminfo; 398 426 399 427 /* Possible values for si_boundto. */ 400 #define SYMINFO_BT_SELF 0xffff/* Symbol bound to self */401 #define SYMINFO_BT_PARENT 0xfffe/* Symbol bound to parent */402 #define SYMINFO_BT_LOWRESERVE 0xff00/* Beginning of reserved entries */428 #define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ 429 #define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ 430 #define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ 403 431 404 432 /* Possible bitmasks for si_flags. */ 405 #define SYMINFO_FLG_DIRECT 0x0001/* Direct bound symbol */406 #define SYMINFO_FLG_PASSTHRU 0x0002/* Pass-thru symbol for translator */407 #define SYMINFO_FLG_COPY 0x0004/* Symbol is a copy-reloc */408 #define SYMINFO_FLG_LAZYLOAD 0x0008/* Symbol bound to object to be lazy409 433 #define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ 434 #define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ 435 #define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ 436 #define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy 437 loaded */ 410 438 /* Syminfo version values. */ 411 #define SYMINFO_NONE 0 412 #define SYMINFO_CURRENT 1 413 #define SYMINFO_NUM 2 414 415 416 /* Special section index. */ 417 418 #define SHN_UNDEF 0 /* No section, undefined symbol. */ 439 #define SYMINFO_NONE 0 440 #define SYMINFO_CURRENT 1 441 #define SYMINFO_NUM 2 442 419 443 420 444 /* How to extract and insert information held in the st_info field. */ 421 445 422 #define ELF32_ST_BIND(val) 423 #define ELF32_ST_TYPE(val) 424 #define ELF32_ST_INFO(bind, type) 446 #define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) 447 #define ELF32_ST_TYPE(val) ((val) & 0xf) 448 #define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) 425 449 426 450 /* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ 427 #define ELF64_ST_BIND(val) 428 #define ELF64_ST_TYPE(val) 429 #define ELF64_ST_INFO(bind, type) 451 #define ELF64_ST_BIND(val) ELF32_ST_BIND (val) 452 #define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) 453 #define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) 430 454 431 455 /* Legal values for ST_BIND subfield of st_info (symbol binding). */ 432 456 433 #define STB_LOCAL 0 /* Local symbol */ 434 #define STB_GLOBAL 1 /* Global symbol */ 435 #define STB_WEAK 2 /* Weak symbol */ 436 #define STB_NUM 3 /* Number of defined types. */ 437 #define STB_LOOS 10 /* Start of OS-specific */ 438 #define STB_HIOS 12 /* End of OS-specific */ 439 #define STB_LOPROC 13 /* Start of processor-specific */ 440 #define STB_HIPROC 15 /* End of processor-specific */ 457 #define STB_LOCAL 0 /* Local symbol */ 458 #define STB_GLOBAL 1 /* Global symbol */ 459 #define STB_WEAK 2 /* Weak symbol */ 460 #define STB_NUM 3 /* Number of defined types. */ 461 #define STB_LOOS 10 /* Start of OS-specific */ 462 #define STB_GNU_UNIQUE 10 /* Unique symbol. */ 463 #define STB_HIOS 12 /* End of OS-specific */ 464 #define STB_LOPROC 13 /* Start of processor-specific */ 465 #define STB_HIPROC 15 /* End of processor-specific */ 441 466 442 467 /* Legal values for ST_TYPE subfield of st_info (symbol type). */ 443 468 444 #define STT_NOTYPE 0 /* Symbol type is unspecified */ 445 #define STT_OBJECT 1 /* Symbol is a data object */ 446 #define STT_FUNC 2 /* Symbol is a code object */ 447 #define STT_SECTION 3 /* Symbol associated with a section */ 448 #define STT_FILE 4 /* Symbol's name is file name */ 449 #define STT_NUM 5 /* Number of defined types. */ 450 #define STT_GNU_IFUNC 10 /* Symbol is a indirect code object */ 451 #define STT_LOOS 11 /* Start of OS-specific */ 452 #define STT_HIOS 12 /* End of OS-specific */ 453 #define STT_LOPROC 13 /* Start of processor-specific */ 454 #define STT_HIPROC 15 /* End of processor-specific */ 469 #define STT_NOTYPE 0 /* Symbol type is unspecified */ 470 #define STT_OBJECT 1 /* Symbol is a data object */ 471 #define STT_FUNC 2 /* Symbol is a code object */ 472 #define STT_SECTION 3 /* Symbol associated with a section */ 473 #define STT_FILE 4 /* Symbol's name is file name */ 474 #define STT_COMMON 5 /* Symbol is a common data object */ 475 #define STT_TLS 6 /* Symbol is thread-local data object*/ 476 #define STT_NUM 7 /* Number of defined types. */ 477 #define STT_LOOS 10 /* Start of OS-specific */ 478 #define STT_GNU_IFUNC 10 /* Symbol is indirect code object */ 479 #define STT_HIOS 12 /* End of OS-specific */ 480 #define STT_LOPROC 13 /* Start of processor-specific */ 481 #define STT_HIPROC 15 /* End of processor-specific */ 455 482 456 483 … … 459 486 the end of a chain, meaning no further symbols are found in that bucket. */ 460 487 461 #define STN_UNDEF 0/* End of a chain. */488 #define STN_UNDEF 0 /* End of a chain. */ 462 489 463 490 464 491 /* How to extract and insert information held in the st_other field. */ 465 492 466 #define ELF32_ST_VISIBILITY(o) 493 #define ELF32_ST_VISIBILITY(o) ((o) & 0x03) 467 494 468 495 /* For ELF64 the definitions are the same. */ 469 #define ELF64_ST_VISIBILITY(o) 496 #define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) 470 497 471 498 /* Symbol visibility specification encoded in the st_other field. */ 472 #define STV_DEFAULT 0/* Default symbol visibility rules */473 #define STV_INTERNAL 1/* Processor specific hidden class */474 #define STV_HIDDEN 2/* Sym unavailable in other modules */475 #define STV_PROTECTED 3/* Not preemptible, not exported */499 #define STV_DEFAULT 0 /* Default symbol visibility rules */ 500 #define STV_INTERNAL 1 /* Processor specific hidden class */ 501 #define STV_HIDDEN 2 /* Sym unavailable in other modules */ 502 #define STV_PROTECTED 3 /* Not preemptible, not exported */ 476 503 477 504 … … 480 507 typedef struct 481 508 { 482 Elf32_Addr r_offset;/* Address */483 Elf32_Word r_info;/* Relocation type and symbol index */484 } Elf32_Rel;509 Elf32_Addr r_offset; /* Address */ 510 Elf32_Word r_info; /* Relocation type and symbol index */ 511 } __attribute__((packed)) Elf32_Rel; 485 512 486 513 /* I have seen two different definitions of the Elf64_Rel and … … 491 518 typedef struct 492 519 { 493 Elf64_Addr r_offset;/* Address */494 Elf64_Xword r_info;/* Relocation type and symbol index */495 } Elf64_Rel;520 Elf64_Addr r_offset; /* Address */ 521 Elf64_Xword r_info; /* Relocation type and symbol index */ 522 } __attribute__((packed)) Elf64_Rel; 496 523 497 524 /* Relocation table entry with addend (in section of type SHT_RELA). */ … … 499 526 typedef struct 500 527 { 501 Elf32_Addr r_offset;/* Address */502 Elf32_Word r_info;/* Relocation type and symbol index */503 Elf32_Sword r_addend;/* Addend */504 } Elf32_Rela;505 506 typedef struct 507 { 508 Elf64_Addr r_offset;/* Address */509 Elf64_Xword r_info;/* Relocation type and symbol index */510 Elf64_Sxword r_addend;/* Addend */511 } Elf64_Rela;528 Elf32_Addr r_offset; /* Address */ 529 Elf32_Word r_info; /* Relocation type and symbol index */ 530 Elf32_Sword r_addend; /* Addend */ 531 } __attribute__((packed)) Elf32_Rela; 532 533 typedef struct 534 { 535 Elf64_Addr r_offset; /* Address */ 536 Elf64_Xword r_info; /* Relocation type and symbol index */ 537 Elf64_Sxword r_addend; /* Addend */ 538 } __attribute__((packed)) Elf64_Rela; 512 539 513 540 /* How to extract and insert information held in the r_info field. */ 514 541 515 #define ELF32_R_SYM(val) 516 #define ELF32_R_TYPE(val) 517 #define ELF32_R_INFO(sym, type) 518 519 #define ELF64_R_SYM(i) 520 #define ELF64_R_TYPE(i) 521 #define ELF64_R_INFO(sym,type) ((((Elf64_Xword)(sym)) << 32) + (type))542 #define ELF32_R_SYM(val) ((val) >> 8) 543 #define ELF32_R_TYPE(val) ((val) & 0xff) 544 #define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) 545 546 #define ELF64_R_SYM(i) ((i) >> 32) 547 #define ELF64_R_TYPE(i) ((i) & 0xffffffff) 548 #define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) 522 549 523 550 /* Program segment header. */ … … 525 552 typedef struct 526 553 { 527 Elf32_Word p_type; /* Segment type */ 528 Elf32_Off p_offset; /* Segment file offset */ 529 Elf32_Addr p_vaddr; /* Segment virtual address */ 530 Elf32_Addr p_paddr; /* Segment physical address */ 531 Elf32_Word p_filesz; /* Segment size in file */ 532 Elf32_Word p_memsz; /* Segment size in memory */ 533 Elf32_Word p_flags; /* Segment flags */ 534 Elf32_Word p_align; /* Segment alignment */ 535 } Elf32_Phdr; 536 537 typedef struct 538 { 539 Elf64_Word p_type; /* Segment type */ 540 Elf64_Word p_flags; /* Segment flags */ 541 Elf64_Off p_offset; /* Segment file offset */ 542 Elf64_Addr p_vaddr; /* Segment virtual address */ 543 Elf64_Addr p_paddr; /* Segment physical address */ 544 Elf64_Xword p_filesz; /* Segment size in file */ 545 Elf64_Xword p_memsz; /* Segment size in memory */ 546 Elf64_Xword p_align; /* Segment alignment */ 547 } Elf64_Phdr; 554 Elf32_Word p_type; /* Segment type */ 555 Elf32_Off p_offset; /* Segment file offset */ 556 Elf32_Addr p_vaddr; /* Segment virtual address */ 557 Elf32_Addr p_paddr; /* Segment physical address */ 558 Elf32_Word p_filesz; /* Segment size in file */ 559 Elf32_Word p_memsz; /* Segment size in memory */ 560 Elf32_Word p_flags; /* Segment flags */ 561 Elf32_Word p_align; /* Segment alignment */ 562 } __attribute__((packed)) Elf32_Phdr; 563 564 typedef struct 565 { 566 Elf64_Word p_type; /* Segment type */ 567 Elf64_Word p_flags; /* Segment flags */ 568 Elf64_Off p_offset; /* Segment file offset */ 569 Elf64_Addr p_vaddr; /* Segment virtual address */ 570 Elf64_Addr p_paddr; /* Segment physical address */ 571 Elf64_Xword p_filesz; /* Segment size in file */ 572 Elf64_Xword p_memsz; /* Segment size in memory */ 573 Elf64_Xword p_align; /* Segment alignment */ 574 } __attribute__((packed)) Elf64_Phdr; 575 576 /* Special value for e_phnum. This indicates that the real number of 577 program headers is too large to fit into e_phnum. Instead the real 578 value is in the field sh_info of section 0. */ 579 580 #define PN_XNUM 0xffff 548 581 549 582 /* Legal values for p_type (segment type). */ 550 583 551 #define PT_NULL 0 /* Program header table entry unused */ 552 #define PT_LOAD 1 /* Loadable program segment */ 553 #define PT_DYNAMIC 2 /* Dynamic linking information */ 554 #define PT_INTERP 3 /* Program interpreter */ 555 #define PT_NOTE 4 /* Auxiliary information */ 556 #define PT_SHLIB 5 /* Reserved */ 557 #define PT_PHDR 6 /* Entry for header table itself */ 558 #define PT_NUM 7 /* Number of defined types. */ 559 #define PT_LOOS 0x60000000 /* Start of OS-specific */ 560 #define PT_HIOS 0x6fffffff /* End of OS-specific */ 561 #define PT_LOPROC 0x70000000 /* Start of processor-specific */ 562 #define PT_HIPROC 0x7fffffff /* End of processor-specific */ 584 #define PT_NULL 0 /* Program header table entry unused */ 585 #define PT_LOAD 1 /* Loadable program segment */ 586 #define PT_DYNAMIC 2 /* Dynamic linking information */ 587 #define PT_INTERP 3 /* Program interpreter */ 588 #define PT_NOTE 4 /* Auxiliary information */ 589 #define PT_SHLIB 5 /* Reserved */ 590 #define PT_PHDR 6 /* Entry for header table itself */ 591 #define PT_TLS 7 /* Thread-local storage segment */ 592 #define PT_NUM 8 /* Number of defined types */ 593 #define PT_LOOS 0x60000000 /* Start of OS-specific */ 594 #define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ 595 #define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ 596 #define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ 597 #define PT_LOSUNW 0x6ffffffa 598 #define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ 599 #define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ 600 #define PT_HISUNW 0x6fffffff 601 #define PT_HIOS 0x6fffffff /* End of OS-specific */ 602 #define PT_LOPROC 0x70000000 /* Start of processor-specific */ 603 #define PT_HIPROC 0x7fffffff /* End of processor-specific */ 563 604 564 605 /* Legal values for p_flags (segment flags). */ 565 606 566 #define PF_X (1 << 0) /* Segment is executable */ 567 #define PF_W (1 << 1) /* Segment is writable */ 568 #define PF_R (1 << 2) /* Segment is readable */ 569 #define PF_MASKPROC 0xf0000000 /* Processor-specific */ 607 #define PF_X (1 << 0) /* Segment is executable */ 608 #define PF_W (1 << 1) /* Segment is writable */ 609 #define PF_R (1 << 2) /* Segment is readable */ 610 #define PF_MASKOS 0x0ff00000 /* OS-specific */ 611 #define PF_MASKPROC 0xf0000000 /* Processor-specific */ 570 612 571 613 /* Legal values for note segment descriptor types for core files. */ 572 614 573 #define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ 574 #define NT_FPREGSET 2 /* Contains copy of fpregset struct */ 575 #define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ 576 #define NT_PRXREG 4 /* Contains copy of prxregset struct */ 577 #define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ 578 #define NT_AUXV 6 /* Contains copy of auxv array */ 579 #define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ 580 #define NT_PSTATUS 10 /* Contains copy of pstatus struct */ 581 #define NT_PSINFO 13 /* Contains copy of psinfo struct */ 582 #define NT_PRCRED 14 /* Contains copy of prcred struct */ 583 #define NT_UTSNAME 15 /* Contains copy of utsname struct */ 584 #define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ 585 #define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ 586 587 /* Legal values for the note segment descriptor types for object files. */ 588 589 #define NT_VERSION 1 /* Contains a version string. */ 615 #define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ 616 #define NT_FPREGSET 2 /* Contains copy of fpregset struct */ 617 #define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ 618 #define NT_PRXREG 4 /* Contains copy of prxregset struct */ 619 #define NT_TASKSTRUCT 4 /* Contains copy of task structure */ 620 #define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ 621 #define NT_AUXV 6 /* Contains copy of auxv array */ 622 #define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ 623 #define NT_ASRS 8 /* Contains copy of asrset struct */ 624 #define NT_PSTATUS 10 /* Contains copy of pstatus struct */ 625 #define NT_PSINFO 13 /* Contains copy of psinfo struct */ 626 #define NT_PRCRED 14 /* Contains copy of prcred struct */ 627 #define NT_UTSNAME 15 /* Contains copy of utsname struct */ 628 #define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ 629 #define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ 630 #define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */ 631 #define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */ 632 #define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ 633 #define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */ 634 #define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ 635 #define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ 636 #define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ 637 #define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ 638 #define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */ 639 #define NT_S390_TIMER 0x301 /* s390 timer register */ 640 #define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */ 641 #define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ 642 #define NT_S390_CTRS 0x304 /* s390 control registers */ 643 #define NT_S390_PREFIX 0x305 /* s390 prefix register */ 644 #define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ 645 #define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ 646 #define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */ 647 #define NT_ARM_TLS 0x401 /* ARM TLS register */ 648 #define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */ 649 #define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */ 650 651 /* Legal values for the note segment descriptor types for object files. */ 652 653 #define NT_VERSION 1 /* Contains a version string. */ 590 654 591 655 … … 594 658 typedef struct 595 659 { 596 Elf32_Sword d_tag;/* Dynamic entry type */660 Elf32_Sword d_tag; /* Dynamic entry type */ 597 661 union 598 662 { 599 Elf32_Word d_val; 600 Elf32_Addr d_ptr; 663 Elf32_Word d_val; /* Integer value */ 664 Elf32_Addr d_ptr; /* Address value */ 601 665 } d_un; 602 } Elf32_Dyn;603 604 typedef struct 605 { 606 Elf64_Sxword d_tag;/* Dynamic entry type */666 } __attribute__((packed)) Elf32_Dyn; 667 668 typedef struct 669 { 670 Elf64_Sxword d_tag; /* Dynamic entry type */ 607 671 union 608 672 { 609 Elf64_Xword d_val; 610 Elf64_Addr d_ptr; 673 Elf64_Xword d_val; /* Integer value */ 674 Elf64_Addr d_ptr; /* Address value */ 611 675 } d_un; 612 } Elf64_Dyn;676 } __attribute__((packed)) Elf64_Dyn; 613 677 614 678 /* Legal values for d_tag (dynamic entry type). */ 615 679 616 #define DT_NULL 0 /* Marks end of dynamic section */ 617 #define DT_NEEDED 1 /* Name of needed library */ 618 #define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ 619 #define DT_PLTGOT 3 /* Processor defined value */ 620 #define DT_HASH 4 /* Address of symbol hash table */ 621 #define DT_STRTAB 5 /* Address of string table */ 622 #define DT_SYMTAB 6 /* Address of symbol table */ 623 #define DT_RELA 7 /* Address of Rela relocs */ 624 #define DT_RELASZ 8 /* Total size of Rela relocs */ 625 #define DT_RELAENT 9 /* Size of one Rela reloc */ 626 #define DT_STRSZ 10 /* Size of string table */ 627 #define DT_SYMENT 11 /* Size of one symbol table entry */ 628 #define DT_INIT 12 /* Address of init function */ 629 #define DT_FINI 13 /* Address of termination function */ 630 #define DT_SONAME 14 /* Name of shared object */ 631 #define DT_RPATH 15 /* Library search path */ 632 #define DT_SYMBOLIC 16 /* Start symbol search here */ 633 #define DT_REL 17 /* Address of Rel relocs */ 634 #define DT_RELSZ 18 /* Total size of Rel relocs */ 635 #define DT_RELENT 19 /* Size of one Rel reloc */ 636 #define DT_PLTREL 20 /* Type of reloc in PLT */ 637 #define DT_DEBUG 21 /* For debugging; unspecified */ 638 #define DT_TEXTREL 22 /* Reloc might modify .text */ 639 #define DT_JMPREL 23 /* Address of PLT relocs */ 640 #define DT_BIND_NOW 24 /* Process relocations of object */ 641 #define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ 642 #define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ 643 #define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ 644 #define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ 645 #define DT_NUM 29 /* Number used */ 646 #define DT_LOOS 0x60000000 /* Start of OS-specific */ 647 #define DT_HIOS 0x6fffffff /* End of OS-specific */ 648 #define DT_LOPROC 0x70000000 /* Start of processor-specific */ 649 #define DT_HIPROC 0x7fffffff /* End of processor-specific */ 650 #define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ 680 #define DT_NULL 0 /* Marks end of dynamic section */ 681 #define DT_NEEDED 1 /* Name of needed library */ 682 #define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ 683 #define DT_PLTGOT 3 /* Processor defined value */ 684 #define DT_HASH 4 /* Address of symbol hash table */ 685 #define DT_STRTAB 5 /* Address of string table */ 686 #define DT_SYMTAB 6 /* Address of symbol table */ 687 #define DT_RELA 7 /* Address of Rela relocs */ 688 #define DT_RELASZ 8 /* Total size of Rela relocs */ 689 #define DT_RELAENT 9 /* Size of one Rela reloc */ 690 #define DT_STRSZ 10 /* Size of string table */ 691 #define DT_SYMENT 11 /* Size of one symbol table entry */ 692 #define DT_INIT 12 /* Address of init function */ 693 #define DT_FINI 13 /* Address of termination function */ 694 #define DT_SONAME 14 /* Name of shared object */ 695 #define DT_RPATH 15 /* Library search path (deprecated) */ 696 #define DT_SYMBOLIC 16 /* Start symbol search here */ 697 #define DT_REL 17 /* Address of Rel relocs */ 698 #define DT_RELSZ 18 /* Total size of Rel relocs */ 699 #define DT_RELENT 19 /* Size of one Rel reloc */ 700 #define DT_PLTREL 20 /* Type of reloc in PLT */ 701 #define DT_DEBUG 21 /* For debugging; unspecified */ 702 #define DT_TEXTREL 22 /* Reloc might modify .text */ 703 #define DT_JMPREL 23 /* Address of PLT relocs */ 704 #define DT_BIND_NOW 24 /* Process relocations of object */ 705 #define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ 706 #define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ 707 #define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ 708 #define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ 709 #define DT_RUNPATH 29 /* Library search path */ 710 #define DT_FLAGS 30 /* Flags for the object being loaded */ 711 #define DT_ENCODING 32 /* Start of encoded range */ 712 #define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ 713 #define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ 714 #define DT_NUM 34 /* Number used */ 715 #define DT_LOOS 0x6000000d /* Start of OS-specific */ 716 #define DT_HIOS 0x6ffff000 /* End of OS-specific */ 717 #define DT_LOPROC 0x70000000 /* Start of processor-specific */ 718 #define DT_HIPROC 0x7fffffff /* End of processor-specific */ 719 #define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ 651 720 652 721 /* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the 653 722 Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's 654 723 approach. */ 655 #define DT_VALRNGLO 0x6ffffd00 656 #define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting 657 the following DT_* entry. */ 658 #define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ 659 #define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ 660 #define DT_VALRNGHI 0x6ffffdff 724 #define DT_VALRNGLO 0x6ffffd00 725 #define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ 726 #define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ 727 #define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ 728 #define DT_CHECKSUM 0x6ffffdf8 729 #define DT_PLTPADSZ 0x6ffffdf9 730 #define DT_MOVEENT 0x6ffffdfa 731 #define DT_MOVESZ 0x6ffffdfb 732 #define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ 733 #define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting 734 the following DT_* entry. */ 735 #define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ 736 #define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ 737 #define DT_VALRNGHI 0x6ffffdff 738 #define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ 739 #define DT_VALNUM 12 661 740 662 741 /* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the … … 665 744 If any adjustment is made to the ELF object after it has been 666 745 built these entries will need to be adjusted. */ 667 #define DT_ADDRRNGLO 0x6ffffe00 668 #define DT_SYMINFO 0x6ffffeff /* syminfo table */ 669 #define DT_ADDRRNGHI 0x6ffffeff 746 #define DT_ADDRRNGLO 0x6ffffe00 747 #define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */ 748 #define DT_TLSDESC_PLT 0x6ffffef6 749 #define DT_TLSDESC_GOT 0x6ffffef7 750 #define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ 751 #define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ 752 #define DT_CONFIG 0x6ffffefa /* Configuration information. */ 753 #define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ 754 #define DT_AUDIT 0x6ffffefc /* Object auditing. */ 755 #define DT_PLTPAD 0x6ffffefd /* PLT padding. */ 756 #define DT_MOVETAB 0x6ffffefe /* Move table. */ 757 #define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ 758 #define DT_ADDRRNGHI 0x6ffffeff 759 #define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ 760 #define DT_ADDRNUM 11 670 761 671 762 /* The versioning entry types. The next are defined as part of the 672 763 GNU extension. */ 673 #define DT_VERSYM 0x6ffffff0 764 #define DT_VERSYM 0x6ffffff0 765 766 #define DT_RELACOUNT 0x6ffffff9 767 #define DT_RELCOUNT 0x6ffffffa 674 768 675 769 /* These were chosen by Sun. */ 676 #define DT_FLAGS_1 0x6ffffffb/* State flags, see DF_1_* below. */677 #define DT_VERDEF 0x6ffffffc/* Address of version definition678 679 #define DT_VERDEFNUM 0x6ffffffd/* Number of version definitions */680 #define DT_VERNEED 0x6ffffffe/* Address of table with needed681 682 #define DT_VERNEEDNUM 0x6fffffff/* Number of needed versions */683 #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag))/* Reverse order! */770 #define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ 771 #define DT_VERDEF 0x6ffffffc /* Address of version definition 772 table */ 773 #define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ 774 #define DT_VERNEED 0x6ffffffe /* Address of table with needed 775 versions */ 776 #define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ 777 #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ 684 778 #define DT_VERSIONTAGNUM 16 685 779 … … 688 782 #define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ 689 783 #define DT_FILTER 0x7fffffff /* Shared object to get values from */ 690 #define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) 691 #define DT_EXTRANUM 3 784 #define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) 785 #define DT_EXTRANUM 3 786 787 /* Values of `d_un.d_val' in the DT_FLAGS entry. */ 788 #define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ 789 #define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ 790 #define DF_TEXTREL 0x00000004 /* Object contains text relocations */ 791 #define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ 792 #define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ 692 793 693 794 /* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 694 795 entry in the dynamic section. */ 695 #define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ 696 #define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ 697 #define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ 698 #define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ 699 #define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ 700 #define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ 701 #define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ 796 #define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ 797 #define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ 798 #define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ 799 #define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ 800 #define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ 801 #define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ 802 #define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ 803 #define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ 804 #define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ 805 #define DF_1_TRANS 0x00000200 806 #define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ 807 #define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ 808 #define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ 809 #define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ 810 #define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ 811 #define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ 812 #define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ 813 #define DF_1_NODIRECT 0x00020000 /* Object has no-direct binding. */ 814 #define DF_1_IGNMULDEF 0x00040000 815 #define DF_1_NOKSYMS 0x00080000 816 #define DF_1_NOHDR 0x00100000 817 #define DF_1_EDITED 0x00200000 /* Object is modified after built. */ 818 #define DF_1_NORELOC 0x00400000 819 #define DF_1_SYMINTPOSE 0x00800000 /* Object has individual interposers. */ 820 #define DF_1_GLOBAUDIT 0x01000000 /* Global auditing required. */ 821 #define DF_1_SINGLETON 0x02000000 /* Singleton symbols are used. */ 822 823 /* Flags for the feature selection in DT_FEATURE_1. */ 824 #define DTF_1_PARINIT 0x00000001 825 #define DTF_1_CONFEXP 0x00000002 826 827 /* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ 828 #define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ 829 #define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not 830 generally available. */ 702 831 703 832 /* Version definition sections. */ … … 705 834 typedef struct 706 835 { 707 Elf32_Half vd_version;/* Version revision */708 Elf32_Half vd_flags;/* Version information */709 Elf32_Half vd_ndx;/* Version Index */710 Elf32_Half vd_cnt;/* Number of associated aux entries */711 Elf32_Word vd_hash;/* Version name hash value */712 Elf32_Word vd_aux;/* Offset in bytes to verdaux array */713 Elf32_Word vd_next;/* Offset in bytes to next verdef714 715 } Elf32_Verdef;716 717 typedef struct 718 { 719 Elf64_Half vd_version;/* Version revision */720 Elf64_Half vd_flags;/* Version information */721 Elf64_Half vd_ndx;/* Version Index */722 Elf64_Half vd_cnt;/* Number of associated aux entries */723 Elf64_Word vd_hash;/* Version name hash value */724 Elf64_Word vd_aux;/* Offset in bytes to verdaux array */725 Elf64_Word vd_next;/* Offset in bytes to next verdef726 727 } Elf64_Verdef;836 Elf32_Half vd_version; /* Version revision */ 837 Elf32_Half vd_flags; /* Version information */ 838 Elf32_Half vd_ndx; /* Version Index */ 839 Elf32_Half vd_cnt; /* Number of associated aux entries */ 840 Elf32_Word vd_hash; /* Version name hash value */ 841 Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ 842 Elf32_Word vd_next; /* Offset in bytes to next verdef 843 entry */ 844 } __attribute__((packed)) Elf32_Verdef; 845 846 typedef struct 847 { 848 Elf64_Half vd_version; /* Version revision */ 849 Elf64_Half vd_flags; /* Version information */ 850 Elf64_Half vd_ndx; /* Version Index */ 851 Elf64_Half vd_cnt; /* Number of associated aux entries */ 852 Elf64_Word vd_hash; /* Version name hash value */ 853 Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ 854 Elf64_Word vd_next; /* Offset in bytes to next verdef 855 entry */ 856 } __attribute__((packed)) Elf64_Verdef; 728 857 729 858 730 859 /* Legal values for vd_version (version revision). */ 731 #define VER_DEF_NONE 0/* No version */732 #define VER_DEF_CURRENT 1/* Current version */733 #define VER_DEF_NUM 2/* Given version number */860 #define VER_DEF_NONE 0 /* No version */ 861 #define VER_DEF_CURRENT 1 /* Current version */ 862 #define VER_DEF_NUM 2 /* Given version number */ 734 863 735 864 /* Legal values for vd_flags (version information flags). */ 736 #define VER_FLG_BASE 0x1 /* Version definition of file itself */ 737 #define VER_FLG_WEAK 0x2 /* Weak version identifier */ 738 739 /* Auxialiary version information. */ 740 741 typedef struct 742 { 743 Elf32_Word vda_name; /* Version or dependency names */ 744 Elf32_Word vda_next; /* Offset in bytes to next verdaux 745 entry */ 746 } Elf32_Verdaux; 747 748 typedef struct 749 { 750 Elf64_Word vda_name; /* Version or dependency names */ 751 Elf64_Word vda_next; /* Offset in bytes to next verdaux 752 entry */ 753 } Elf64_Verdaux; 865 #define VER_FLG_BASE 0x1 /* Version definition of file itself */ 866 #define VER_FLG_WEAK 0x2 /* Weak version identifier */ 867 868 /* Versym symbol index values. */ 869 #define VER_NDX_LOCAL 0 /* Symbol is local. */ 870 #define VER_NDX_GLOBAL 1 /* Symbol is global. */ 871 #define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ 872 #define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ 873 874 /* Auxiliary version information. */ 875 876 typedef struct 877 { 878 Elf32_Word vda_name; /* Version or dependency names */ 879 Elf32_Word vda_next; /* Offset in bytes to next verdaux 880 entry */ 881 } __attribute__((packed)) Elf32_Verdaux; 882 883 typedef struct 884 { 885 Elf64_Word vda_name; /* Version or dependency names */ 886 Elf64_Word vda_next; /* Offset in bytes to next verdaux 887 entry */ 888 } __attribute__((packed)) Elf64_Verdaux; 754 889 755 890 … … 758 893 typedef struct 759 894 { 760 Elf32_Half vn_version;/* Version of structure */761 Elf32_Half vn_cnt;/* Number of associated aux entries */762 Elf32_Word vn_file;/* Offset of filename for this763 764 Elf32_Word vn_aux;/* Offset in bytes to vernaux array */765 Elf32_Word vn_next;/* Offset in bytes to next verneed766 767 } Elf32_Verneed;768 769 typedef struct 770 { 771 Elf64_Half vn_version;/* Version of structure */772 Elf64_Half vn_cnt;/* Number of associated aux entries */773 Elf64_Word vn_file;/* Offset of filename for this774 775 Elf64_Word vn_aux;/* Offset in bytes to vernaux array */776 Elf64_Word vn_next;/* Offset in bytes to next verneed777 778 } Elf64_Verneed;895 Elf32_Half vn_version; /* Version of structure */ 896 Elf32_Half vn_cnt; /* Number of associated aux entries */ 897 Elf32_Word vn_file; /* Offset of filename for this 898 dependency */ 899 Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ 900 Elf32_Word vn_next; /* Offset in bytes to next verneed 901 entry */ 902 } __attribute__((packed)) Elf32_Verneed; 903 904 typedef struct 905 { 906 Elf64_Half vn_version; /* Version of structure */ 907 Elf64_Half vn_cnt; /* Number of associated aux entries */ 908 Elf64_Word vn_file; /* Offset of filename for this 909 dependency */ 910 Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ 911 Elf64_Word vn_next; /* Offset in bytes to next verneed 912 entry */ 913 } __attribute__((packed)) Elf64_Verneed; 779 914 780 915 781 916 /* Legal values for vn_version (version revision). */ 782 #define VER_NEED_NONE 0/* No version */783 #define VER_NEED_CURRENT 1 784 #define VER_NEED_NUM 2/* Given version number */917 #define VER_NEED_NONE 0 /* No version */ 918 #define VER_NEED_CURRENT 1 /* Current version */ 919 #define VER_NEED_NUM 2 /* Given version number */ 785 920 786 921 /* Auxiliary needed version information. */ … … 788 923 typedef struct 789 924 { 790 Elf32_Word vna_hash;/* Hash value of dependency name */791 Elf32_Half vna_flags;/* Dependency specific information */792 Elf32_Half vna_other;/* Unused */793 Elf32_Word vna_name;/* Dependency name string offset */794 Elf32_Word vna_next;/* Offset in bytes to next vernaux795 796 } Elf32_Vernaux;797 798 typedef struct 799 { 800 Elf64_Word vna_hash;/* Hash value of dependency name */801 Elf64_Half vna_flags;/* Dependency specific information */802 Elf64_Half vna_other;/* Unused */803 Elf64_Word vna_name;/* Dependency name string offset */804 Elf64_Word vna_next;/* Offset in bytes to next vernaux805 806 } Elf64_Vernaux;925 Elf32_Word vna_hash; /* Hash value of dependency name */ 926 Elf32_Half vna_flags; /* Dependency specific information */ 927 Elf32_Half vna_other; /* Unused */ 928 Elf32_Word vna_name; /* Dependency name string offset */ 929 Elf32_Word vna_next; /* Offset in bytes to next vernaux 930 entry */ 931 } __attribute__((packed)) Elf32_Vernaux; 932 933 typedef struct 934 { 935 Elf64_Word vna_hash; /* Hash value of dependency name */ 936 Elf64_Half vna_flags; /* Dependency specific information */ 937 Elf64_Half vna_other; /* Unused */ 938 Elf64_Word vna_name; /* Dependency name string offset */ 939 Elf64_Word vna_next; /* Offset in bytes to next vernaux 940 entry */ 941 } __attribute__((packed)) Elf64_Vernaux; 807 942 808 943 809 944 /* Legal values for vna_flags. */ 810 #define VER_FLG_WEAK 0x2/* Weak version identifier */945 #define VER_FLG_WEAK 0x2 /* Weak version identifier */ 811 946 812 947 … … 822 957 typedef struct 823 958 { 824 int a_type;/* Entry type */959 uint32_t a_type; /* Entry type */ 825 960 union 826 961 { 827 long int a_val; /* Integer value */ 828 void *a_ptr; /* Pointer value */ 829 void (*a_fcn) (void); /* Function pointer value */ 962 uint32_t a_val; /* Integer value */ 963 /* We use to have pointer elements added here. We cannot do that, 964 though, since it does not work when using 32-bit definitions 965 on 64-bit platforms and vice versa. */ 830 966 } a_un; 831 } Elf32_auxv_t;832 833 typedef struct 834 { 835 long int a_type;/* Entry type */967 } __attribute__((packed)) Elf32_auxv_t; 968 969 typedef struct 970 { 971 uint64_t a_type; /* Entry type */ 836 972 union 837 973 { 838 long int a_val; /* Integer value */ 839 void *a_ptr; /* Pointer value */ 840 void (*a_fcn) (void); /* Function pointer value */ 974 uint64_t a_val; /* Integer value */ 975 /* We use to have pointer elements added here. We cannot do that, 976 though, since it does not work when using 32-bit definitions 977 on 64-bit platforms and vice versa. */ 841 978 } a_un; 842 } Elf64_auxv_t;979 } __attribute__((packed)) Elf64_auxv_t; 843 980 844 981 /* Legal values for a_type (entry type). */ 845 982 846 #define AT_NULL 0 /* End of vector */ 847 #define AT_IGNORE 1 /* Entry should be ignored */ 848 #define AT_EXECFD 2 /* File descriptor of program */ 849 #define AT_PHDR 3 /* Program headers for program */ 850 #define AT_PHENT 4 /* Size of program header entry */ 851 #define AT_PHNUM 5 /* Number of program headers */ 852 #define AT_PAGESZ 6 /* System page size */ 853 #define AT_BASE 7 /* Base address of interpreter */ 854 #define AT_FLAGS 8 /* Flags */ 855 #define AT_ENTRY 9 /* Entry point of program */ 856 #define AT_NOTELF 10 /* Program is not ELF */ 857 #define AT_UID 11 /* Real uid */ 858 #define AT_EUID 12 /* Effective uid */ 859 #define AT_GID 13 /* Real gid */ 860 #define AT_EGID 14 /* Effective gid */ 983 #define AT_NULL 0 /* End of vector */ 984 #define AT_IGNORE 1 /* Entry should be ignored */ 985 #define AT_EXECFD 2 /* File descriptor of program */ 986 #define AT_PHDR 3 /* Program headers for program */ 987 #define AT_PHENT 4 /* Size of program header entry */ 988 #define AT_PHNUM 5 /* Number of program headers */ 989 #define AT_PAGESZ 6 /* System page size */ 990 #define AT_BASE 7 /* Base address of interpreter */ 991 #define AT_FLAGS 8 /* Flags */ 992 #define AT_ENTRY 9 /* Entry point of program */ 993 #define AT_NOTELF 10 /* Program is not ELF */ 994 #define AT_UID 11 /* Real uid */ 995 #define AT_EUID 12 /* Effective uid */ 996 #define AT_GID 13 /* Real gid */ 997 #define AT_EGID 14 /* Effective gid */ 998 #define AT_CLKTCK 17 /* Frequency of times() */ 861 999 862 1000 /* Some more special a_type values describing the hardware. */ 863 #define AT_PLATFORM 15/* String identifying platform. */864 #define AT_HWCAP 16/* Machine dependent hints about865 1001 #define AT_PLATFORM 15 /* String identifying platform. */ 1002 #define AT_HWCAP 16 /* Machine dependent hints about 1003 processor capabilities. */ 866 1004 867 1005 /* This entry gives some information about the FPU initialization 868 1006 performed by the kernel. */ 869 #define AT_FPUCW 17 /* Used FPU control word. */ 870 1007 #define AT_FPUCW 18 /* Used FPU control word. */ 1008 1009 /* Cache block sizes. */ 1010 #define AT_DCACHEBSIZE 19 /* Data cache block size. */ 1011 #define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ 1012 #define AT_UCACHEBSIZE 21 /* Unified cache block size. */ 1013 1014 /* A special ignored value for PPC, used by the kernel to control the 1015 interpretation of the AUXV. Must be > 16. */ 1016 #define AT_IGNOREPPC 22 /* Entry should be ignored. */ 1017 1018 #define AT_SECURE 23 /* Boolean, was exec setuid-like? */ 1019 1020 #define AT_BASE_PLATFORM 24 /* String identifying real platforms.*/ 1021 1022 #define AT_RANDOM 25 /* Address of 16 random bytes. */ 1023 1024 #define AT_EXECFN 31 /* Filename of executable. */ 1025 1026 /* Pointer to the global system page used for system calls and other 1027 nice things. */ 1028 #define AT_SYSINFO 32 1029 #define AT_SYSINFO_EHDR 33 1030 1031 /* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains 1032 log2 of line size; mask those to get cache size. */ 1033 #define AT_L1I_CACHESHAPE 34 1034 #define AT_L1D_CACHESHAPE 35 1035 #define AT_L2_CACHESHAPE 36 1036 #define AT_L3_CACHESHAPE 37 871 1037 872 1038 /* Note section contents. Each entry in the note section begins with … … 875 1041 typedef struct 876 1042 { 877 Elf32_Word n_namesz; 878 Elf32_Word n_descsz; 879 Elf32_Word n_type; 880 } Elf32_Nhdr;881 882 typedef struct 883 { 884 Elf64_Word n_namesz; 885 Elf64_Word n_descsz; 886 Elf64_Word n_type; 887 } Elf64_Nhdr;1043 Elf32_Word n_namesz; /* Length of the note's name. */ 1044 Elf32_Word n_descsz; /* Length of the note's descriptor. */ 1045 Elf32_Word n_type; /* Type of the note. */ 1046 } __attribute__((packed)) Elf32_Nhdr; 1047 1048 typedef struct 1049 { 1050 Elf64_Word n_namesz; /* Length of the note's name. */ 1051 Elf64_Word n_descsz; /* Length of the note's descriptor. */ 1052 Elf64_Word n_type; /* Type of the note. */ 1053 } __attribute__((packed)) Elf64_Nhdr; 888 1054 889 1055 /* Known names of notes. */ 890 1056 891 1057 /* Solaris entries in the note section have this name. */ 892 #define ELF_NOTE_SOLARIS 1058 #define ELF_NOTE_SOLARIS "SUNW Solaris" 893 1059 894 1060 /* Note entries for GNU systems have this name. */ 895 #define ELF_NOTE_GNU 1061 #define ELF_NOTE_GNU "GNU" 896 1062 897 1063 … … 899 1065 900 1066 /* Value of descriptor (one word) is desired pagesize for the binary. */ 901 #define ELF_NOTE_PAGESIZE_HINT 1067 #define ELF_NOTE_PAGESIZE_HINT 1 902 1068 903 1069 … … 910 1076 word 3: subminor version of the ABI 911 1077 */ 912 #define ELF_NOTE_ABI 1 913 914 /* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI 915 note section entry. */ 916 #define ELF_NOTE_OS_LINUX 0 917 #define ELF_NOTE_OS_GNU 1 918 #define ELF_NOTE_OS_SOLARIS2 2 1078 #define NT_GNU_ABI_TAG 1 1079 #define ELF_NOTE_ABI NT_GNU_ABI_TAG /* Old name. */ 1080 1081 /* Known OSes. These values can appear in word 0 of an 1082 NT_GNU_ABI_TAG note section entry. */ 1083 #define ELF_NOTE_OS_LINUX 0 1084 #define ELF_NOTE_OS_GNU 1 1085 #define ELF_NOTE_OS_SOLARIS2 2 1086 #define ELF_NOTE_OS_FREEBSD 3 1087 1088 /* Synthetic hwcap information. The descriptor begins with two words: 1089 word 0: number of entries 1090 word 1: bitmask of enabled entries 1091 Then follow variable-length entries, one byte followed by a 1092 '\0'-terminated hwcap name string. The byte gives the bit 1093 number to test if enabled, (1U << bit) & bitmask. */ 1094 #define NT_GNU_HWCAP 2 1095 1096 /* Build ID bits as generated by ld --build-id. 1097 The descriptor consists of any nonzero number of bytes. */ 1098 #define NT_GNU_BUILD_ID 3 1099 1100 /* Version note generated by GNU gold containing a version string. */ 1101 #define NT_GNU_GOLD_VERSION 4 1102 1103 1104 /* Move records. */ 1105 typedef struct 1106 { 1107 Elf32_Xword m_value; /* Symbol value. */ 1108 Elf32_Word m_info; /* Size and index. */ 1109 Elf32_Word m_poffset; /* Symbol offset. */ 1110 Elf32_Half m_repeat; /* Repeat count. */ 1111 Elf32_Half m_stride; /* Stride info. */ 1112 } __attribute__((packed)) Elf32_Move; 1113 1114 typedef struct 1115 { 1116 Elf64_Xword m_value; /* Symbol value. */ 1117 Elf64_Xword m_info; /* Size and index. */ 1118 Elf64_Xword m_poffset; /* Symbol offset. */ 1119 Elf64_Half m_repeat; /* Repeat count. */ 1120 Elf64_Half m_stride; /* Stride info. */ 1121 } __attribute__((packed)) Elf64_Move; 1122 1123 /* Macro to construct move records. */ 1124 #define ELF32_M_SYM(info) ((info) >> 8) 1125 #define ELF32_M_SIZE(info) ((unsigned char) (info)) 1126 #define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) 1127 1128 #define ELF64_M_SYM(info) ELF32_M_SYM (info) 1129 #define ELF64_M_SIZE(info) ELF32_M_SIZE (info) 1130 #define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) 919 1131 920 1132 921 1133 /* Motorola 68k specific definitions. */ 922 1134 1135 /* Values for Elf32_Ehdr.e_flags. */ 1136 #define EF_CPU32 0x00810000 1137 923 1138 /* m68k relocs. */ 924 1139 925 #define R_68K_NONE 0 /* No reloc */ 926 #define R_68K_32 1 /* Direct 32 bit */ 927 #define R_68K_16 2 /* Direct 16 bit */ 928 #define R_68K_8 3 /* Direct 8 bit */ 929 #define R_68K_PC32 4 /* PC relative 32 bit */ 930 #define R_68K_PC16 5 /* PC relative 16 bit */ 931 #define R_68K_PC8 6 /* PC relative 8 bit */ 932 #define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ 933 #define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ 934 #define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ 935 #define R_68K_GOT32O 10 /* 32 bit GOT offset */ 936 #define R_68K_GOT16O 11 /* 16 bit GOT offset */ 937 #define R_68K_GOT8O 12 /* 8 bit GOT offset */ 938 #define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ 939 #define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ 940 #define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ 941 #define R_68K_PLT32O 16 /* 32 bit PLT offset */ 942 #define R_68K_PLT16O 17 /* 16 bit PLT offset */ 943 #define R_68K_PLT8O 18 /* 8 bit PLT offset */ 944 #define R_68K_COPY 19 /* Copy symbol at runtime */ 945 #define R_68K_GLOB_DAT 20 /* Create GOT entry */ 946 #define R_68K_JMP_SLOT 21 /* Create PLT entry */ 947 #define R_68K_RELATIVE 22 /* Adjust by program base */ 1140 #define R_68K_NONE 0 /* No reloc */ 1141 #define R_68K_32 1 /* Direct 32 bit */ 1142 #define R_68K_16 2 /* Direct 16 bit */ 1143 #define R_68K_8 3 /* Direct 8 bit */ 1144 #define R_68K_PC32 4 /* PC relative 32 bit */ 1145 #define R_68K_PC16 5 /* PC relative 16 bit */ 1146 #define R_68K_PC8 6 /* PC relative 8 bit */ 1147 #define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ 1148 #define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ 1149 #define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ 1150 #define R_68K_GOT32O 10 /* 32 bit GOT offset */ 1151 #define R_68K_GOT16O 11 /* 16 bit GOT offset */ 1152 #define R_68K_GOT8O 12 /* 8 bit GOT offset */ 1153 #define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ 1154 #define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ 1155 #define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ 1156 #define R_68K_PLT32O 16 /* 32 bit PLT offset */ 1157 #define R_68K_PLT16O 17 /* 16 bit PLT offset */ 1158 #define R_68K_PLT8O 18 /* 8 bit PLT offset */ 1159 #define R_68K_COPY 19 /* Copy symbol at runtime */ 1160 #define R_68K_GLOB_DAT 20 /* Create GOT entry */ 1161 #define R_68K_JMP_SLOT 21 /* Create PLT entry */ 1162 #define R_68K_RELATIVE 22 /* Adjust by program base */ 1163 #define R_68K_TLS_GD32 25 /* 32 bit GOT offset for GD */ 1164 #define R_68K_TLS_GD16 26 /* 16 bit GOT offset for GD */ 1165 #define R_68K_TLS_GD8 27 /* 8 bit GOT offset for GD */ 1166 #define R_68K_TLS_LDM32 28 /* 32 bit GOT offset for LDM */ 1167 #define R_68K_TLS_LDM16 29 /* 16 bit GOT offset for LDM */ 1168 #define R_68K_TLS_LDM8 30 /* 8 bit GOT offset for LDM */ 1169 #define R_68K_TLS_LDO32 31 /* 32 bit module-relative offset */ 1170 #define R_68K_TLS_LDO16 32 /* 16 bit module-relative offset */ 1171 #define R_68K_TLS_LDO8 33 /* 8 bit module-relative offset */ 1172 #define R_68K_TLS_IE32 34 /* 32 bit GOT offset for IE */ 1173 #define R_68K_TLS_IE16 35 /* 16 bit GOT offset for IE */ 1174 #define R_68K_TLS_IE8 36 /* 8 bit GOT offset for IE */ 1175 #define R_68K_TLS_LE32 37 /* 32 bit offset relative to 1176 static TLS block */ 1177 #define R_68K_TLS_LE16 38 /* 16 bit offset relative to 1178 static TLS block */ 1179 #define R_68K_TLS_LE8 39 /* 8 bit offset relative to 1180 static TLS block */ 1181 #define R_68K_TLS_DTPMOD32 40 /* 32 bit module number */ 1182 #define R_68K_TLS_DTPREL32 41 /* 32 bit module-relative offset */ 1183 #define R_68K_TLS_TPREL32 42 /* 32 bit TP-relative offset */ 948 1184 /* Keep this the last entry. */ 949 #define R_68K_NUM 231185 #define R_68K_NUM 43 950 1186 951 1187 /* Intel 80386 specific definitions. */ … … 953 1189 /* i386 relocs. */ 954 1190 955 #define R_386_NONE 0 /* No reloc */ 956 #define R_386_32 1 /* Direct 32 bit */ 957 #define R_386_PC32 2 /* PC relative 32 bit */ 958 #define R_386_GOT32 3 /* 32 bit GOT entry */ 959 #define R_386_PLT32 4 /* 32 bit PLT address */ 960 #define R_386_COPY 5 /* Copy symbol at runtime */ 961 #define R_386_GLOB_DAT 6 /* Create GOT entry */ 962 #define R_386_JMP_SLOT 7 /* Create PLT entry */ 963 #define R_386_RELATIVE 8 /* Adjust by program base */ 964 #define R_386_GOTOFF 9 /* 32 bit offset to GOT */ 965 #define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ 1191 #define R_386_NONE 0 /* No reloc */ 1192 #define R_386_32 1 /* Direct 32 bit */ 1193 #define R_386_PC32 2 /* PC relative 32 bit */ 1194 #define R_386_GOT32 3 /* 32 bit GOT entry */ 1195 #define R_386_PLT32 4 /* 32 bit PLT address */ 1196 #define R_386_COPY 5 /* Copy symbol at runtime */ 1197 #define R_386_GLOB_DAT 6 /* Create GOT entry */ 1198 #define R_386_JMP_SLOT 7 /* Create PLT entry */ 1199 #define R_386_RELATIVE 8 /* Adjust by program base */ 1200 #define R_386_GOTOFF 9 /* 32 bit offset to GOT */ 1201 #define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ 1202 #define R_386_32PLT 11 1203 #define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ 1204 #define R_386_TLS_IE 15 /* Address of GOT entry for static TLS 1205 block offset */ 1206 #define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block 1207 offset */ 1208 #define R_386_TLS_LE 17 /* Offset relative to static TLS 1209 block */ 1210 #define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of 1211 general dynamic thread local data */ 1212 #define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of 1213 local dynamic thread local data 1214 in LE code */ 1215 #define R_386_16 20 1216 #define R_386_PC16 21 1217 #define R_386_8 22 1218 #define R_386_PC8 23 1219 #define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic 1220 thread local data */ 1221 #define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ 1222 #define R_386_TLS_GD_CALL 26 /* Relocation for call to 1223 __tls_get_addr() */ 1224 #define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ 1225 #define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic 1226 thread local data in LE code */ 1227 #define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ 1228 #define R_386_TLS_LDM_CALL 30 /* Relocation for call to 1229 __tls_get_addr() in LDM code */ 1230 #define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ 1231 #define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ 1232 #define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS 1233 block offset */ 1234 #define R_386_TLS_LE_32 34 /* Negated offset relative to static 1235 TLS block */ 1236 #define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ 1237 #define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ 1238 #define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ 1239 /* 38? */ 1240 #define R_386_TLS_GOTDESC 39 /* GOT offset for TLS descriptor. */ 1241 #define R_386_TLS_DESC_CALL 40 /* Marker of call through TLS 1242 descriptor for 1243 relaxation. */ 1244 #define R_386_TLS_DESC 41 /* TLS descriptor containing 1245 pointer to code and to 1246 argument, returning the TLS 1247 offset for the symbol. */ 1248 #define R_386_IRELATIVE 42 /* Adjust indirectly by program base */ 1249 #define R_386_GOT32X 43 /* 32 bit GOT entry, relaxable */ 966 1250 /* Keep this the last entry. */ 967 #define R_386_NUM 11 968 969 /* TCC-specific 16-bit relocs. */ 970 #define R_386_16 12 /* Direct 16 bit */ 971 #define R_386_PC16 13 /* PC relative 16 bit */ 1251 #define R_386_NUM 44 972 1252 973 1253 /* SUN SPARC specific definitions. */ 974 1254 1255 /* Legal values for ST_TYPE subfield of st_info (symbol type). */ 1256 1257 #define STT_SPARC_REGISTER 13 /* Global register reserved to app. */ 1258 975 1259 /* Values for Elf64_Ehdr.e_flags. */ 976 1260 977 #define EF_SPARCV9_MM 3 978 #define EF_SPARCV9_TSO 0 979 #define EF_SPARCV9_PSO 1 980 #define EF_SPARCV9_RMO 2 981 #define EF_SPARC_EXT_MASK 0xFFFF00 982 #define EF_SPARC_SUN_US1 0x000200 983 #define EF_SPARC_HAL_R1 0x000400 1261 #define EF_SPARCV9_MM 3 1262 #define EF_SPARCV9_TSO 0 1263 #define EF_SPARCV9_PSO 1 1264 #define EF_SPARCV9_RMO 2 1265 #define EF_SPARC_LEDATA 0x800000 /* little endian data */ 1266 #define EF_SPARC_EXT_MASK 0xFFFF00 1267 #define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ 1268 #define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ 1269 #define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ 1270 #define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ 984 1271 985 1272 /* SPARC relocs. */ 986 1273 987 #define R_SPARC_NONE 0/* No reloc */988 #define R_SPARC_8 1/* Direct 8 bit */989 #define R_SPARC_16 2/* Direct 16 bit */990 #define R_SPARC_32 3/* Direct 32 bit */991 #define R_SPARC_DISP8 4/* PC relative 8 bit */992 #define R_SPARC_DISP16 5/* PC relative 16 bit */993 #define R_SPARC_DISP32 6/* PC relative 32 bit */994 #define R_SPARC_WDISP30 7/* PC relative 30 bit shifted */995 #define R_SPARC_WDISP22 8/* PC relative 22 bit shifted */996 #define R_SPARC_HI22 9/* High 22 bit */997 #define R_SPARC_22 10/* Direct 22 bit */998 #define R_SPARC_13 11/* Direct 13 bit */999 #define R_SPARC_LO10 12/* Truncated 10 bit */1000 #define R_SPARC_GOT10 13/* Truncated 10 bit GOT entry */1001 #define R_SPARC_GOT13 14/* 13 bit GOT entry */1002 #define R_SPARC_GOT22 15/* 22 bit GOT entry shifted */1003 #define R_SPARC_PC10 16/* PC relative 10 bit truncated */1004 #define R_SPARC_PC22 17/* PC relative 22 bit shifted */1005 #define R_SPARC_WPLT30 18/* 30 bit PC relative PLT address */1006 #define R_SPARC_COPY 19/* Copy symbol at runtime */1007 #define R_SPARC_GLOB_DAT 20/* Create GOT entry */1008 #define R_SPARC_JMP_SLOT 21/* Create PLT entry */1009 #define R_SPARC_RELATIVE 22/* Adjust by program base */1010 #define R_SPARC_UA32 23/* Direct 32 bit unaligned */1274 #define R_SPARC_NONE 0 /* No reloc */ 1275 #define R_SPARC_8 1 /* Direct 8 bit */ 1276 #define R_SPARC_16 2 /* Direct 16 bit */ 1277 #define R_SPARC_32 3 /* Direct 32 bit */ 1278 #define R_SPARC_DISP8 4 /* PC relative 8 bit */ 1279 #define R_SPARC_DISP16 5 /* PC relative 16 bit */ 1280 #define R_SPARC_DISP32 6 /* PC relative 32 bit */ 1281 #define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ 1282 #define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ 1283 #define R_SPARC_HI22 9 /* High 22 bit */ 1284 #define R_SPARC_22 10 /* Direct 22 bit */ 1285 #define R_SPARC_13 11 /* Direct 13 bit */ 1286 #define R_SPARC_LO10 12 /* Truncated 10 bit */ 1287 #define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ 1288 #define R_SPARC_GOT13 14 /* 13 bit GOT entry */ 1289 #define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ 1290 #define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ 1291 #define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ 1292 #define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ 1293 #define R_SPARC_COPY 19 /* Copy symbol at runtime */ 1294 #define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ 1295 #define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ 1296 #define R_SPARC_RELATIVE 22 /* Adjust by program base */ 1297 #define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ 1011 1298 1012 1299 /* Additional Sparc64 relocs. */ 1013 1300 1014 #define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ 1015 #define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ 1016 #define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ 1017 #define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ 1018 #define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ 1019 #define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ 1020 #define R_SPARC_10 30 /* Direct 10 bit */ 1021 #define R_SPARC_11 31 /* Direct 11 bit */ 1022 #define R_SPARC_64 32 /* Direct 64 bit */ 1023 #define R_SPARC_OLO10 33 /* ?? */ 1024 #define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ 1025 #define R_SPARC_HM10 35 /* High middle 10 bits of ... */ 1026 #define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ 1027 #define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ 1028 #define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ 1029 #define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ 1030 #define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ 1031 #define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ 1032 #define R_SPARC_7 43 /* Direct 7 bit */ 1033 #define R_SPARC_5 44 /* Direct 5 bit */ 1034 #define R_SPARC_6 45 /* Direct 6 bit */ 1035 #define R_SPARC_DISP64 46 /* PC relative 64 bit */ 1036 #define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ 1037 #define R_SPARC_HIX22 48 /* High 22 bit complemented */ 1038 #define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ 1039 #define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ 1040 #define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ 1041 #define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ 1042 #define R_SPARC_REGISTER 53 /* Global register usage */ 1043 #define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ 1044 #define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ 1301 #define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ 1302 #define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ 1303 #define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ 1304 #define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ 1305 #define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ 1306 #define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ 1307 #define R_SPARC_10 30 /* Direct 10 bit */ 1308 #define R_SPARC_11 31 /* Direct 11 bit */ 1309 #define R_SPARC_64 32 /* Direct 64 bit */ 1310 #define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ 1311 #define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ 1312 #define R_SPARC_HM10 35 /* High middle 10 bits of ... */ 1313 #define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ 1314 #define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ 1315 #define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ 1316 #define R_SPARC_PC_LM22 39 /* Low middle 22 bits of ... */ 1317 #define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ 1318 #define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ 1319 #define R_SPARC_GLOB_JMP 42 /* was part of v9 ABI but was removed */ 1320 #define R_SPARC_7 43 /* Direct 7 bit */ 1321 #define R_SPARC_5 44 /* Direct 5 bit */ 1322 #define R_SPARC_6 45 /* Direct 6 bit */ 1323 #define R_SPARC_DISP64 46 /* PC relative 64 bit */ 1324 #define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ 1325 #define R_SPARC_HIX22 48 /* High 22 bit complemented */ 1326 #define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ 1327 #define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ 1328 #define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ 1329 #define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ 1330 #define R_SPARC_REGISTER 53 /* Global register usage */ 1331 #define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ 1332 #define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ 1333 #define R_SPARC_TLS_GD_HI22 56 1334 #define R_SPARC_TLS_GD_LO10 57 1335 #define R_SPARC_TLS_GD_ADD 58 1336 #define R_SPARC_TLS_GD_CALL 59 1337 #define R_SPARC_TLS_LDM_HI22 60 1338 #define R_SPARC_TLS_LDM_LO10 61 1339 #define R_SPARC_TLS_LDM_ADD 62 1340 #define R_SPARC_TLS_LDM_CALL 63 1341 #define R_SPARC_TLS_LDO_HIX22 64 1342 #define R_SPARC_TLS_LDO_LOX10 65 1343 #define R_SPARC_TLS_LDO_ADD 66 1344 #define R_SPARC_TLS_IE_HI22 67 1345 #define R_SPARC_TLS_IE_LO10 68 1346 #define R_SPARC_TLS_IE_LD 69 1347 #define R_SPARC_TLS_IE_LDX 70 1348 #define R_SPARC_TLS_IE_ADD 71 1349 #define R_SPARC_TLS_LE_HIX22 72 1350 #define R_SPARC_TLS_LE_LOX10 73 1351 #define R_SPARC_TLS_DTPMOD32 74 1352 #define R_SPARC_TLS_DTPMOD64 75 1353 #define R_SPARC_TLS_DTPOFF32 76 1354 #define R_SPARC_TLS_DTPOFF64 77 1355 #define R_SPARC_TLS_TPOFF32 78 1356 #define R_SPARC_TLS_TPOFF64 79 1357 #define R_SPARC_GOTDATA_HIX22 80 1358 #define R_SPARC_GOTDATA_LOX10 81 1359 #define R_SPARC_GOTDATA_OP_HIX22 82 1360 #define R_SPARC_GOTDATA_OP_LOX10 83 1361 #define R_SPARC_GOTDATA_OP 84 1362 #define R_SPARC_H34 85 1363 #define R_SPARC_SIZE32 86 1364 #define R_SPARC_SIZE64 87 1365 #define R_SPARC_WDISP10 88 1366 #define R_SPARC_JMP_IREL 248 1367 #define R_SPARC_IRELATIVE 249 1368 #define R_SPARC_GNU_VTINHERIT 250 1369 #define R_SPARC_GNU_VTENTRY 251 1370 #define R_SPARC_REV32 252 1045 1371 /* Keep this the last entry. */ 1046 #define R_SPARC_NUM 56 1372 #define R_SPARC_NUM 253 1373 1374 /* For Sparc64, legal values for d_tag of Elf64_Dyn. */ 1375 1376 #define DT_SPARC_REGISTER 0x70000001 1377 #define DT_SPARC_NUM 2 1378 1379 /* MIPS R3000 specific definitions. */ 1380 1381 /* Legal values for e_flags field of Elf32_Ehdr. */ 1382 1383 #define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ 1384 #define EF_MIPS_PIC 2 /* Contains PIC code */ 1385 #define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ 1386 #define EF_MIPS_XGOT 8 1387 #define EF_MIPS_64BIT_WHIRL 16 1388 #define EF_MIPS_ABI2 32 1389 #define EF_MIPS_ABI_ON32 64 1390 #define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ 1391 1392 /* Legal values for MIPS architecture level. */ 1393 1394 #define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ 1395 #define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ 1396 #define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ 1397 #define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ 1398 #define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ 1399 #define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ 1400 #define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ 1401 1402 /* The following are non-official names and should not be used. */ 1403 1404 #define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ 1405 #define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ 1406 #define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ 1407 #define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ 1408 #define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ 1409 #define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ 1410 #define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ 1411 1412 /* Special section indices. */ 1413 1414 #define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ 1415 #define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ 1416 #define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ 1417 #define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ 1418 #define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ 1419 1420 /* Legal values for sh_type field of Elf32_Shdr. */ 1421 1422 #define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ 1423 #define SHT_MIPS_MSYM 0x70000001 1424 #define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ 1425 #define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ 1426 #define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ 1427 #define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/ 1428 #define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ 1429 #define SHT_MIPS_PACKAGE 0x70000007 1430 #define SHT_MIPS_PACKSYM 0x70000008 1431 #define SHT_MIPS_RELD 0x70000009 1432 #define SHT_MIPS_IFACE 0x7000000b 1433 #define SHT_MIPS_CONTENT 0x7000000c 1434 #define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ 1435 #define SHT_MIPS_SHDR 0x70000010 1436 #define SHT_MIPS_FDESC 0x70000011 1437 #define SHT_MIPS_EXTSYM 0x70000012 1438 #define SHT_MIPS_DENSE 0x70000013 1439 #define SHT_MIPS_PDESC 0x70000014 1440 #define SHT_MIPS_LOCSYM 0x70000015 1441 #define SHT_MIPS_AUXSYM 0x70000016 1442 #define SHT_MIPS_OPTSYM 0x70000017 1443 #define SHT_MIPS_LOCSTR 0x70000018 1444 #define SHT_MIPS_LINE 0x70000019 1445 #define SHT_MIPS_RFDESC 0x7000001a 1446 #define SHT_MIPS_DELTASYM 0x7000001b 1447 #define SHT_MIPS_DELTAINST 0x7000001c 1448 #define SHT_MIPS_DELTACLASS 0x7000001d 1449 #define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ 1450 #define SHT_MIPS_DELTADECL 0x7000001f 1451 #define SHT_MIPS_SYMBOL_LIB 0x70000020 1452 #define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ 1453 #define SHT_MIPS_TRANSLATE 0x70000022 1454 #define SHT_MIPS_PIXIE 0x70000023 1455 #define SHT_MIPS_XLATE 0x70000024 1456 #define SHT_MIPS_XLATE_DEBUG 0x70000025 1457 #define SHT_MIPS_WHIRL 0x70000026 1458 #define SHT_MIPS_EH_REGION 0x70000027 1459 #define SHT_MIPS_XLATE_OLD 0x70000028 1460 #define SHT_MIPS_PDR_EXCEPTION 0x70000029 1461 1462 /* Legal values for sh_flags field of Elf32_Shdr. */ 1463 1464 #define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ 1465 #define SHF_MIPS_MERGE 0x20000000 1466 #define SHF_MIPS_ADDR 0x40000000 1467 #define SHF_MIPS_STRINGS 0x80000000 1468 #define SHF_MIPS_NOSTRIP 0x08000000 1469 #define SHF_MIPS_LOCAL 0x04000000 1470 #define SHF_MIPS_NAMES 0x02000000 1471 #define SHF_MIPS_NODUPE 0x01000000 1472 1473 1474 /* Symbol tables. */ 1475 1476 /* MIPS specific values for `st_other'. */ 1477 #define STO_MIPS_DEFAULT 0x0 1478 #define STO_MIPS_INTERNAL 0x1 1479 #define STO_MIPS_HIDDEN 0x2 1480 #define STO_MIPS_PROTECTED 0x3 1481 #define STO_MIPS_PLT 0x8 1482 #define STO_MIPS_SC_ALIGN_UNUSED 0xff 1483 1484 /* MIPS specific values for `st_info'. */ 1485 #define STB_MIPS_SPLIT_COMMON 13 1486 1487 /* Entries found in sections of type SHT_MIPS_GPTAB. */ 1488 1489 typedef union 1490 { 1491 struct 1492 { 1493 Elf32_Word gt_current_g_value; /* -G value used for compilation */ 1494 Elf32_Word gt_unused; /* Not used */ 1495 } gt_header; /* First entry in section */ 1496 struct 1497 { 1498 Elf32_Word gt_g_value; /* If this value were used for -G */ 1499 Elf32_Word gt_bytes; /* This many bytes would be used */ 1500 } gt_entry; /* Subsequent entries in section */ 1501 } __attribute__((packed)) Elf32_gptab; 1502 1503 /* Entry found in sections of type SHT_MIPS_REGINFO. */ 1504 1505 typedef struct 1506 { 1507 Elf32_Word ri_gprmask; /* General registers used */ 1508 Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ 1509 Elf32_Sword ri_gp_value; /* $gp register value */ 1510 } __attribute__((packed)) Elf32_RegInfo; 1511 1512 /* Entries found in sections of type SHT_MIPS_OPTIONS. */ 1513 1514 typedef struct 1515 { 1516 unsigned char kind; /* Determines interpretation of the 1517 variable part of descriptor. */ 1518 unsigned char size; /* Size of descriptor, including header. */ 1519 Elf32_Section section; /* Section header index of section affected, 1520 0 for global options. */ 1521 Elf32_Word info; /* Kind-specific information. */ 1522 } __attribute__((packed)) Elf_Options; 1523 1524 /* Values for `kind' field in Elf_Options. */ 1525 1526 #define ODK_NULL 0 /* Undefined. */ 1527 #define ODK_REGINFO 1 /* Register usage information. */ 1528 #define ODK_EXCEPTIONS 2 /* Exception processing options. */ 1529 #define ODK_PAD 3 /* Section padding options. */ 1530 #define ODK_HWPATCH 4 /* Hardware workarounds performed */ 1531 #define ODK_FILL 5 /* record the fill value used by the linker. */ 1532 #define ODK_TAGS 6 /* reserve space for desktop tools to write. */ 1533 #define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ 1534 #define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ 1535 1536 /* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ 1537 1538 #define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ 1539 #define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ 1540 #define OEX_PAGE0 0x10000 /* page zero must be mapped. */ 1541 #define OEX_SMM 0x20000 /* Force sequential memory mode? */ 1542 #define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ 1543 #define OEX_PRECISEFP OEX_FPDBUG 1544 #define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ 1545 1546 #define OEX_FPU_INVAL 0x10 1547 #define OEX_FPU_DIV0 0x08 1548 #define OEX_FPU_OFLO 0x04 1549 #define OEX_FPU_UFLO 0x02 1550 #define OEX_FPU_INEX 0x01 1551 1552 /* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ 1553 1554 #define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ 1555 #define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ 1556 #define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ 1557 #define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ 1558 1559 #define OPAD_PREFIX 0x1 1560 #define OPAD_POSTFIX 0x2 1561 #define OPAD_SYMBOL 0x4 1562 1563 /* Entry found in `.options' section. */ 1564 1565 typedef struct 1566 { 1567 Elf32_Word hwp_flags1; /* Extra flags. */ 1568 Elf32_Word hwp_flags2; /* Extra flags. */ 1569 } __attribute__((packed)) Elf_Options_Hw; 1570 1571 /* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ 1572 1573 #define OHWA0_R4KEOP_CHECKED 0x00000001 1574 #define OHWA1_R4KEOP_CLEAN 0x00000002 1575 1576 /* MIPS relocs. */ 1577 1578 #define R_MIPS_NONE 0 /* No reloc */ 1579 #define R_MIPS_16 1 /* Direct 16 bit */ 1580 #define R_MIPS_32 2 /* Direct 32 bit */ 1581 #define R_MIPS_REL32 3 /* PC relative 32 bit */ 1582 #define R_MIPS_26 4 /* Direct 26 bit shifted */ 1583 #define R_MIPS_HI16 5 /* High 16 bit */ 1584 #define R_MIPS_LO16 6 /* Low 16 bit */ 1585 #define R_MIPS_GPREL16 7 /* GP relative 16 bit */ 1586 #define R_MIPS_LITERAL 8 /* 16 bit literal entry */ 1587 #define R_MIPS_GOT16 9 /* 16 bit GOT entry */ 1588 #define R_MIPS_PC16 10 /* PC relative 16 bit */ 1589 #define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ 1590 #define R_MIPS_GPREL32 12 /* GP relative 32 bit */ 1591 1592 #define R_MIPS_SHIFT5 16 1593 #define R_MIPS_SHIFT6 17 1594 #define R_MIPS_64 18 1595 #define R_MIPS_GOT_DISP 19 1596 #define R_MIPS_GOT_PAGE 20 1597 #define R_MIPS_GOT_OFST 21 1598 #define R_MIPS_GOT_HI16 22 1599 #define R_MIPS_GOT_LO16 23 1600 #define R_MIPS_SUB 24 1601 #define R_MIPS_INSERT_A 25 1602 #define R_MIPS_INSERT_B 26 1603 #define R_MIPS_DELETE 27 1604 #define R_MIPS_HIGHER 28 1605 #define R_MIPS_HIGHEST 29 1606 #define R_MIPS_CALL_HI16 30 1607 #define R_MIPS_CALL_LO16 31 1608 #define R_MIPS_SCN_DISP 32 1609 #define R_MIPS_REL16 33 1610 #define R_MIPS_ADD_IMMEDIATE 34 1611 #define R_MIPS_PJUMP 35 1612 #define R_MIPS_RELGOT 36 1613 #define R_MIPS_JALR 37 1614 #define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */ 1615 #define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */ 1616 #define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */ 1617 #define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */ 1618 #define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */ 1619 #define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */ 1620 #define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */ 1621 #define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */ 1622 #define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */ 1623 #define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */ 1624 #define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */ 1625 #define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */ 1626 #define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */ 1627 #define R_MIPS_GLOB_DAT 51 1628 #define R_MIPS_COPY 126 1629 #define R_MIPS_JUMP_SLOT 127 1630 /* Keep this the last entry. */ 1631 #define R_MIPS_NUM 128 1632 1633 /* Legal values for p_type field of Elf32_Phdr. */ 1634 1635 #define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ 1636 #define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ 1637 #define PT_MIPS_OPTIONS 0x70000002 1638 1639 /* Special program header types. */ 1640 1641 #define PF_MIPS_LOCAL 0x10000000 1642 1643 /* Legal values for d_tag field of Elf32_Dyn. */ 1644 1645 #define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ 1646 #define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ 1647 #define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ 1648 #define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ 1649 #define DT_MIPS_FLAGS 0x70000005 /* Flags */ 1650 #define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ 1651 #define DT_MIPS_MSYM 0x70000007 1652 #define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ 1653 #define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ 1654 #define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ 1655 #define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ 1656 #define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ 1657 #define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ 1658 #define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ 1659 #define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ 1660 #define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ 1661 #define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ 1662 #define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ 1663 #define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in 1664 DT_MIPS_DELTA_CLASS. */ 1665 #define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ 1666 #define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in 1667 DT_MIPS_DELTA_INSTANCE. */ 1668 #define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ 1669 #define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in 1670 DT_MIPS_DELTA_RELOC. */ 1671 #define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta 1672 relocations refer to. */ 1673 #define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in 1674 DT_MIPS_DELTA_SYM. */ 1675 #define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the 1676 class declaration. */ 1677 #define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in 1678 DT_MIPS_DELTA_CLASSSYM. */ 1679 #define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ 1680 #define DT_MIPS_PIXIE_INIT 0x70000023 1681 #define DT_MIPS_SYMBOL_LIB 0x70000024 1682 #define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 1683 #define DT_MIPS_LOCAL_GOTIDX 0x70000026 1684 #define DT_MIPS_HIDDEN_GOTIDX 0x70000027 1685 #define DT_MIPS_PROTECTED_GOTIDX 0x70000028 1686 #define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ 1687 #define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ 1688 #define DT_MIPS_DYNSTR_ALIGN 0x7000002b 1689 #define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ 1690 #define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve 1691 function stored in GOT. */ 1692 #define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added 1693 by rld on dlopen() calls. */ 1694 #define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ 1695 #define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ 1696 #define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ 1697 /* The address of .got.plt in an executable using the new non-PIC ABI. */ 1698 #define DT_MIPS_PLTGOT 0x70000032 1699 /* The base of the PLT in an executable using the new non-PIC ABI if that 1700 PLT is writable. For a non-writable PLT, this is omitted or has a zero 1701 value. */ 1702 #define DT_MIPS_RWPLT 0x70000034 1703 #define DT_MIPS_NUM 0x35 1704 1705 /* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ 1706 1707 #define RHF_NONE 0 /* No flags */ 1708 #define RHF_QUICKSTART (1 << 0) /* Use quickstart */ 1709 #define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ 1710 #define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ 1711 #define RHF_NO_MOVE (1 << 3) 1712 #define RHF_SGI_ONLY (1 << 4) 1713 #define RHF_GUARANTEE_INIT (1 << 5) 1714 #define RHF_DELTA_C_PLUS_PLUS (1 << 6) 1715 #define RHF_GUARANTEE_START_INIT (1 << 7) 1716 #define RHF_PIXIE (1 << 8) 1717 #define RHF_DEFAULT_DELAY_LOAD (1 << 9) 1718 #define RHF_REQUICKSTART (1 << 10) 1719 #define RHF_REQUICKSTARTED (1 << 11) 1720 #define RHF_CORD (1 << 12) 1721 #define RHF_NO_UNRES_UNDEF (1 << 13) 1722 #define RHF_RLD_ORDER_SAFE (1 << 14) 1723 1724 /* Entries found in sections of type SHT_MIPS_LIBLIST. */ 1725 1726 typedef struct 1727 { 1728 Elf32_Word l_name; /* Name (string table index) */ 1729 Elf32_Word l_time_stamp; /* Timestamp */ 1730 Elf32_Word l_checksum; /* Checksum */ 1731 Elf32_Word l_version; /* Interface version */ 1732 Elf32_Word l_flags; /* Flags */ 1733 } __attribute__((packed)) Elf32_Lib; 1734 1735 typedef struct 1736 { 1737 Elf64_Word l_name; /* Name (string table index) */ 1738 Elf64_Word l_time_stamp; /* Timestamp */ 1739 Elf64_Word l_checksum; /* Checksum */ 1740 Elf64_Word l_version; /* Interface version */ 1741 Elf64_Word l_flags; /* Flags */ 1742 } __attribute__((packed)) Elf64_Lib; 1743 1744 1745 /* Legal values for l_flags. */ 1746 1747 #define LL_NONE 0 1748 #define LL_EXACT_MATCH (1 << 0) /* Require exact match */ 1749 #define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ 1750 #define LL_REQUIRE_MINOR (1 << 2) 1751 #define LL_EXPORTS (1 << 3) 1752 #define LL_DELAY_LOAD (1 << 4) 1753 #define LL_DELTA (1 << 5) 1754 1755 /* Entries found in sections of type SHT_MIPS_CONFLICT. */ 1756 1757 typedef Elf32_Addr Elf32_Conflict; 1758 1759 1760 /* HPPA specific definitions. */ 1761 1762 /* Legal values for e_flags field of Elf32_Ehdr. */ 1763 1764 #define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ 1765 #define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ 1766 #define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ 1767 #define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ 1768 #define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch 1769 prediction. */ 1770 #define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ 1771 #define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ 1772 1773 /* Defined values for `e_flags & EF_PARISC_ARCH' are: */ 1774 1775 #define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ 1776 #define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ 1777 #define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ 1778 1779 /* Additional section indices. */ 1780 1781 #define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tentatively declared 1782 symbols in ANSI C. */ 1783 #define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ 1784 1785 /* Legal values for sh_type field of Elf32_Shdr. */ 1786 1787 #define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ 1788 #define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ 1789 #define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ 1790 1791 /* Legal values for sh_flags field of Elf32_Shdr. */ 1792 1793 #define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ 1794 #define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ 1795 #define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ 1796 1797 /* Legal values for ST_TYPE subfield of st_info (symbol type). */ 1798 1799 #define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ 1800 1801 #define STT_HP_OPAQUE (STT_LOOS + 0x1) 1802 #define STT_HP_STUB (STT_LOOS + 0x2) 1803 1804 /* HPPA relocs. */ 1805 1806 #define R_PARISC_NONE 0 /* No reloc. */ 1807 #define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ 1808 #define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ 1809 #define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ 1810 #define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ 1811 #define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ 1812 #define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ 1813 #define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ 1814 #define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ 1815 #define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ 1816 #define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ 1817 #define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ 1818 #define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ 1819 #define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ 1820 #define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ 1821 #define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ 1822 #define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ 1823 #define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ 1824 #define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ 1825 #define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ 1826 #define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ 1827 #define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ 1828 #define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ 1829 #define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ 1830 #define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ 1831 #define R_PARISC_FPTR64 64 /* 64 bits function address. */ 1832 #define R_PARISC_PLABEL32 65 /* 32 bits function address. */ 1833 #define R_PARISC_PLABEL21L 66 /* Left 21 bits of fdesc address. */ 1834 #define R_PARISC_PLABEL14R 70 /* Right 14 bits of fdesc address. */ 1835 #define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ 1836 #define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ 1837 #define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ 1838 #define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ 1839 #define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ 1840 #define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ 1841 #define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ 1842 #define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ 1843 #define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ 1844 #define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ 1845 #define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ 1846 #define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ 1847 #define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ 1848 #define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ 1849 #define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ 1850 #define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ 1851 #define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ 1852 #define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ 1853 #define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ 1854 #define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ 1855 #define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ 1856 #define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ 1857 #define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ 1858 #define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ 1859 #define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ 1860 #define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ 1861 #define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ 1862 #define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ 1863 #define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ 1864 #define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ 1865 #define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ 1866 #define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ 1867 #define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ 1868 #define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ 1869 #define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ 1870 #define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ 1871 #define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ 1872 #define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ 1873 #define R_PARISC_LORESERVE 128 1874 #define R_PARISC_COPY 128 /* Copy relocation. */ 1875 #define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ 1876 #define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ 1877 #define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ 1878 #define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ 1879 #define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ 1880 #define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ 1881 #define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ 1882 #define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ 1883 #define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ 1884 #define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ 1885 #define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ 1886 #define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ 1887 #define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ 1888 #define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ 1889 #define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ 1890 #define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ 1891 #define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ 1892 #define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ 1893 #define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ 1894 #define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ 1895 #define R_PARISC_GNU_VTENTRY 232 1896 #define R_PARISC_GNU_VTINHERIT 233 1897 #define R_PARISC_TLS_GD21L 234 /* GD 21-bit left. */ 1898 #define R_PARISC_TLS_GD14R 235 /* GD 14-bit right. */ 1899 #define R_PARISC_TLS_GDCALL 236 /* GD call to __t_g_a. */ 1900 #define R_PARISC_TLS_LDM21L 237 /* LD module 21-bit left. */ 1901 #define R_PARISC_TLS_LDM14R 238 /* LD module 14-bit right. */ 1902 #define R_PARISC_TLS_LDMCALL 239 /* LD module call to __t_g_a. */ 1903 #define R_PARISC_TLS_LDO21L 240 /* LD offset 21-bit left. */ 1904 #define R_PARISC_TLS_LDO14R 241 /* LD offset 14-bit right. */ 1905 #define R_PARISC_TLS_DTPMOD32 242 /* DTP module 32-bit. */ 1906 #define R_PARISC_TLS_DTPMOD64 243 /* DTP module 64-bit. */ 1907 #define R_PARISC_TLS_DTPOFF32 244 /* DTP offset 32-bit. */ 1908 #define R_PARISC_TLS_DTPOFF64 245 /* DTP offset 32-bit. */ 1909 #define R_PARISC_TLS_LE21L R_PARISC_TPREL21L 1910 #define R_PARISC_TLS_LE14R R_PARISC_TPREL14R 1911 #define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L 1912 #define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R 1913 #define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32 1914 #define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64 1915 #define R_PARISC_HIRESERVE 255 1916 1917 /* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ 1918 1919 #define PT_HP_TLS (PT_LOOS + 0x0) 1920 #define PT_HP_CORE_NONE (PT_LOOS + 0x1) 1921 #define PT_HP_CORE_VERSION (PT_LOOS + 0x2) 1922 #define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) 1923 #define PT_HP_CORE_COMM (PT_LOOS + 0x4) 1924 #define PT_HP_CORE_PROC (PT_LOOS + 0x5) 1925 #define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) 1926 #define PT_HP_CORE_STACK (PT_LOOS + 0x7) 1927 #define PT_HP_CORE_SHM (PT_LOOS + 0x8) 1928 #define PT_HP_CORE_MMF (PT_LOOS + 0x9) 1929 #define PT_HP_PARALLEL (PT_LOOS + 0x10) 1930 #define PT_HP_FASTBIND (PT_LOOS + 0x11) 1931 #define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) 1932 #define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) 1933 #define PT_HP_STACK (PT_LOOS + 0x14) 1934 1935 #define PT_PARISC_ARCHEXT 0x70000000 1936 #define PT_PARISC_UNWIND 0x70000001 1937 1938 /* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ 1939 1940 #define PF_PARISC_SBP 0x08000000 1941 1942 #define PF_HP_PAGE_SIZE 0x00100000 1943 #define PF_HP_FAR_SHARED 0x00200000 1944 #define PF_HP_NEAR_SHARED 0x00400000 1945 #define PF_HP_CODE 0x01000000 1946 #define PF_HP_MODIFY 0x02000000 1947 #define PF_HP_LAZYSWAP 0x04000000 1948 #define PF_HP_SBP 0x08000000 1949 1950 1951 /* Alpha specific definitions. */ 1952 1953 /* Legal values for e_flags field of Elf64_Ehdr. */ 1954 1955 #define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ 1956 #define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ 1957 1958 /* Legal values for sh_type field of Elf64_Shdr. */ 1959 1960 /* These two are primarily concerned with ECOFF debugging info. */ 1961 #define SHT_ALPHA_DEBUG 0x70000001 1962 #define SHT_ALPHA_REGINFO 0x70000002 1963 1964 /* Legal values for sh_flags field of Elf64_Shdr. */ 1965 1966 #define SHF_ALPHA_GPREL 0x10000000 1967 1968 /* Legal values for st_other field of Elf64_Sym. */ 1969 #define STO_ALPHA_NOPV 0x80 /* No PV required. */ 1970 #define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ 1971 1972 /* Alpha relocs. */ 1973 1974 #define R_ALPHA_NONE 0 /* No reloc */ 1975 #define R_ALPHA_REFLONG 1 /* Direct 32 bit */ 1976 #define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ 1977 #define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ 1978 #define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ 1979 #define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ 1980 #define R_ALPHA_GPDISP 6 /* Add displacement to GP */ 1981 #define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ 1982 #define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ 1983 #define R_ALPHA_SREL16 9 /* PC relative 16 bit */ 1984 #define R_ALPHA_SREL32 10 /* PC relative 32 bit */ 1985 #define R_ALPHA_SREL64 11 /* PC relative 64 bit */ 1986 #define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ 1987 #define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ 1988 #define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ 1989 #define R_ALPHA_COPY 24 /* Copy symbol at runtime */ 1990 #define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ 1991 #define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ 1992 #define R_ALPHA_RELATIVE 27 /* Adjust by program base */ 1993 #define R_ALPHA_TLS_GD_HI 28 1994 #define R_ALPHA_TLSGD 29 1995 #define R_ALPHA_TLS_LDM 30 1996 #define R_ALPHA_DTPMOD64 31 1997 #define R_ALPHA_GOTDTPREL 32 1998 #define R_ALPHA_DTPREL64 33 1999 #define R_ALPHA_DTPRELHI 34 2000 #define R_ALPHA_DTPRELLO 35 2001 #define R_ALPHA_DTPREL16 36 2002 #define R_ALPHA_GOTTPREL 37 2003 #define R_ALPHA_TPREL64 38 2004 #define R_ALPHA_TPRELHI 39 2005 #define R_ALPHA_TPRELLO 40 2006 #define R_ALPHA_TPREL16 41 2007 /* Keep this the last entry. */ 2008 #define R_ALPHA_NUM 46 2009 2010 /* Magic values of the LITUSE relocation addend. */ 2011 #define LITUSE_ALPHA_ADDR 0 2012 #define LITUSE_ALPHA_BASE 1 2013 #define LITUSE_ALPHA_BYTOFF 2 2014 #define LITUSE_ALPHA_JSR 3 2015 #define LITUSE_ALPHA_TLS_GD 4 2016 #define LITUSE_ALPHA_TLS_LDM 5 2017 2018 /* Legal values for d_tag of Elf64_Dyn. */ 2019 #define DT_ALPHA_PLTRO (DT_LOPROC + 0) 2020 #define DT_ALPHA_NUM 1 2021 2022 /* PowerPC specific declarations */ 2023 2024 /* Values for Elf32/64_Ehdr.e_flags. */ 2025 #define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ 2026 2027 /* Cygnus local bits below */ 2028 #define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ 2029 #define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib 2030 flag */ 2031 2032 /* PowerPC relocations defined by the ABIs */ 2033 #define R_PPC_NONE 0 2034 #define R_PPC_ADDR32 1 /* 32bit absolute address */ 2035 #define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ 2036 #define R_PPC_ADDR16 3 /* 16bit absolute address */ 2037 #define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ 2038 #define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ 2039 #define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ 2040 #define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ 2041 #define R_PPC_ADDR14_BRTAKEN 8 2042 #define R_PPC_ADDR14_BRNTAKEN 9 2043 #define R_PPC_REL24 10 /* PC relative 26 bit */ 2044 #define R_PPC_REL14 11 /* PC relative 16 bit */ 2045 #define R_PPC_REL14_BRTAKEN 12 2046 #define R_PPC_REL14_BRNTAKEN 13 2047 #define R_PPC_GOT16 14 2048 #define R_PPC_GOT16_LO 15 2049 #define R_PPC_GOT16_HI 16 2050 #define R_PPC_GOT16_HA 17 2051 #define R_PPC_PLTREL24 18 2052 #define R_PPC_COPY 19 2053 #define R_PPC_GLOB_DAT 20 2054 #define R_PPC_JMP_SLOT 21 2055 #define R_PPC_RELATIVE 22 2056 #define R_PPC_LOCAL24PC 23 2057 #define R_PPC_UADDR32 24 2058 #define R_PPC_UADDR16 25 2059 #define R_PPC_REL32 26 2060 #define R_PPC_PLT32 27 2061 #define R_PPC_PLTREL32 28 2062 #define R_PPC_PLT16_LO 29 2063 #define R_PPC_PLT16_HI 30 2064 #define R_PPC_PLT16_HA 31 2065 #define R_PPC_SDAREL16 32 2066 #define R_PPC_SECTOFF 33 2067 #define R_PPC_SECTOFF_LO 34 2068 #define R_PPC_SECTOFF_HI 35 2069 #define R_PPC_SECTOFF_HA 36 2070 2071 /* PowerPC relocations defined for the TLS access ABI. */ 2072 #define R_PPC_TLS 67 /* none (sym+add)@tls */ 2073 #define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ 2074 #define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ 2075 #define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ 2076 #define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ 2077 #define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ 2078 #define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ 2079 #define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ 2080 #define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ 2081 #define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ 2082 #define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ 2083 #define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ 2084 #define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ 2085 #define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ 2086 #define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ 2087 #define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ 2088 #define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ 2089 #define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ 2090 #define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ 2091 #define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ 2092 #define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ 2093 #define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ 2094 #define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ 2095 #define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ 2096 #define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ 2097 #define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */ 2098 #define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */ 2099 #define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */ 2100 2101 /* The remaining relocs are from the Embedded ELF ABI, and are not 2102 in the SVR4 ELF ABI. */ 2103 #define R_PPC_EMB_NADDR32 101 2104 #define R_PPC_EMB_NADDR16 102 2105 #define R_PPC_EMB_NADDR16_LO 103 2106 #define R_PPC_EMB_NADDR16_HI 104 2107 #define R_PPC_EMB_NADDR16_HA 105 2108 #define R_PPC_EMB_SDAI16 106 2109 #define R_PPC_EMB_SDA2I16 107 2110 #define R_PPC_EMB_SDA2REL 108 2111 #define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ 2112 #define R_PPC_EMB_MRKREF 110 2113 #define R_PPC_EMB_RELSEC16 111 2114 #define R_PPC_EMB_RELST_LO 112 2115 #define R_PPC_EMB_RELST_HI 113 2116 #define R_PPC_EMB_RELST_HA 114 2117 #define R_PPC_EMB_BIT_FLD 115 2118 #define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ 2119 2120 /* Diab tool relocations. */ 2121 #define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ 2122 #define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ 2123 #define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ 2124 #define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ 2125 #define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ 2126 #define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ 2127 2128 /* GNU extension to support local ifunc. */ 2129 #define R_PPC_IRELATIVE 248 2130 2131 /* GNU relocs used in PIC code sequences. */ 2132 #define R_PPC_REL16 249 /* half16 (sym+add-.) */ 2133 #define R_PPC_REL16_LO 250 /* half16 (sym+add-.)@l */ 2134 #define R_PPC_REL16_HI 251 /* half16 (sym+add-.)@h */ 2135 #define R_PPC_REL16_HA 252 /* half16 (sym+add-.)@ha */ 2136 2137 /* This is a phony reloc to handle any old fashioned TOC16 references 2138 that may still be in object files. */ 2139 #define R_PPC_TOC16 255 2140 2141 /* PowerPC specific values for the Dyn d_tag field. */ 2142 #define DT_PPC_GOT (DT_LOPROC + 0) 2143 #define DT_PPC_NUM 1 2144 2145 /* PowerPC64 relocations defined by the ABIs */ 2146 #define R_PPC64_NONE R_PPC_NONE 2147 #define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */ 2148 #define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */ 2149 #define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */ 2150 #define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */ 2151 #define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */ 2152 #define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ 2153 #define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */ 2154 #define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN 2155 #define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN 2156 #define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */ 2157 #define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */ 2158 #define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN 2159 #define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN 2160 #define R_PPC64_GOT16 R_PPC_GOT16 2161 #define R_PPC64_GOT16_LO R_PPC_GOT16_LO 2162 #define R_PPC64_GOT16_HI R_PPC_GOT16_HI 2163 #define R_PPC64_GOT16_HA R_PPC_GOT16_HA 2164 2165 #define R_PPC64_COPY R_PPC_COPY 2166 #define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT 2167 #define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT 2168 #define R_PPC64_RELATIVE R_PPC_RELATIVE 2169 2170 #define R_PPC64_UADDR32 R_PPC_UADDR32 2171 #define R_PPC64_UADDR16 R_PPC_UADDR16 2172 #define R_PPC64_REL32 R_PPC_REL32 2173 #define R_PPC64_PLT32 R_PPC_PLT32 2174 #define R_PPC64_PLTREL32 R_PPC_PLTREL32 2175 #define R_PPC64_PLT16_LO R_PPC_PLT16_LO 2176 #define R_PPC64_PLT16_HI R_PPC_PLT16_HI 2177 #define R_PPC64_PLT16_HA R_PPC_PLT16_HA 2178 2179 #define R_PPC64_SECTOFF R_PPC_SECTOFF 2180 #define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO 2181 #define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI 2182 #define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA 2183 #define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */ 2184 #define R_PPC64_ADDR64 38 /* doubleword64 S + A */ 2185 #define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */ 2186 #define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */ 2187 #define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */ 2188 #define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */ 2189 #define R_PPC64_UADDR64 43 /* doubleword64 S + A */ 2190 #define R_PPC64_REL64 44 /* doubleword64 S + A - P */ 2191 #define R_PPC64_PLT64 45 /* doubleword64 L + A */ 2192 #define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */ 2193 #define R_PPC64_TOC16 47 /* half16* S + A - .TOC */ 2194 #define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */ 2195 #define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */ 2196 #define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */ 2197 #define R_PPC64_TOC 51 /* doubleword64 .TOC */ 2198 #define R_PPC64_PLTGOT16 52 /* half16* M + A */ 2199 #define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */ 2200 #define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */ 2201 #define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */ 2202 2203 #define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */ 2204 #define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */ 2205 #define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */ 2206 #define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */ 2207 #define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */ 2208 #define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */ 2209 #define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */ 2210 #define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */ 2211 #define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */ 2212 #define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */ 2213 #define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */ 2214 2215 /* PowerPC64 relocations defined for the TLS access ABI. */ 2216 #define R_PPC64_TLS 67 /* none (sym+add)@tls */ 2217 #define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ 2218 #define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ 2219 #define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ 2220 #define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ 2221 #define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ 2222 #define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ 2223 #define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ 2224 #define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ 2225 #define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ 2226 #define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ 2227 #define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ 2228 #define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ 2229 #define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ 2230 #define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ 2231 #define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ 2232 #define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ 2233 #define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ 2234 #define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ 2235 #define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ 2236 #define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ 2237 #define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ 2238 #define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ 2239 #define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ 2240 #define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ 2241 #define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ 2242 #define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ 2243 #define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ 2244 #define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ 2245 #define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ 2246 #define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ 2247 #define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ 2248 #define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ 2249 #define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ 2250 #define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ 2251 #define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ 2252 #define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ 2253 #define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ 2254 #define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ 2255 #define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ 2256 2257 /* GNU extension to support local ifunc. */ 2258 #define R_PPC64_JMP_IREL 247 2259 #define R_PPC64_IRELATIVE 248 2260 #define R_PPC64_REL16 249 /* half16 (sym+add-.) */ 2261 #define R_PPC64_REL16_LO 250 /* half16 (sym+add-.)@l */ 2262 #define R_PPC64_REL16_HI 251 /* half16 (sym+add-.)@h */ 2263 #define R_PPC64_REL16_HA 252 /* half16 (sym+add-.)@ha */ 2264 2265 /* PowerPC64 specific values for the Dyn d_tag field. */ 2266 #define DT_PPC64_GLINK (DT_LOPROC + 0) 2267 #define DT_PPC64_OPD (DT_LOPROC + 1) 2268 #define DT_PPC64_OPDSZ (DT_LOPROC + 2) 2269 #define DT_PPC64_NUM 3 2270 2271 2272 /* ARM specific declarations */ 2273 2274 /* Processor specific flags for the ELF header e_flags field. */ 2275 #define EF_ARM_RELEXEC 0x01 2276 #define EF_ARM_HASENTRY 0x02 2277 #define EF_ARM_INTERWORK 0x04 2278 #define EF_ARM_APCS_26 0x08 2279 #define EF_ARM_APCS_FLOAT 0x10 2280 #define EF_ARM_PIC 0x20 2281 #define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ 2282 #define EF_ARM_NEW_ABI 0x80 2283 #define EF_ARM_OLD_ABI 0x100 2284 #define EF_ARM_SOFT_FLOAT 0x200 2285 #define EF_ARM_VFP_FLOAT 0x400 2286 #define EF_ARM_MAVERICK_FLOAT 0x800 2287 2288 #define EF_ARM_ABI_FLOAT_SOFT 0x200 /* NB conflicts with EF_ARM_SOFT_FLOAT */ 2289 #define EF_ARM_ABI_FLOAT_HARD 0x400 /* NB conflicts with EF_ARM_VFP_FLOAT */ 2290 2291 2292 /* Other constants defined in the ARM ELF spec. version B-01. */ 2293 /* NB. These conflict with values defined above. */ 2294 #define EF_ARM_SYMSARESORTED 0x04 2295 #define EF_ARM_DYNSYMSUSESEGIDX 0x08 2296 #define EF_ARM_MAPSYMSFIRST 0x10 2297 #define EF_ARM_EABIMASK 0XFF000000 2298 2299 /* Constants defined in AAELF. */ 2300 #define EF_ARM_BE8 0x00800000 2301 #define EF_ARM_LE8 0x00400000 2302 2303 #define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) 2304 #define EF_ARM_EABI_UNKNOWN 0x00000000 2305 #define EF_ARM_EABI_VER1 0x01000000 2306 #define EF_ARM_EABI_VER2 0x02000000 2307 #define EF_ARM_EABI_VER3 0x03000000 2308 #define EF_ARM_EABI_VER4 0x04000000 2309 #define EF_ARM_EABI_VER5 0x05000000 2310 2311 /* Additional symbol types for Thumb. */ 2312 #define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ 2313 #define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ 2314 2315 /* ARM-specific values for sh_flags */ 2316 #define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ 2317 #define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined 2318 in the input to a link step. */ 2319 2320 /* ARM-specific program header flags */ 2321 #define PF_ARM_SB 0x10000000 /* Segment contains the location 2322 addressed by the static base. */ 2323 #define PF_ARM_PI 0x20000000 /* Position-independent segment. */ 2324 #define PF_ARM_ABS 0x40000000 /* Absolute segment. */ 2325 2326 /* Processor specific values for the Phdr p_type field. */ 2327 #define PT_ARM_EXIDX (PT_LOPROC + 1) /* ARM unwind segment. */ 2328 2329 /* Processor specific values for the Shdr sh_type field. */ 2330 #define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */ 2331 #define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */ 2332 #define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */ 2333 2334 2335 /* AArch64 relocs. */ 2336 2337 #define R_AARCH64_NONE 0 /* No relocation. */ 2338 #define R_AARCH64_ABS64 257 /* Direct 64 bit. */ 2339 #define R_AARCH64_ABS32 258 /* Direct 32 bit. */ 2340 #define R_AARCH64_ABS16 259 /* Direct 16-bit. */ 2341 #define R_AARCH64_PREL64 260 /* PC-relative 64-bit. */ 2342 #define R_AARCH64_PREL32 261 /* PC-relative 32-bit. */ 2343 #define R_AARCH64_PREL16 262 /* PC-relative 16-bit. */ 2344 #define R_AARCH64_MOVW_UABS_G0 263 /* Dir. MOVZ imm. from bits 15:0. */ 2345 #define R_AARCH64_MOVW_UABS_G0_NC 264 /* Likewise for MOVK; no check. */ 2346 #define R_AARCH64_MOVW_UABS_G1 265 /* Dir. MOVZ imm. from bits 31:16. */ 2347 #define R_AARCH64_MOVW_UABS_G1_NC 266 /* Likewise for MOVK; no check. */ 2348 #define R_AARCH64_MOVW_UABS_G2 267 /* Dir. MOVZ imm. from bits 47:32. */ 2349 #define R_AARCH64_MOVW_UABS_G2_NC 268 /* Likewise for MOVK; no check. */ 2350 #define R_AARCH64_MOVW_UABS_G3 269 /* Dir. MOV{K,Z} imm. from 63:48. */ 2351 #define R_AARCH64_MOVW_SABS_G0 270 /* Dir. MOV{N,Z} imm. from 15:0. */ 2352 #define R_AARCH64_MOVW_SABS_G1 271 /* Dir. MOV{N,Z} imm. from 31:16. */ 2353 #define R_AARCH64_MOVW_SABS_G2 272 /* Dir. MOV{N,Z} imm. from 47:32. */ 2354 #define R_AARCH64_LD_PREL_LO19 273 /* PC-rel. LD imm. from bits 20:2. */ 2355 #define R_AARCH64_ADR_PREL_LO21 274 /* PC-rel. ADR imm. from bits 20:0. */ 2356 #define R_AARCH64_ADR_PREL_PG_HI21 275 /* Page-rel. ADRP imm. from 32:12. */ 2357 #define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Likewise; no overflow check. */ 2358 #define R_AARCH64_ADD_ABS_LO12_NC 277 /* Dir. ADD imm. from bits 11:0. */ 2359 #define R_AARCH64_LDST8_ABS_LO12_NC 278 /* Likewise for LD/ST; no check. */ 2360 #define R_AARCH64_TSTBR14 279 /* PC-rel. TBZ/TBNZ imm. from 15:2. */ 2361 #define R_AARCH64_CONDBR19 280 /* PC-rel. cond. br. imm. from 20:2. */ 2362 #define R_AARCH64_JUMP26 282 /* PC-rel. B imm. from bits 27:2. */ 2363 #define R_AARCH64_CALL26 283 /* Likewise for CALL. */ 2364 #define R_AARCH64_LDST16_ABS_LO12_NC 284 /* Dir. ADD imm. from bits 11:1. */ 2365 #define R_AARCH64_LDST32_ABS_LO12_NC 285 /* Likewise for bits 11:2. */ 2366 #define R_AARCH64_LDST64_ABS_LO12_NC 286 /* Likewise for bits 11:3. */ 2367 #define R_AARCH64_MOVW_PREL_G0 287 /* PC-rel. MOV{N,Z} imm. from 15:0. */ 2368 #define R_AARCH64_MOVW_PREL_G0_NC 288 /* Likewise for MOVK; no check. */ 2369 #define R_AARCH64_MOVW_PREL_G1 289 /* PC-rel. MOV{N,Z} imm. from 31:16. */ 2370 #define R_AARCH64_MOVW_PREL_G1_NC 290 /* Likewise for MOVK; no check. */ 2371 #define R_AARCH64_MOVW_PREL_G2 291 /* PC-rel. MOV{N,Z} imm. from 47:32. */ 2372 #define R_AARCH64_MOVW_PREL_G2_NC 292 /* Likewise for MOVK; no check. */ 2373 #define R_AARCH64_MOVW_PREL_G3 293 /* PC-rel. MOV{N,Z} imm. from 63:48. */ 2374 #define R_AARCH64_LDST128_ABS_LO12_NC 299 /* Dir. ADD imm. from bits 11:4. */ 2375 #define R_AARCH64_MOVW_GOTOFF_G0 300 /* GOT-rel. off. MOV{N,Z} imm. 15:0. */ 2376 #define R_AARCH64_MOVW_GOTOFF_G0_NC 301 /* Likewise for MOVK; no check. */ 2377 #define R_AARCH64_MOVW_GOTOFF_G1 302 /* GOT-rel. o. MOV{N,Z} imm. 31:16. */ 2378 #define R_AARCH64_MOVW_GOTOFF_G1_NC 303 /* Likewise for MOVK; no check. */ 2379 #define R_AARCH64_MOVW_GOTOFF_G2 304 /* GOT-rel. o. MOV{N,Z} imm. 47:32. */ 2380 #define R_AARCH64_MOVW_GOTOFF_G2_NC 305 /* Likewise for MOVK; no check. */ 2381 #define R_AARCH64_MOVW_GOTOFF_G3 306 /* GOT-rel. o. MOV{N,Z} imm. 63:48. */ 2382 #define R_AARCH64_GOTREL64 307 /* GOT-relative 64-bit. */ 2383 #define R_AARCH64_GOTREL32 308 /* GOT-relative 32-bit. */ 2384 #define R_AARCH64_GOT_LD_PREL19 309 /* PC-rel. GOT off. load imm. 20:2. */ 2385 #define R_AARCH64_LD64_GOTOFF_LO15 310 /* GOT-rel. off. LD/ST imm. 14:3. */ 2386 #define R_AARCH64_ADR_GOT_PAGE 311 /* P-page-rel. GOT off. ADRP 32:12. */ 2387 #define R_AARCH64_LD64_GOT_LO12_NC 312 /* Dir. GOT off. LD/ST imm. 11:3. */ 2388 #define R_AARCH64_LD64_GOTPAGE_LO15 313 /* GOT-page-rel. GOT off. LD/ST 14:3 */ 2389 #define R_AARCH64_TLSGD_ADR_PREL21 512 /* PC-relative ADR imm. 20:0. */ 2390 #define R_AARCH64_TLSGD_ADR_PAGE21 513 /* page-rel. ADRP imm. 32:12. */ 2391 #define R_AARCH64_TLSGD_ADD_LO12_NC 514 /* direct ADD imm. from 11:0. */ 2392 #define R_AARCH64_TLSGD_MOVW_G1 515 /* GOT-rel. MOV{N,Z} 31:16. */ 2393 #define R_AARCH64_TLSGD_MOVW_G0_NC 516 /* GOT-rel. MOVK imm. 15:0. */ 2394 #define R_AARCH64_TLSLD_ADR_PREL21 517 /* Like 512; local dynamic model. */ 2395 #define R_AARCH64_TLSLD_ADR_PAGE21 518 /* Like 513; local dynamic model. */ 2396 #define R_AARCH64_TLSLD_ADD_LO12_NC 519 /* Like 514; local dynamic model. */ 2397 #define R_AARCH64_TLSLD_MOVW_G1 520 /* Like 515; local dynamic model. */ 2398 #define R_AARCH64_TLSLD_MOVW_G0_NC 521 /* Like 516; local dynamic model. */ 2399 #define R_AARCH64_TLSLD_LD_PREL19 522 /* TLS PC-rel. load imm. 20:2. */ 2400 #define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* TLS DTP-rel. MOV{N,Z} 47:32. */ 2401 #define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* TLS DTP-rel. MOV{N,Z} 31:16. */ 2402 #define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* Likewise; MOVK; no check. */ 2403 #define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* TLS DTP-rel. MOV{N,Z} 15:0. */ 2404 #define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* Likewise; MOVK; no check. */ 2405 #define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTP-rel. ADD imm. from 23:12. */ 2406 #define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTP-rel. ADD imm. from 11:0. */ 2407 #define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* Likewise; no ovfl. check. */ 2408 #define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTP-rel. LD/ST imm. 11:0. */ 2409 #define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* Likewise; no check. */ 2410 #define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTP-rel. LD/ST imm. 11:1. */ 2411 #define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* Likewise; no check. */ 2412 #define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTP-rel. LD/ST imm. 11:2. */ 2413 #define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* Likewise; no check. */ 2414 #define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTP-rel. LD/ST imm. 11:3. */ 2415 #define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* Likewise; no check. */ 2416 #define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* GOT-rel. MOV{N,Z} 31:16. */ 2417 #define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* GOT-rel. MOVK 15:0. */ 2418 #define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page-rel. ADRP 32:12. */ 2419 #define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* Direct LD off. 11:3. */ 2420 #define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* PC-rel. load imm. 20:2. */ 2421 #define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TLS TP-rel. MOV{N,Z} 47:32. */ 2422 #define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TLS TP-rel. MOV{N,Z} 31:16. */ 2423 #define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* Likewise; MOVK; no check. */ 2424 #define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TLS TP-rel. MOV{N,Z} 15:0. */ 2425 #define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* Likewise; MOVK; no check. */ 2426 #define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TP-rel. ADD imm. 23:12. */ 2427 #define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TP-rel. ADD imm. 11:0. */ 2428 #define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* Likewise; no ovfl. check. */ 2429 #define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TP-rel. LD/ST off. 11:0. */ 2430 #define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* Likewise; no ovfl. check. */ 2431 #define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TP-rel. LD/ST off. 11:1. */ 2432 #define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* Likewise; no check. */ 2433 #define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TP-rel. LD/ST off. 11:2. */ 2434 #define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* Likewise; no check. */ 2435 #define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TP-rel. LD/ST off. 11:3. */ 2436 #define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* Likewise; no check. */ 2437 #define R_AARCH64_TLSDESC_LD_PREL19 560 /* PC-rel. load immediate 20:2. */ 2438 #define R_AARCH64_TLSDESC_ADR_PREL21 561 /* PC-rel. ADR immediate 20:0. */ 2439 #define R_AARCH64_TLSDESC_ADR_PAGE21 562 /* Page-rel. ADRP imm. 32:12. */ 2440 #define R_AARCH64_TLSDESC_LD64_LO12 563 /* Direct LD off. from 11:3. */ 2441 #define R_AARCH64_TLSDESC_ADD_LO12 564 /* Direct ADD imm. from 11:0. */ 2442 #define R_AARCH64_TLSDESC_OFF_G1 565 /* GOT-rel. MOV{N,Z} imm. 31:16. */ 2443 #define R_AARCH64_TLSDESC_OFF_G0_NC 566 /* GOT-rel. MOVK imm. 15:0; no ck. */ 2444 #define R_AARCH64_TLSDESC_LDR 567 /* Relax LDR. */ 2445 #define R_AARCH64_TLSDESC_ADD 568 /* Relax ADD. */ 2446 #define R_AARCH64_TLSDESC_CALL 569 /* Relax BLR. */ 2447 #define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 /* TP-rel. LD/ST off. 11:4. */ 2448 #define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 /* Likewise; no check. */ 2449 #define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 /* DTP-rel. LD/ST imm. 11:4. */ 2450 #define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573 /* Likewise; no check. */ 2451 #define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */ 2452 #define R_AARCH64_GLOB_DAT 1025 /* Create GOT entry. */ 2453 #define R_AARCH64_JUMP_SLOT 1026 /* Create PLT entry. */ 2454 #define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */ 2455 #define R_AARCH64_TLS_DTPMOD64 1028 /* Module number, 64 bit. */ 2456 #define R_AARCH64_TLS_DTPREL64 1029 /* Module-relative offset, 64 bit. */ 2457 #define R_AARCH64_TLS_TPREL64 1030 /* TP-relative offset, 64 bit. */ 2458 #define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */ 2459 #define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */ 2460 /* Keep this the last entry. */ 2461 #define R_AARCH64_NUM 1033 2462 2463 /* ARM relocs. */ 2464 2465 #define R_ARM_NONE 0 /* No reloc */ 2466 #define R_ARM_PC24 1 /* PC relative 26 bit branch */ 2467 #define R_ARM_ABS32 2 /* Direct 32 bit */ 2468 #define R_ARM_REL32 3 /* PC relative 32 bit */ 2469 #define R_ARM_PC13 4 2470 #define R_ARM_ABS16 5 /* Direct 16 bit */ 2471 #define R_ARM_ABS12 6 /* Direct 12 bit */ 2472 #define R_ARM_THM_ABS5 7 2473 #define R_ARM_ABS8 8 /* Direct 8 bit */ 2474 #define R_ARM_SBREL32 9 2475 #define R_ARM_THM_PC22 10 2476 #define R_ARM_THM_PC8 11 2477 #define R_ARM_AMP_VCALL9 12 2478 #define R_ARM_SWI24 13 /* Obsolete static relocation. */ 2479 #define R_ARM_TLS_DESC 13 /* Dynamic relocation. */ 2480 #define R_ARM_THM_SWI8 14 2481 #define R_ARM_XPC25 15 2482 #define R_ARM_THM_XPC22 16 2483 #define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ 2484 #define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ 2485 #define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ 2486 #define R_ARM_COPY 20 /* Copy symbol at runtime */ 2487 #define R_ARM_GLOB_DAT 21 /* Create GOT entry */ 2488 #define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ 2489 #define R_ARM_RELATIVE 23 /* Adjust by program base */ 2490 #define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ 2491 #define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ 2492 #define R_ARM_GOT32 26 /* 32 bit GOT entry */ 2493 #define R_ARM_PLT32 27 /* 32 bit PLT address */ 2494 #define R_ARM_CALL 28 2495 #define R_ARM_JUMP24 29 2496 #define R_ARM_THM_JUMP24 30 2497 #define R_ARM_ALU_PCREL_7_0 32 2498 #define R_ARM_ALU_PCREL_15_8 33 2499 #define R_ARM_ALU_PCREL_23_15 34 2500 #define R_ARM_LDR_SBREL_11_0 35 2501 #define R_ARM_ALU_SBREL_19_12 36 2502 #define R_ARM_ALU_SBREL_27_20 37 2503 #define R_ARM_V4BX 40 2504 #define R_ARM_PREL31 42 2505 #define R_ARM_MOVW_ABS_NC 43 2506 #define R_ARM_MOVT_ABS 44 2507 #define R_ARM_THM_MOVW_ABS_NC 47 2508 #define R_ARM_THM_MOVT_ABS 48 2509 #define R_ARM_TLS_GOTDESC 90 2510 #define R_ARM_TLS_CALL 91 2511 #define R_ARM_TLS_DESCSEQ 92 2512 #define R_ARM_THM_TLS_CALL 93 2513 #define R_ARM_GNU_VTENTRY 100 2514 #define R_ARM_GNU_VTINHERIT 101 2515 #define R_ARM_THM_PC11 102 /* thumb unconditional branch */ 2516 #define R_ARM_THM_PC9 103 /* thumb conditional branch */ 2517 #define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic 2518 thread local data */ 2519 #define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic 2520 thread local data */ 2521 #define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS 2522 block */ 2523 #define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of 2524 static TLS block offset */ 2525 #define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static 2526 TLS block */ 2527 #define R_ARM_THM_TLS_DESCSEQ 129 2528 #define R_ARM_IRELATIVE 160 2529 #define R_ARM_RXPC25 249 2530 #define R_ARM_RSBREL32 250 2531 #define R_ARM_THM_RPC22 251 2532 #define R_ARM_RREL32 252 2533 #define R_ARM_RABS22 253 2534 #define R_ARM_RPC24 254 2535 #define R_ARM_RBASE 255 2536 /* Keep this the last entry. */ 2537 #define R_ARM_NUM 256 2538 2539 /* TMS320C67xx specific declarations */ 2540 2541 /* XXX: no ELF standard yet*/ 2542 2543 /* TMS320C67xx relocs. */ 2544 #define R_C60_32 1 2545 #define R_C60_GOT32 3 /* 32 bit GOT entry */ 2546 #define R_C60_PLT32 4 /* 32 bit PLT address */ 2547 #define R_C60_COPY 5 /* Copy symbol at runtime */ 2548 #define R_C60_GLOB_DAT 6 /* Create GOT entry */ 2549 #define R_C60_JMP_SLOT 7 /* Create PLT entry */ 2550 #define R_C60_RELATIVE 8 /* Adjust by program base */ 2551 #define R_C60_GOTOFF 9 /* 32 bit offset to GOT */ 2552 #define R_C60_GOTPC 10 /* 32 bit PC relative offset to GOT */ 2553 2554 #define R_C60LO16 0x54 /* low 16 bit MVKL embedded */ 2555 #define R_C60HI16 0x55 /* high 16 bit MVKH embedded */ 2556 /* Keep this the last entry. */ 2557 #define R_C60_NUM 0x56 2558 2559 /* IA-64 specific declarations. */ 2560 2561 /* Processor specific flags for the Ehdr e_flags field. */ 2562 #define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ 2563 #define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ 2564 #define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ 2565 2566 /* Processor specific values for the Phdr p_type field. */ 2567 #define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ 2568 #define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ 2569 #define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12) 2570 #define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13) 2571 #define PT_IA_64_HP_STACK (PT_LOOS + 0x14) 2572 2573 /* Processor specific flags for the Phdr p_flags field. */ 2574 #define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ 2575 2576 /* Processor specific values for the Shdr sh_type field. */ 2577 #define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ 2578 #define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ 2579 2580 /* Processor specific flags for the Shdr sh_flags field. */ 2581 #define SHF_IA_64_SHORT 0x10000000 /* section near gp */ 2582 #define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ 2583 2584 /* Processor specific values for the Dyn d_tag field. */ 2585 #define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) 2586 #define DT_IA_64_NUM 1 2587 2588 /* IA-64 relocations. */ 2589 #define R_IA64_NONE 0x00 /* none */ 2590 #define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ 2591 #define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ 2592 #define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ 2593 #define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ 2594 #define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ 2595 #define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ 2596 #define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ 2597 #define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ 2598 #define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ 2599 #define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ 2600 #define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ 2601 #define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ 2602 #define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ 2603 #define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ 2604 #define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ 2605 #define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ 2606 #define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ 2607 #define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ 2608 #define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ 2609 #define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ 2610 #define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ 2611 #define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ 2612 #define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ 2613 #define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ 2614 #define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ 2615 #define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ 2616 #define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ 2617 #define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ 2618 #define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ 2619 #define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ 2620 #define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ 2621 #define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ 2622 #define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ 2623 #define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ 2624 #define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ 2625 #define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ 2626 #define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ 2627 #define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ 2628 #define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ 2629 #define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ 2630 #define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ 2631 #define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ 2632 #define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ 2633 #define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ 2634 #define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ 2635 #define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ 2636 #define R_IA64_REL32MSB 0x6c /* data 4 + REL */ 2637 #define R_IA64_REL32LSB 0x6d /* data 4 + REL */ 2638 #define R_IA64_REL64MSB 0x6e /* data 8 + REL */ 2639 #define R_IA64_REL64LSB 0x6f /* data 8 + REL */ 2640 #define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ 2641 #define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ 2642 #define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ 2643 #define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ 2644 #define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ 2645 #define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ 2646 #define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ 2647 #define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ 2648 #define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ 2649 #define R_IA64_COPY 0x84 /* copy relocation */ 2650 #define R_IA64_SUB 0x85 /* Addend and symbol difference */ 2651 #define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ 2652 #define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ 2653 #define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ 2654 #define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ 2655 #define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ 2656 #define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ 2657 #define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ 2658 #define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ 2659 #define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ 2660 #define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ 2661 #define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ 2662 #define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ 2663 #define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ 2664 #define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ 2665 #define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ 2666 #define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ 2667 #define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ 2668 #define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ 2669 #define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ 2670 2671 /* SH specific declarations */ 2672 2673 /* Processor specific flags for the ELF header e_flags field. */ 2674 #define EF_SH_MACH_MASK 0x1f 2675 #define EF_SH_UNKNOWN 0x0 2676 #define EF_SH1 0x1 2677 #define EF_SH2 0x2 2678 #define EF_SH3 0x3 2679 #define EF_SH_DSP 0x4 2680 #define EF_SH3_DSP 0x5 2681 #define EF_SH4AL_DSP 0x6 2682 #define EF_SH3E 0x8 2683 #define EF_SH4 0x9 2684 #define EF_SH2E 0xb 2685 #define EF_SH4A 0xc 2686 #define EF_SH2A 0xd 2687 #define EF_SH4_NOFPU 0x10 2688 #define EF_SH4A_NOFPU 0x11 2689 #define EF_SH4_NOMMU_NOFPU 0x12 2690 #define EF_SH2A_NOFPU 0x13 2691 #define EF_SH3_NOMMU 0x14 2692 #define EF_SH2A_SH4_NOFPU 0x15 2693 #define EF_SH2A_SH3_NOFPU 0x16 2694 #define EF_SH2A_SH4 0x17 2695 #define EF_SH2A_SH3E 0x18 2696 2697 /* SH relocs. */ 2698 #define R_SH_NONE 0 2699 #define R_SH_DIR32 1 2700 #define R_SH_REL32 2 2701 #define R_SH_DIR8WPN 3 2702 #define R_SH_IND12W 4 2703 #define R_SH_DIR8WPL 5 2704 #define R_SH_DIR8WPZ 6 2705 #define R_SH_DIR8BP 7 2706 #define R_SH_DIR8W 8 2707 #define R_SH_DIR8L 9 2708 #define R_SH_SWITCH16 25 2709 #define R_SH_SWITCH32 26 2710 #define R_SH_USES 27 2711 #define R_SH_COUNT 28 2712 #define R_SH_ALIGN 29 2713 #define R_SH_CODE 30 2714 #define R_SH_DATA 31 2715 #define R_SH_LABEL 32 2716 #define R_SH_SWITCH8 33 2717 #define R_SH_GNU_VTINHERIT 34 2718 #define R_SH_GNU_VTENTRY 35 2719 #define R_SH_TLS_GD_32 144 2720 #define R_SH_TLS_LD_32 145 2721 #define R_SH_TLS_LDO_32 146 2722 #define R_SH_TLS_IE_32 147 2723 #define R_SH_TLS_LE_32 148 2724 #define R_SH_TLS_DTPMOD32 149 2725 #define R_SH_TLS_DTPOFF32 150 2726 #define R_SH_TLS_TPOFF32 151 2727 #define R_SH_GOT32 160 2728 #define R_SH_PLT32 161 2729 #define R_SH_COPY 162 2730 #define R_SH_GLOB_DAT 163 2731 #define R_SH_JMP_SLOT 164 2732 #define R_SH_RELATIVE 165 2733 #define R_SH_GOTOFF 166 2734 #define R_SH_GOTPC 167 2735 /* Keep this the last entry. */ 2736 #define R_SH_NUM 256 2737 2738 /* S/390 specific definitions. */ 2739 2740 /* Valid values for the e_flags field. */ 2741 2742 #define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. */ 2743 2744 /* Additional s390 relocs */ 2745 2746 #define R_390_NONE 0 /* No reloc. */ 2747 #define R_390_8 1 /* Direct 8 bit. */ 2748 #define R_390_12 2 /* Direct 12 bit. */ 2749 #define R_390_16 3 /* Direct 16 bit. */ 2750 #define R_390_32 4 /* Direct 32 bit. */ 2751 #define R_390_PC32 5 /* PC relative 32 bit. */ 2752 #define R_390_GOT12 6 /* 12 bit GOT offset. */ 2753 #define R_390_GOT32 7 /* 32 bit GOT offset. */ 2754 #define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ 2755 #define R_390_COPY 9 /* Copy symbol at runtime. */ 2756 #define R_390_GLOB_DAT 10 /* Create GOT entry. */ 2757 #define R_390_JMP_SLOT 11 /* Create PLT entry. */ 2758 #define R_390_RELATIVE 12 /* Adjust by program base. */ 2759 #define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ 2760 #define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ 2761 #define R_390_GOT16 15 /* 16 bit GOT offset. */ 2762 #define R_390_PC16 16 /* PC relative 16 bit. */ 2763 #define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ 2764 #define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ 2765 #define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ 2766 #define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ 2767 #define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ 2768 #define R_390_64 22 /* Direct 64 bit. */ 2769 #define R_390_PC64 23 /* PC relative 64 bit. */ 2770 #define R_390_GOT64 24 /* 64 bit GOT offset. */ 2771 #define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ 2772 #define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ 2773 #define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ 2774 #define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ 2775 #define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ 2776 #define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ 2777 #define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ 2778 #define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ 2779 #define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ 2780 #define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ 2781 #define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ 2782 #define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ 2783 #define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ 2784 #define R_390_TLS_GDCALL 38 /* Tag for function call in general 2785 dynamic TLS code. */ 2786 #define R_390_TLS_LDCALL 39 /* Tag for function call in local 2787 dynamic TLS code. */ 2788 #define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic 2789 thread local data. */ 2790 #define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic 2791 thread local data. */ 2792 #define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS 2793 block offset. */ 2794 #define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS 2795 block offset. */ 2796 #define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS 2797 block offset. */ 2798 #define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic 2799 thread local data in LE code. */ 2800 #define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic 2801 thread local data in LE code. */ 2802 #define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for 2803 negated static TLS block offset. */ 2804 #define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for 2805 negated static TLS block offset. */ 2806 #define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for 2807 negated static TLS block offset. */ 2808 #define R_390_TLS_LE32 50 /* 32 bit negated offset relative to 2809 static TLS block. */ 2810 #define R_390_TLS_LE64 51 /* 64 bit negated offset relative to 2811 static TLS block. */ 2812 #define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS 2813 block. */ 2814 #define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS 2815 block. */ 2816 #define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ 2817 #define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ 2818 #define R_390_TLS_TPOFF 56 /* Negated offset in static TLS 2819 block. */ 2820 #define R_390_20 57 /* Direct 20 bit. */ 2821 #define R_390_GOT20 58 /* 20 bit GOT offset. */ 2822 #define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ 2823 #define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS 2824 block offset. */ 2825 #define R_390_IRELATIVE 61 /* STT_GNU_IFUNC relocation. */ 2826 /* Keep this the last entry. */ 2827 #define R_390_NUM 62 2828 2829 2830 /* CRIS relocations. */ 2831 #define R_CRIS_NONE 0 2832 #define R_CRIS_8 1 2833 #define R_CRIS_16 2 2834 #define R_CRIS_32 3 2835 #define R_CRIS_8_PCREL 4 2836 #define R_CRIS_16_PCREL 5 2837 #define R_CRIS_32_PCREL 6 2838 #define R_CRIS_GNU_VTINHERIT 7 2839 #define R_CRIS_GNU_VTENTRY 8 2840 #define R_CRIS_COPY 9 2841 #define R_CRIS_GLOB_DAT 10 2842 #define R_CRIS_JUMP_SLOT 11 2843 #define R_CRIS_RELATIVE 12 2844 #define R_CRIS_16_GOT 13 2845 #define R_CRIS_32_GOT 14 2846 #define R_CRIS_16_GOTPLT 15 2847 #define R_CRIS_32_GOTPLT 16 2848 #define R_CRIS_32_GOTREL 17 2849 #define R_CRIS_32_PLT_GOTREL 18 2850 #define R_CRIS_32_PLT_PCREL 19 2851 2852 #define R_CRIS_NUM 20 2853 1047 2854 1048 2855 /* AMD x86-64 relocations. */ … … 1075 2882 to GOT entry for IE symbol */ 1076 2883 #define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ 1077 1078 #define R_X86_64_NUM 24 1079 1080 /* For Sparc64, legal values for d_tag of Elf64_Dyn. */ 1081 1082 #define DT_SPARC_REGISTER 0x70000001 1083 #define DT_SPARC_NUM 2 1084 1085 /* Bits present in AT_HWCAP, primarily for Sparc32. */ 1086 1087 #define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */ 1088 #define HWCAP_SPARC_STBAR 2 1089 #define HWCAP_SPARC_SWAP 4 1090 #define HWCAP_SPARC_MULDIV 8 1091 #define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */ 1092 1093 /* MIPS R3000 specific definitions. */ 1094 1095 /* Legal values for e_flags field of Elf32_Ehdr. */ 1096 1097 #define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ 1098 #define EF_MIPS_PIC 2 /* Contains PIC code */ 1099 #define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ 1100 #define EF_MIPS_XGOT 8 1101 #define EF_MIPS_64BIT_WHIRL 16 1102 #define EF_MIPS_ABI2 32 1103 #define EF_MIPS_ABI_ON32 64 1104 #define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ 1105 1106 /* Legal values for MIPS architecture level. */ 1107 1108 #define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ 1109 #define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ 1110 #define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ 1111 #define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ 1112 #define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ 1113 1114 /* The following are non-official names and should not be used. */ 1115 1116 #define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ 1117 #define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ 1118 #define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ 1119 #define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ 1120 #define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ 1121 1122 /* Special section indices. */ 1123 1124 #define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ 1125 #define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ 1126 #define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ 1127 #define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ 1128 #define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ 1129 1130 /* Legal values for sh_type field of Elf32_Shdr. */ 1131 1132 #define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ 1133 #define SHT_MIPS_MSYM 0x70000001 1134 #define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ 1135 #define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ 1136 #define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ 1137 #define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/ 1138 #define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ 1139 #define SHT_MIPS_PACKAGE 0x70000007 1140 #define SHT_MIPS_PACKSYM 0x70000008 1141 #define SHT_MIPS_RELD 0x70000009 1142 #define SHT_MIPS_IFACE 0x7000000b 1143 #define SHT_MIPS_CONTENT 0x7000000c 1144 #define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ 1145 #define SHT_MIPS_SHDR 0x70000010 1146 #define SHT_MIPS_FDESC 0x70000011 1147 #define SHT_MIPS_EXTSYM 0x70000012 1148 #define SHT_MIPS_DENSE 0x70000013 1149 #define SHT_MIPS_PDESC 0x70000014 1150 #define SHT_MIPS_LOCSYM 0x70000015 1151 #define SHT_MIPS_AUXSYM 0x70000016 1152 #define SHT_MIPS_OPTSYM 0x70000017 1153 #define SHT_MIPS_LOCSTR 0x70000018 1154 #define SHT_MIPS_LINE 0x70000019 1155 #define SHT_MIPS_RFDESC 0x7000001a 1156 #define SHT_MIPS_DELTASYM 0x7000001b 1157 #define SHT_MIPS_DELTAINST 0x7000001c 1158 #define SHT_MIPS_DELTACLASS 0x7000001d 1159 #define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ 1160 #define SHT_MIPS_DELTADECL 0x7000001f 1161 #define SHT_MIPS_SYMBOL_LIB 0x70000020 1162 #define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ 1163 #define SHT_MIPS_TRANSLATE 0x70000022 1164 #define SHT_MIPS_PIXIE 0x70000023 1165 #define SHT_MIPS_XLATE 0x70000024 1166 #define SHT_MIPS_XLATE_DEBUG 0x70000025 1167 #define SHT_MIPS_WHIRL 0x70000026 1168 #define SHT_MIPS_EH_REGION 0x70000027 1169 #define SHT_MIPS_XLATE_OLD 0x70000028 1170 #define SHT_MIPS_PDR_EXCEPTION 0x70000029 1171 1172 /* Legal values for sh_flags field of Elf32_Shdr. */ 1173 1174 #define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ 1175 #define SHF_MIPS_MERGE 0x20000000 1176 #define SHF_MIPS_ADDR 0x40000000 1177 #define SHF_MIPS_STRINGS 0x80000000 1178 #define SHF_MIPS_NOSTRIP 0x08000000 1179 #define SHF_MIPS_LOCAL 0x04000000 1180 #define SHF_MIPS_NAMES 0x02000000 1181 #define SHF_MIPS_NODUPE 0x01000000 1182 1183 1184 /* Symbol tables. */ 1185 1186 /* MIPS specific values for `st_other'. */ 1187 #define STO_MIPS_DEFAULT 0x0 1188 #define STO_MIPS_INTERNAL 0x1 1189 #define STO_MIPS_HIDDEN 0x2 1190 #define STO_MIPS_PROTECTED 0x3 1191 #define STO_MIPS_SC_ALIGN_UNUSED 0xff 1192 1193 /* MIPS specific values for `st_info'. */ 1194 #define STB_MIPS_SPLIT_COMMON 13 1195 1196 /* Entries found in sections of type SHT_MIPS_GPTAB. */ 1197 1198 typedef union 1199 { 1200 struct 1201 { 1202 Elf32_Word gt_current_g_value; /* -G value used for compilation */ 1203 Elf32_Word gt_unused; /* Not used */ 1204 } gt_header; /* First entry in section */ 1205 struct 1206 { 1207 Elf32_Word gt_g_value; /* If this value were used for -G */ 1208 Elf32_Word gt_bytes; /* This many bytes would be used */ 1209 } gt_entry; /* Subsequent entries in section */ 1210 } Elf32_gptab; 1211 1212 /* Entry found in sections of type SHT_MIPS_REGINFO. */ 1213 1214 typedef struct 1215 { 1216 Elf32_Word ri_gprmask; /* General registers used */ 1217 Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ 1218 Elf32_Sword ri_gp_value; /* $gp register value */ 1219 } Elf32_RegInfo; 1220 1221 /* Entries found in sections of type SHT_MIPS_OPTIONS. */ 1222 1223 typedef struct 1224 { 1225 unsigned char kind; /* Determines interpretation of the 1226 variable part of descriptor. */ 1227 unsigned char size; /* Size of descriptor, including header. */ 1228 Elf32_Section section; /* Section header index of section affected, 1229 0 for global options. */ 1230 Elf32_Word info; /* Kind-specific information. */ 1231 } Elf_Options; 1232 1233 /* Values for `kind' field in Elf_Options. */ 1234 1235 #define ODK_NULL 0 /* Undefined. */ 1236 #define ODK_REGINFO 1 /* Register usage information. */ 1237 #define ODK_EXCEPTIONS 2 /* Exception processing options. */ 1238 #define ODK_PAD 3 /* Section padding options. */ 1239 #define ODK_HWPATCH 4 /* Hardware workarounds performed */ 1240 #define ODK_FILL 5 /* record the fill value used by the linker. */ 1241 #define ODK_TAGS 6 /* reserve space for desktop tools to write. */ 1242 #define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ 1243 #define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ 1244 1245 /* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ 1246 1247 #define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ 1248 #define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ 1249 #define OEX_PAGE0 0x10000 /* page zero must be mapped. */ 1250 #define OEX_SMM 0x20000 /* Force sequential memory mode? */ 1251 #define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ 1252 #define OEX_PRECISEFP OEX_FPDBUG 1253 #define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ 1254 1255 #define OEX_FPU_INVAL 0x10 1256 #define OEX_FPU_DIV0 0x08 1257 #define OEX_FPU_OFLO 0x04 1258 #define OEX_FPU_UFLO 0x02 1259 #define OEX_FPU_INEX 0x01 1260 1261 /* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ 1262 1263 #define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ 1264 #define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ 1265 #define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ 1266 #define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ 1267 1268 #define OPAD_PREFIX 0x1 1269 #define OPAD_POSTFIX 0x2 1270 #define OPAD_SYMBOL 0x4 1271 1272 /* Entry found in `.options' section. */ 1273 1274 typedef struct 1275 { 1276 Elf32_Word hwp_flags1; /* Extra flags. */ 1277 Elf32_Word hwp_flags2; /* Extra flags. */ 1278 } Elf_Options_Hw; 1279 1280 /* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ 1281 1282 #define OHWA0_R4KEOP_CHECKED 0x00000001 1283 #define OHWA1_R4KEOP_CLEAN 0x00000002 1284 1285 /* MIPS relocs. */ 1286 1287 #define R_MIPS_NONE 0 /* No reloc */ 1288 #define R_MIPS_16 1 /* Direct 16 bit */ 1289 #define R_MIPS_32 2 /* Direct 32 bit */ 1290 #define R_MIPS_REL32 3 /* PC relative 32 bit */ 1291 #define R_MIPS_26 4 /* Direct 26 bit shifted */ 1292 #define R_MIPS_HI16 5 /* High 16 bit */ 1293 #define R_MIPS_LO16 6 /* Low 16 bit */ 1294 #define R_MIPS_GPREL16 7 /* GP relative 16 bit */ 1295 #define R_MIPS_LITERAL 8 /* 16 bit literal entry */ 1296 #define R_MIPS_GOT16 9 /* 16 bit GOT entry */ 1297 #define R_MIPS_PC16 10 /* PC relative 16 bit */ 1298 #define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ 1299 #define R_MIPS_GPREL32 12 /* GP relative 32 bit */ 1300 1301 #define R_MIPS_SHIFT5 16 1302 #define R_MIPS_SHIFT6 17 1303 #define R_MIPS_64 18 1304 #define R_MIPS_GOT_DISP 19 1305 #define R_MIPS_GOT_PAGE 20 1306 #define R_MIPS_GOT_OFST 21 1307 #define R_MIPS_GOT_HI16 22 1308 #define R_MIPS_GOT_LO16 23 1309 #define R_MIPS_SUB 24 1310 #define R_MIPS_INSERT_A 25 1311 #define R_MIPS_INSERT_B 26 1312 #define R_MIPS_DELETE 27 1313 #define R_MIPS_HIGHER 28 1314 #define R_MIPS_HIGHEST 29 1315 #define R_MIPS_CALL_HI16 30 1316 #define R_MIPS_CALL_LO16 31 1317 #define R_MIPS_SCN_DISP 32 1318 #define R_MIPS_REL16 33 1319 #define R_MIPS_ADD_IMMEDIATE 34 1320 #define R_MIPS_PJUMP 35 1321 #define R_MIPS_RELGOT 36 1322 #define R_MIPS_JALR 37 1323 /* Keep this the last entry. */ 1324 #define R_MIPS_NUM 38 1325 1326 /* Legal values for p_type field of Elf32_Phdr. */ 1327 1328 #define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ 1329 #define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ 1330 #define PT_MIPS_OPTIONS 0x70000002 1331 1332 /* Special program header types. */ 1333 1334 #define PF_MIPS_LOCAL 0x10000000 1335 1336 /* Legal values for d_tag field of Elf32_Dyn. */ 1337 1338 #define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ 1339 #define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ 1340 #define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ 1341 #define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ 1342 #define DT_MIPS_FLAGS 0x70000005 /* Flags */ 1343 #define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ 1344 #define DT_MIPS_MSYM 0x70000007 1345 #define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ 1346 #define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ 1347 #define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ 1348 #define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ 1349 #define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ 1350 #define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ 1351 #define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ 1352 #define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ 1353 #define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ 1354 #define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ 1355 #define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ 1356 #define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in 1357 DT_MIPS_DELTA_CLASS. */ 1358 #define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ 1359 #define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in 1360 DT_MIPS_DELTA_INSTANCE. */ 1361 #define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ 1362 #define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in 1363 DT_MIPS_DELTA_RELOC. */ 1364 #define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta 1365 relocations refer to. */ 1366 #define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in 1367 DT_MIPS_DELTA_SYM. */ 1368 #define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the 1369 class declaration. */ 1370 #define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in 1371 DT_MIPS_DELTA_CLASSSYM. */ 1372 #define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ 1373 #define DT_MIPS_PIXIE_INIT 0x70000023 1374 #define DT_MIPS_SYMBOL_LIB 0x70000024 1375 #define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 1376 #define DT_MIPS_LOCAL_GOTIDX 0x70000026 1377 #define DT_MIPS_HIDDEN_GOTIDX 0x70000027 1378 #define DT_MIPS_PROTECTED_GOTIDX 0x70000028 1379 #define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ 1380 #define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ 1381 #define DT_MIPS_DYNSTR_ALIGN 0x7000002b 1382 #define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ 1383 #define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve 1384 function stored in GOT. */ 1385 #define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added 1386 by rld on dlopen() calls. */ 1387 #define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ 1388 #define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ 1389 #define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ 1390 #define DT_MIPS_NUM 0x32 1391 1392 /* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ 1393 1394 #define RHF_NONE 0 /* No flags */ 1395 #define RHF_QUICKSTART (1 << 0) /* Use quickstart */ 1396 #define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ 1397 #define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ 1398 #define RHF_NO_MOVE (1 << 3) 1399 #define RHF_SGI_ONLY (1 << 4) 1400 #define RHF_GUARANTEE_INIT (1 << 5) 1401 #define RHF_DELTA_C_PLUS_PLUS (1 << 6) 1402 #define RHF_GUARANTEE_START_INIT (1 << 7) 1403 #define RHF_PIXIE (1 << 8) 1404 #define RHF_DEFAULT_DELAY_LOAD (1 << 9) 1405 #define RHF_REQUICKSTART (1 << 10) 1406 #define RHF_REQUICKSTARTED (1 << 11) 1407 #define RHF_CORD (1 << 12) 1408 #define RHF_NO_UNRES_UNDEF (1 << 13) 1409 #define RHF_RLD_ORDER_SAFE (1 << 14) 1410 1411 /* Entries found in sections of type SHT_MIPS_LIBLIST. */ 1412 1413 typedef struct 1414 { 1415 Elf32_Word l_name; /* Name (string table index) */ 1416 Elf32_Word l_time_stamp; /* Timestamp */ 1417 Elf32_Word l_checksum; /* Checksum */ 1418 Elf32_Word l_version; /* Interface version */ 1419 Elf32_Word l_flags; /* Flags */ 1420 } Elf32_Lib; 1421 1422 typedef struct 1423 { 1424 Elf64_Word l_name; /* Name (string table index) */ 1425 Elf64_Word l_time_stamp; /* Timestamp */ 1426 Elf64_Word l_checksum; /* Checksum */ 1427 Elf64_Word l_version; /* Interface version */ 1428 Elf64_Word l_flags; /* Flags */ 1429 } Elf64_Lib; 1430 1431 1432 /* Legal values for l_flags. */ 1433 1434 #define LL_NONE 0 1435 #define LL_EXACT_MATCH (1 << 0) /* Require exact match */ 1436 #define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ 1437 #define LL_REQUIRE_MINOR (1 << 2) 1438 #define LL_EXPORTS (1 << 3) 1439 #define LL_DELAY_LOAD (1 << 4) 1440 #define LL_DELTA (1 << 5) 1441 1442 /* Entries found in sections of type SHT_MIPS_CONFLICT. */ 1443 1444 typedef Elf32_Addr Elf32_Conflict; 1445 1446 1447 /* HPPA specific definitions. */ 1448 1449 /* Legal values for e_flags field of Elf32_Ehdr. */ 1450 1451 #define EF_PARISC_TRAPNL 1 /* Trap nil pointer dereference. */ 1452 #define EF_PARISC_EXT 2 /* Program uses arch. extensions. */ 1453 #define EF_PARISC_ARCH 0xffff0000 /* Architecture version. */ 1454 /* Defined values are: 1455 0x020b PA-RISC 1.0 big-endian 1456 0x0210 PA-RISC 1.1 big-endian 1457 0x028b PA-RISC 1.0 little-endian 1458 0x0290 PA-RISC 1.1 little-endian 1459 */ 1460 1461 /* Legal values for sh_type field of Elf32_Shdr. */ 1462 1463 #define SHT_PARISC_GOT 0x70000000 /* GOT for external data. */ 1464 #define SHT_PARISC_ARCH 0x70000001 /* Architecture extensions. */ 1465 #define SHT_PARISC_GLOBAL 0x70000002 /* Definition of $global$. */ 1466 #define SHT_PARISC_MILLI 0x70000003 /* Millicode routines. */ 1467 #define SHT_PARISC_UNWIND 0x70000004 /* Unwind information. */ 1468 #define SHT_PARISC_PLT 0x70000005 /* Procedure linkage table. */ 1469 #define SHT_PARISC_SDATA 0x70000006 /* Short initialized data. */ 1470 #define SHT_PARISC_SBSS 0x70000007 /* Short uninitialized data. */ 1471 #define SHT_PARISC_SYMEXTN 0x70000008 /* Argument/relocation info. */ 1472 #define SHT_PARISC_STUBS 0x70000009 /* Linker stubs. */ 1473 1474 /* Legal values for sh_flags field of Elf32_Shdr. */ 1475 1476 #define SHF_PARISC_GLOBAL 0x10000000 /* Section defines dp. */ 1477 #define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ 1478 1479 /* Legal values for ST_TYPE subfield of st_info (symbol type). */ 1480 1481 #define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ 1482 1483 /* HPPA relocs. */ 1484 1485 #define R_PARISC_NONE 0 /* No reloc. */ 1486 #define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ 1487 #define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ 1488 #define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ 1489 #define R_PARISC_DIR14R 4 /* Right 14 bits of eff. address. */ 1490 #define R_PARISC_PCREL21L 5 /* PC-relative, left 21 bits. */ 1491 #define R_PARISC_PCREL14R 6 /* PC-relative, right 14 bits. */ 1492 #define R_PARISC_PCREL17C 7 /* Conditional PC-relative, ignore 1493 if displacement > 17bits. */ 1494 #define R_PARISC_PCREL17F 8 /* Conditional PC-relative, must 1495 fit in 17bits. */ 1496 #define R_PARISC_DPREL21L 9 /* DP-relative, left 21 bits. */ 1497 #define R_PARISC_DPREL14R 10 /* DP-relative, right 14 bits. */ 1498 #define R_PARISC_DPREL14F 11 /* DP-relative, must bit in 14 bits. */ 1499 #define R_PARISC_DLTREL21L 12 /* DLT-relative, left 21 bits. */ 1500 #define R_PARISC_DLTREL14R 13 /* DLT-relative, right 14 bits. */ 1501 #define R_PARISC_DLTREL14F 14 /* DLT-relative, must fit in 14 bits.*/ 1502 #define R_PARISC_DLTIND21L 15 /* DLT-relative indirect, left 1503 21 bits. */ 1504 #define R_PARISC_DLTIND14R 16 /* DLT-relative indirect, right 1505 14 bits. */ 1506 #define R_PARISC_DLTIND14F 17 /* DLT-relative indirect, must fit 1507 int 14 bits. */ 1508 #define R_PARISC_PLABEL32 18 /* Direct 32-bit reference to proc. */ 1509 1510 /* Alpha specific definitions. */ 1511 1512 /* Legal values for e_flags field of Elf64_Ehdr. */ 1513 1514 #define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ 1515 #define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ 1516 1517 /* Legal values for sh_type field of Elf64_Shdr. */ 1518 1519 /* These two are primerily concerned with ECOFF debugging info. */ 1520 #define SHT_ALPHA_DEBUG 0x70000001 1521 #define SHT_ALPHA_REGINFO 0x70000002 1522 1523 /* Legal values for sh_flags field of Elf64_Shdr. */ 1524 1525 #define SHF_ALPHA_GPREL 0x10000000 1526 1527 /* Legal values for st_other field of Elf64_Sym. */ 1528 #define STO_ALPHA_NOPV 0x80 /* No PV required. */ 1529 #define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ 1530 1531 /* Alpha relocs. */ 1532 1533 #define R_ALPHA_NONE 0 /* No reloc */ 1534 #define R_ALPHA_REFLONG 1 /* Direct 32 bit */ 1535 #define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ 1536 #define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ 1537 #define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ 1538 #define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ 1539 #define R_ALPHA_GPDISP 6 /* Add displacement to GP */ 1540 #define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ 1541 #define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ 1542 #define R_ALPHA_SREL16 9 /* PC relative 16 bit */ 1543 #define R_ALPHA_SREL32 10 /* PC relative 32 bit */ 1544 #define R_ALPHA_SREL64 11 /* PC relative 64 bit */ 1545 #define R_ALPHA_OP_PUSH 12 /* OP stack push */ 1546 #define R_ALPHA_OP_STORE 13 /* OP stack pop and store */ 1547 #define R_ALPHA_OP_PSUB 14 /* OP stack subtract */ 1548 #define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */ 1549 #define R_ALPHA_GPVALUE 16 1550 #define R_ALPHA_GPRELHIGH 17 1551 #define R_ALPHA_GPRELLOW 18 1552 #define R_ALPHA_IMMED_GP_16 19 1553 #define R_ALPHA_IMMED_GP_HI32 20 1554 #define R_ALPHA_IMMED_SCN_HI32 21 1555 #define R_ALPHA_IMMED_BR_HI32 22 1556 #define R_ALPHA_IMMED_LO32 23 1557 #define R_ALPHA_COPY 24 /* Copy symbol at runtime */ 1558 #define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ 1559 #define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ 1560 #define R_ALPHA_RELATIVE 27 /* Adjust by program base */ 1561 /* Keep this the last entry. */ 1562 #define R_ALPHA_NUM 28 1563 1564 1565 /* PowerPC specific declarations */ 1566 1567 /* PowerPC relocations defined by the ABIs */ 1568 #define R_PPC_NONE 0 1569 #define R_PPC_ADDR32 1 /* 32bit absolute address */ 1570 #define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ 1571 #define R_PPC_ADDR16 3 /* 16bit absolute address */ 1572 #define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ 1573 #define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ 1574 #define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ 1575 #define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ 1576 #define R_PPC_ADDR14_BRTAKEN 8 1577 #define R_PPC_ADDR14_BRNTAKEN 9 1578 #define R_PPC_REL24 10 /* PC relative 26 bit */ 1579 #define R_PPC_REL14 11 /* PC relative 16 bit */ 1580 #define R_PPC_REL14_BRTAKEN 12 1581 #define R_PPC_REL14_BRNTAKEN 13 1582 #define R_PPC_GOT16 14 1583 #define R_PPC_GOT16_LO 15 1584 #define R_PPC_GOT16_HI 16 1585 #define R_PPC_GOT16_HA 17 1586 #define R_PPC_PLTREL24 18 1587 #define R_PPC_COPY 19 1588 #define R_PPC_GLOB_DAT 20 1589 #define R_PPC_JMP_SLOT 21 1590 #define R_PPC_RELATIVE 22 1591 #define R_PPC_LOCAL24PC 23 1592 #define R_PPC_UADDR32 24 1593 #define R_PPC_UADDR16 25 1594 #define R_PPC_REL32 26 1595 #define R_PPC_PLT32 27 1596 #define R_PPC_PLTREL32 28 1597 #define R_PPC_PLT16_LO 29 1598 #define R_PPC_PLT16_HI 30 1599 #define R_PPC_PLT16_HA 31 1600 #define R_PPC_SDAREL16 32 1601 #define R_PPC_SECTOFF 33 1602 #define R_PPC_SECTOFF_LO 34 1603 #define R_PPC_SECTOFF_HI 35 1604 #define R_PPC_SECTOFF_HA 36 1605 /* Keep this the last entry. */ 1606 #define R_PPC_NUM 37 1607 1608 /* The remaining relocs are from the Embedded ELF ABI, and are not 1609 in the SVR4 ELF ABI. */ 1610 #define R_PPC_EMB_NADDR32 101 1611 #define R_PPC_EMB_NADDR16 102 1612 #define R_PPC_EMB_NADDR16_LO 103 1613 #define R_PPC_EMB_NADDR16_HI 104 1614 #define R_PPC_EMB_NADDR16_HA 105 1615 #define R_PPC_EMB_SDAI16 106 1616 #define R_PPC_EMB_SDA2I16 107 1617 #define R_PPC_EMB_SDA2REL 108 1618 #define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ 1619 #define R_PPC_EMB_MRKREF 110 1620 #define R_PPC_EMB_RELSEC16 111 1621 #define R_PPC_EMB_RELST_LO 112 1622 #define R_PPC_EMB_RELST_HI 113 1623 #define R_PPC_EMB_RELST_HA 114 1624 #define R_PPC_EMB_BIT_FLD 115 1625 #define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ 1626 1627 /* Diab tool relocations. */ 1628 #define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ 1629 #define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ 1630 #define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ 1631 #define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ 1632 #define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ 1633 #define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ 1634 1635 /* This is a phony reloc to handle any old fashioned TOC16 references 1636 that may still be in object files. */ 1637 #define R_PPC_TOC16 255 1638 1639 1640 /* ARM specific declarations */ 1641 1642 /* Processor specific flags for the ELF header e_flags field. */ 1643 #define EF_ARM_RELEXEC 0x01 1644 #define EF_ARM_HASENTRY 0x02 1645 #define EF_ARM_INTERWORK 0x04 1646 #define EF_ARM_APCS_26 0x08 1647 #define EF_ARM_APCS_FLOAT 0x10 1648 #define EF_ARM_PIC 0x20 1649 #define EF_ALIGN8 0x40 /* 8-bit structure alignment is in use */ 1650 #define EF_NEW_ABI 0x80 1651 #define EF_OLD_ABI 0x100 1652 1653 /* Additional symbol types for Thumb */ 1654 #define STT_ARM_TFUNC 0xd 1655 1656 /* ARM-specific values for sh_flags */ 1657 #define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ 1658 #define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined 1659 in the input to a link step */ 1660 1661 /* ARM-specific program header flags */ 1662 #define PF_ARM_SB 0x10000000 /* Segment contains the location 1663 addressed by the static base */ 1664 1665 /* ARM relocs. */ 1666 #define R_ARM_NONE 0 /* No reloc */ 1667 #define R_ARM_PC24 1 /* PC relative 26 bit branch */ 1668 #define R_ARM_ABS32 2 /* Direct 32 bit */ 1669 #define R_ARM_REL32 3 /* PC relative 32 bit */ 1670 #define R_ARM_PC13 4 1671 #define R_ARM_ABS16 5 /* Direct 16 bit */ 1672 #define R_ARM_ABS12 6 /* Direct 12 bit */ 1673 #define R_ARM_THM_ABS5 7 1674 #define R_ARM_ABS8 8 /* Direct 8 bit */ 1675 #define R_ARM_SBREL32 9 1676 #define R_ARM_THM_CALL 10 1677 #define R_ARM_THM_PC8 11 1678 #define R_ARM_AMP_VCALL9 12 1679 #define R_ARM_SWI24 13 1680 #define R_ARM_THM_SWI8 14 1681 #define R_ARM_XPC25 15 1682 #define R_ARM_THM_XPC22 16 1683 #define R_ARM_COPY 20 /* Copy symbol at runtime */ 1684 #define R_ARM_GLOB_DAT 21 /* Create GOT entry */ 1685 #define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ 1686 #define R_ARM_RELATIVE 23 /* Adjust by program base */ 1687 #define R_ARM_GOTOFF32 24 /* 32 bit offset to GOT */ 1688 #define R_ARM_BASE_PREL 25 /* 32 bit PC relative offset to GOT */ 1689 #define R_ARM_GOT_BREL 26 /* 32 bit GOT entry */ 1690 #define R_ARM_PLT32 27 /* 32 bit PLT address */ 1691 #define R_ARM_CALL 28 1692 #define R_ARM_JUMP24 29 1693 #define R_ARM_THM_JUMP24 30 1694 #define R_ARM_V4BX 40 1695 #define R_ARM_PREL31 42 1696 #define R_ARM_MOVW_ABS_NC 43 1697 #define R_ARM_MOVT_ABS 44 1698 #define R_ARM_THM_MOVW_ABS_NC 47 1699 #define R_ARM_THM_MOVT_ABS 48 1700 #define R_ARM_GNU_VTENTRY 100 1701 #define R_ARM_GNU_VTINHERIT 101 1702 #define R_ARM_THM_PC11 102 /* thumb unconditional branch */ 1703 #define R_ARM_THM_PC9 103 /* thumb conditional branch */ 1704 #define R_ARM_RXPC25 249 1705 #define R_ARM_RSBREL32 250 1706 #define R_ARM_THM_RPC22 251 1707 #define R_ARM_RREL32 252 1708 #define R_ARM_RABS22 253 1709 #define R_ARM_RPC24 254 1710 #define R_ARM_RBASE 255 1711 /* Keep this the last entry. */ 1712 #define R_ARM_NUM 256 1713 1714 /* TMS320C67xx specific declarations */ 1715 /* XXX: no ELF standard yet */ 1716 1717 /* TMS320C67xx relocs. */ 1718 #define R_C60_32 1 1719 #define R_C60_GOT32 3 /* 32 bit GOT entry */ 1720 #define R_C60_PLT32 4 /* 32 bit PLT address */ 1721 #define R_C60_COPY 5 /* Copy symbol at runtime */ 1722 #define R_C60_GLOB_DAT 6 /* Create GOT entry */ 1723 #define R_C60_JMP_SLOT 7 /* Create PLT entry */ 1724 #define R_C60_RELATIVE 8 /* Adjust by program base */ 1725 #define R_C60_GOTOFF 9 /* 32 bit offset to GOT */ 1726 #define R_C60_GOTPC 10 /* 32 bit PC relative offset to GOT */ 1727 1728 #define R_C60HI16 0x55 // high 16 bit MVKH embedded 1729 #define R_C60LO16 0x54 // low 16 bit MVKL embedded 1730 1731 #endif /* elf.h */ 2884 #define R_X86_64_PC64 24 /* PC relative 64 bit */ 2885 #define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ 2886 #define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative 2887 offset to GOT */ 2888 #define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */ 2889 #define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset 2890 to GOT entry */ 2891 #define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */ 2892 #define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */ 2893 #define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset 2894 to PLT entry */ 2895 #define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */ 2896 #define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */ 2897 #define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ 2898 #define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS 2899 descriptor. */ 2900 #define R_X86_64_TLSDESC 36 /* TLS descriptor. */ 2901 #define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ 2902 #define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */ 2903 #define R_X86_64_GOTPCRELX 41 /* like GOTPCREL, but optionally with 2904 linker optimizations */ 2905 #define R_X86_64_REX_GOTPCRELX 42 /* like GOTPCRELX, but a REX prefix 2906 is present */ 2907 2908 #define R_X86_64_NUM 43 2909 2910 2911 /* AM33 relocations. */ 2912 #define R_MN10300_NONE 0 /* No reloc. */ 2913 #define R_MN10300_32 1 /* Direct 32 bit. */ 2914 #define R_MN10300_16 2 /* Direct 16 bit. */ 2915 #define R_MN10300_8 3 /* Direct 8 bit. */ 2916 #define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */ 2917 #define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */ 2918 #define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */ 2919 #define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */ 2920 #define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */ 2921 #define R_MN10300_24 9 /* Direct 24 bit. */ 2922 #define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */ 2923 #define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */ 2924 #define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */ 2925 #define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */ 2926 #define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */ 2927 #define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */ 2928 #define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */ 2929 #define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */ 2930 #define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */ 2931 #define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */ 2932 #define R_MN10300_COPY 20 /* Copy symbol at runtime. */ 2933 #define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */ 2934 #define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */ 2935 #define R_MN10300_RELATIVE 23 /* Adjust by program base. */ 2936 #define R_MN10300_TLS_GD 24 /* 32-bit offset for global dynamic. */ 2937 #define R_MN10300_TLS_LD 25 /* 32-bit offset for local dynamic. */ 2938 #define R_MN10300_TLS_LDO 26 /* Module-relative offset. */ 2939 #define R_MN10300_TLS_GOTIE 27 /* GOT offset for static TLS block 2940 offset. */ 2941 #define R_MN10300_TLS_IE 28 /* GOT address for static TLS block 2942 offset. */ 2943 #define R_MN10300_TLS_LE 29 /* Offset relative to static TLS 2944 block. */ 2945 #define R_MN10300_TLS_DTPMOD 30 /* ID of module containing symbol. */ 2946 #define R_MN10300_TLS_DTPOFF 31 /* Offset in module TLS block. */ 2947 #define R_MN10300_TLS_TPOFF 32 /* Offset in static TLS block. */ 2948 #define R_MN10300_SYM_DIFF 33 /* Adjustment for next reloc as needed 2949 by linker relaxation. */ 2950 #define R_MN10300_ALIGN 34 /* Alignment requirement for linker 2951 relaxation. */ 2952 #define R_MN10300_NUM 35 2953 2954 2955 /* M32R relocs. */ 2956 #define R_M32R_NONE 0 /* No reloc. */ 2957 #define R_M32R_16 1 /* Direct 16 bit. */ 2958 #define R_M32R_32 2 /* Direct 32 bit. */ 2959 #define R_M32R_24 3 /* Direct 24 bit. */ 2960 #define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */ 2961 #define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */ 2962 #define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */ 2963 #define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */ 2964 #define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */ 2965 #define R_M32R_LO16 9 /* Low 16 bit. */ 2966 #define R_M32R_SDA16 10 /* 16 bit offset in SDA. */ 2967 #define R_M32R_GNU_VTINHERIT 11 2968 #define R_M32R_GNU_VTENTRY 12 2969 /* M32R relocs use SHT_RELA. */ 2970 #define R_M32R_16_RELA 33 /* Direct 16 bit. */ 2971 #define R_M32R_32_RELA 34 /* Direct 32 bit. */ 2972 #define R_M32R_24_RELA 35 /* Direct 24 bit. */ 2973 #define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */ 2974 #define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */ 2975 #define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */ 2976 #define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */ 2977 #define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */ 2978 #define R_M32R_LO16_RELA 41 /* Low 16 bit */ 2979 #define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */ 2980 #define R_M32R_RELA_GNU_VTINHERIT 43 2981 #define R_M32R_RELA_GNU_VTENTRY 44 2982 #define R_M32R_REL32 45 /* PC relative 32 bit. */ 2983 2984 #define R_M32R_GOT24 48 /* 24 bit GOT entry */ 2985 #define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */ 2986 #define R_M32R_COPY 50 /* Copy symbol at runtime */ 2987 #define R_M32R_GLOB_DAT 51 /* Create GOT entry */ 2988 #define R_M32R_JMP_SLOT 52 /* Create PLT entry */ 2989 #define R_M32R_RELATIVE 53 /* Adjust by program base */ 2990 #define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */ 2991 #define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */ 2992 #define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned 2993 low */ 2994 #define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed 2995 low */ 2996 #define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */ 2997 #define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to 2998 GOT with unsigned low */ 2999 #define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to 3000 GOT with signed low */ 3001 #define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to 3002 GOT */ 3003 #define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT 3004 with unsigned low */ 3005 #define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT 3006 with signed low */ 3007 #define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */ 3008 #define R_M32R_NUM 256 /* Keep this the last entry. */ 3009 3010 3011 /* TILEPro relocations. */ 3012 #define R_TILEPRO_NONE 0 /* No reloc */ 3013 #define R_TILEPRO_32 1 /* Direct 32 bit */ 3014 #define R_TILEPRO_16 2 /* Direct 16 bit */ 3015 #define R_TILEPRO_8 3 /* Direct 8 bit */ 3016 #define R_TILEPRO_32_PCREL 4 /* PC relative 32 bit */ 3017 #define R_TILEPRO_16_PCREL 5 /* PC relative 16 bit */ 3018 #define R_TILEPRO_8_PCREL 6 /* PC relative 8 bit */ 3019 #define R_TILEPRO_LO16 7 /* Low 16 bit */ 3020 #define R_TILEPRO_HI16 8 /* High 16 bit */ 3021 #define R_TILEPRO_HA16 9 /* High 16 bit, adjusted */ 3022 #define R_TILEPRO_COPY 10 /* Copy relocation */ 3023 #define R_TILEPRO_GLOB_DAT 11 /* Create GOT entry */ 3024 #define R_TILEPRO_JMP_SLOT 12 /* Create PLT entry */ 3025 #define R_TILEPRO_RELATIVE 13 /* Adjust by program base */ 3026 #define R_TILEPRO_BROFF_X1 14 /* X1 pipe branch offset */ 3027 #define R_TILEPRO_JOFFLONG_X1 15 /* X1 pipe jump offset */ 3028 #define R_TILEPRO_JOFFLONG_X1_PLT 16 /* X1 pipe jump offset to PLT */ 3029 #define R_TILEPRO_IMM8_X0 17 /* X0 pipe 8-bit */ 3030 #define R_TILEPRO_IMM8_Y0 18 /* Y0 pipe 8-bit */ 3031 #define R_TILEPRO_IMM8_X1 19 /* X1 pipe 8-bit */ 3032 #define R_TILEPRO_IMM8_Y1 20 /* Y1 pipe 8-bit */ 3033 #define R_TILEPRO_MT_IMM15_X1 21 /* X1 pipe mtspr */ 3034 #define R_TILEPRO_MF_IMM15_X1 22 /* X1 pipe mfspr */ 3035 #define R_TILEPRO_IMM16_X0 23 /* X0 pipe 16-bit */ 3036 #define R_TILEPRO_IMM16_X1 24 /* X1 pipe 16-bit */ 3037 #define R_TILEPRO_IMM16_X0_LO 25 /* X0 pipe low 16-bit */ 3038 #define R_TILEPRO_IMM16_X1_LO 26 /* X1 pipe low 16-bit */ 3039 #define R_TILEPRO_IMM16_X0_HI 27 /* X0 pipe high 16-bit */ 3040 #define R_TILEPRO_IMM16_X1_HI 28 /* X1 pipe high 16-bit */ 3041 #define R_TILEPRO_IMM16_X0_HA 29 /* X0 pipe high 16-bit, adjusted */ 3042 #define R_TILEPRO_IMM16_X1_HA 30 /* X1 pipe high 16-bit, adjusted */ 3043 #define R_TILEPRO_IMM16_X0_PCREL 31 /* X0 pipe PC relative 16 bit */ 3044 #define R_TILEPRO_IMM16_X1_PCREL 32 /* X1 pipe PC relative 16 bit */ 3045 #define R_TILEPRO_IMM16_X0_LO_PCREL 33 /* X0 pipe PC relative low 16 bit */ 3046 #define R_TILEPRO_IMM16_X1_LO_PCREL 34 /* X1 pipe PC relative low 16 bit */ 3047 #define R_TILEPRO_IMM16_X0_HI_PCREL 35 /* X0 pipe PC relative high 16 bit */ 3048 #define R_TILEPRO_IMM16_X1_HI_PCREL 36 /* X1 pipe PC relative high 16 bit */ 3049 #define R_TILEPRO_IMM16_X0_HA_PCREL 37 /* X0 pipe PC relative ha() 16 bit */ 3050 #define R_TILEPRO_IMM16_X1_HA_PCREL 38 /* X1 pipe PC relative ha() 16 bit */ 3051 #define R_TILEPRO_IMM16_X0_GOT 39 /* X0 pipe 16-bit GOT offset */ 3052 #define R_TILEPRO_IMM16_X1_GOT 40 /* X1 pipe 16-bit GOT offset */ 3053 #define R_TILEPRO_IMM16_X0_GOT_LO 41 /* X0 pipe low 16-bit GOT offset */ 3054 #define R_TILEPRO_IMM16_X1_GOT_LO 42 /* X1 pipe low 16-bit GOT offset */ 3055 #define R_TILEPRO_IMM16_X0_GOT_HI 43 /* X0 pipe high 16-bit GOT offset */ 3056 #define R_TILEPRO_IMM16_X1_GOT_HI 44 /* X1 pipe high 16-bit GOT offset */ 3057 #define R_TILEPRO_IMM16_X0_GOT_HA 45 /* X0 pipe ha() 16-bit GOT offset */ 3058 #define R_TILEPRO_IMM16_X1_GOT_HA 46 /* X1 pipe ha() 16-bit GOT offset */ 3059 #define R_TILEPRO_MMSTART_X0 47 /* X0 pipe mm "start" */ 3060 #define R_TILEPRO_MMEND_X0 48 /* X0 pipe mm "end" */ 3061 #define R_TILEPRO_MMSTART_X1 49 /* X1 pipe mm "start" */ 3062 #define R_TILEPRO_MMEND_X1 50 /* X1 pipe mm "end" */ 3063 #define R_TILEPRO_SHAMT_X0 51 /* X0 pipe shift amount */ 3064 #define R_TILEPRO_SHAMT_X1 52 /* X1 pipe shift amount */ 3065 #define R_TILEPRO_SHAMT_Y0 53 /* Y0 pipe shift amount */ 3066 #define R_TILEPRO_SHAMT_Y1 54 /* Y1 pipe shift amount */ 3067 #define R_TILEPRO_DEST_IMM8_X1 55 /* X1 pipe destination 8-bit */ 3068 /* Relocs 56-59 are currently not defined. */ 3069 #define R_TILEPRO_TLS_GD_CALL 60 /* "jal" for TLS GD */ 3070 #define R_TILEPRO_IMM8_X0_TLS_GD_ADD 61 /* X0 pipe "addi" for TLS GD */ 3071 #define R_TILEPRO_IMM8_X1_TLS_GD_ADD 62 /* X1 pipe "addi" for TLS GD */ 3072 #define R_TILEPRO_IMM8_Y0_TLS_GD_ADD 63 /* Y0 pipe "addi" for TLS GD */ 3073 #define R_TILEPRO_IMM8_Y1_TLS_GD_ADD 64 /* Y1 pipe "addi" for TLS GD */ 3074 #define R_TILEPRO_TLS_IE_LOAD 65 /* "lw_tls" for TLS IE */ 3075 #define R_TILEPRO_IMM16_X0_TLS_GD 66 /* X0 pipe 16-bit TLS GD offset */ 3076 #define R_TILEPRO_IMM16_X1_TLS_GD 67 /* X1 pipe 16-bit TLS GD offset */ 3077 #define R_TILEPRO_IMM16_X0_TLS_GD_LO 68 /* X0 pipe low 16-bit TLS GD offset */ 3078 #define R_TILEPRO_IMM16_X1_TLS_GD_LO 69 /* X1 pipe low 16-bit TLS GD offset */ 3079 #define R_TILEPRO_IMM16_X0_TLS_GD_HI 70 /* X0 pipe high 16-bit TLS GD offset */ 3080 #define R_TILEPRO_IMM16_X1_TLS_GD_HI 71 /* X1 pipe high 16-bit TLS GD offset */ 3081 #define R_TILEPRO_IMM16_X0_TLS_GD_HA 72 /* X0 pipe ha() 16-bit TLS GD offset */ 3082 #define R_TILEPRO_IMM16_X1_TLS_GD_HA 73 /* X1 pipe ha() 16-bit TLS GD offset */ 3083 #define R_TILEPRO_IMM16_X0_TLS_IE 74 /* X0 pipe 16-bit TLS IE offset */ 3084 #define R_TILEPRO_IMM16_X1_TLS_IE 75 /* X1 pipe 16-bit TLS IE offset */ 3085 #define R_TILEPRO_IMM16_X0_TLS_IE_LO 76 /* X0 pipe low 16-bit TLS IE offset */ 3086 #define R_TILEPRO_IMM16_X1_TLS_IE_LO 77 /* X1 pipe low 16-bit TLS IE offset */ 3087 #define R_TILEPRO_IMM16_X0_TLS_IE_HI 78 /* X0 pipe high 16-bit TLS IE offset */ 3088 #define R_TILEPRO_IMM16_X1_TLS_IE_HI 79 /* X1 pipe high 16-bit TLS IE offset */ 3089 #define R_TILEPRO_IMM16_X0_TLS_IE_HA 80 /* X0 pipe ha() 16-bit TLS IE offset */ 3090 #define R_TILEPRO_IMM16_X1_TLS_IE_HA 81 /* X1 pipe ha() 16-bit TLS IE offset */ 3091 #define R_TILEPRO_TLS_DTPMOD32 82 /* ID of module containing symbol */ 3092 #define R_TILEPRO_TLS_DTPOFF32 83 /* Offset in TLS block */ 3093 #define R_TILEPRO_TLS_TPOFF32 84 /* Offset in static TLS block */ 3094 #define R_TILEPRO_IMM16_X0_TLS_LE 85 /* X0 pipe 16-bit TLS LE offset */ 3095 #define R_TILEPRO_IMM16_X1_TLS_LE 86 /* X1 pipe 16-bit TLS LE offset */ 3096 #define R_TILEPRO_IMM16_X0_TLS_LE_LO 87 /* X0 pipe low 16-bit TLS LE offset */ 3097 #define R_TILEPRO_IMM16_X1_TLS_LE_LO 88 /* X1 pipe low 16-bit TLS LE offset */ 3098 #define R_TILEPRO_IMM16_X0_TLS_LE_HI 89 /* X0 pipe high 16-bit TLS LE offset */ 3099 #define R_TILEPRO_IMM16_X1_TLS_LE_HI 90 /* X1 pipe high 16-bit TLS LE offset */ 3100 #define R_TILEPRO_IMM16_X0_TLS_LE_HA 91 /* X0 pipe ha() 16-bit TLS LE offset */ 3101 #define R_TILEPRO_IMM16_X1_TLS_LE_HA 92 /* X1 pipe ha() 16-bit TLS LE offset */ 3102 3103 #define R_TILEPRO_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ 3104 #define R_TILEPRO_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ 3105 3106 #define R_TILEPRO_NUM 130 3107 3108 3109 /* TILE-Gx relocations. */ 3110 #define R_TILEGX_NONE 0 /* No reloc */ 3111 #define R_TILEGX_64 1 /* Direct 64 bit */ 3112 #define R_TILEGX_32 2 /* Direct 32 bit */ 3113 #define R_TILEGX_16 3 /* Direct 16 bit */ 3114 #define R_TILEGX_8 4 /* Direct 8 bit */ 3115 #define R_TILEGX_64_PCREL 5 /* PC relative 64 bit */ 3116 #define R_TILEGX_32_PCREL 6 /* PC relative 32 bit */ 3117 #define R_TILEGX_16_PCREL 7 /* PC relative 16 bit */ 3118 #define R_TILEGX_8_PCREL 8 /* PC relative 8 bit */ 3119 #define R_TILEGX_HW0 9 /* hword 0 16-bit */ 3120 #define R_TILEGX_HW1 10 /* hword 1 16-bit */ 3121 #define R_TILEGX_HW2 11 /* hword 2 16-bit */ 3122 #define R_TILEGX_HW3 12 /* hword 3 16-bit */ 3123 #define R_TILEGX_HW0_LAST 13 /* last hword 0 16-bit */ 3124 #define R_TILEGX_HW1_LAST 14 /* last hword 1 16-bit */ 3125 #define R_TILEGX_HW2_LAST 15 /* last hword 2 16-bit */ 3126 #define R_TILEGX_COPY 16 /* Copy relocation */ 3127 #define R_TILEGX_GLOB_DAT 17 /* Create GOT entry */ 3128 #define R_TILEGX_JMP_SLOT 18 /* Create PLT entry */ 3129 #define R_TILEGX_RELATIVE 19 /* Adjust by program base */ 3130 #define R_TILEGX_BROFF_X1 20 /* X1 pipe branch offset */ 3131 #define R_TILEGX_JUMPOFF_X1 21 /* X1 pipe jump offset */ 3132 #define R_TILEGX_JUMPOFF_X1_PLT 22 /* X1 pipe jump offset to PLT */ 3133 #define R_TILEGX_IMM8_X0 23 /* X0 pipe 8-bit */ 3134 #define R_TILEGX_IMM8_Y0 24 /* Y0 pipe 8-bit */ 3135 #define R_TILEGX_IMM8_X1 25 /* X1 pipe 8-bit */ 3136 #define R_TILEGX_IMM8_Y1 26 /* Y1 pipe 8-bit */ 3137 #define R_TILEGX_DEST_IMM8_X1 27 /* X1 pipe destination 8-bit */ 3138 #define R_TILEGX_MT_IMM14_X1 28 /* X1 pipe mtspr */ 3139 #define R_TILEGX_MF_IMM14_X1 29 /* X1 pipe mfspr */ 3140 #define R_TILEGX_MMSTART_X0 30 /* X0 pipe mm "start" */ 3141 #define R_TILEGX_MMEND_X0 31 /* X0 pipe mm "end" */ 3142 #define R_TILEGX_SHAMT_X0 32 /* X0 pipe shift amount */ 3143 #define R_TILEGX_SHAMT_X1 33 /* X1 pipe shift amount */ 3144 #define R_TILEGX_SHAMT_Y0 34 /* Y0 pipe shift amount */ 3145 #define R_TILEGX_SHAMT_Y1 35 /* Y1 pipe shift amount */ 3146 #define R_TILEGX_IMM16_X0_HW0 36 /* X0 pipe hword 0 */ 3147 #define R_TILEGX_IMM16_X1_HW0 37 /* X1 pipe hword 0 */ 3148 #define R_TILEGX_IMM16_X0_HW1 38 /* X0 pipe hword 1 */ 3149 #define R_TILEGX_IMM16_X1_HW1 39 /* X1 pipe hword 1 */ 3150 #define R_TILEGX_IMM16_X0_HW2 40 /* X0 pipe hword 2 */ 3151 #define R_TILEGX_IMM16_X1_HW2 41 /* X1 pipe hword 2 */ 3152 #define R_TILEGX_IMM16_X0_HW3 42 /* X0 pipe hword 3 */ 3153 #define R_TILEGX_IMM16_X1_HW3 43 /* X1 pipe hword 3 */ 3154 #define R_TILEGX_IMM16_X0_HW0_LAST 44 /* X0 pipe last hword 0 */ 3155 #define R_TILEGX_IMM16_X1_HW0_LAST 45 /* X1 pipe last hword 0 */ 3156 #define R_TILEGX_IMM16_X0_HW1_LAST 46 /* X0 pipe last hword 1 */ 3157 #define R_TILEGX_IMM16_X1_HW1_LAST 47 /* X1 pipe last hword 1 */ 3158 #define R_TILEGX_IMM16_X0_HW2_LAST 48 /* X0 pipe last hword 2 */ 3159 #define R_TILEGX_IMM16_X1_HW2_LAST 49 /* X1 pipe last hword 2 */ 3160 #define R_TILEGX_IMM16_X0_HW0_PCREL 50 /* X0 pipe PC relative hword 0 */ 3161 #define R_TILEGX_IMM16_X1_HW0_PCREL 51 /* X1 pipe PC relative hword 0 */ 3162 #define R_TILEGX_IMM16_X0_HW1_PCREL 52 /* X0 pipe PC relative hword 1 */ 3163 #define R_TILEGX_IMM16_X1_HW1_PCREL 53 /* X1 pipe PC relative hword 1 */ 3164 #define R_TILEGX_IMM16_X0_HW2_PCREL 54 /* X0 pipe PC relative hword 2 */ 3165 #define R_TILEGX_IMM16_X1_HW2_PCREL 55 /* X1 pipe PC relative hword 2 */ 3166 #define R_TILEGX_IMM16_X0_HW3_PCREL 56 /* X0 pipe PC relative hword 3 */ 3167 #define R_TILEGX_IMM16_X1_HW3_PCREL 57 /* X1 pipe PC relative hword 3 */ 3168 #define R_TILEGX_IMM16_X0_HW0_LAST_PCREL 58 /* X0 pipe PC-rel last hword 0 */ 3169 #define R_TILEGX_IMM16_X1_HW0_LAST_PCREL 59 /* X1 pipe PC-rel last hword 0 */ 3170 #define R_TILEGX_IMM16_X0_HW1_LAST_PCREL 60 /* X0 pipe PC-rel last hword 1 */ 3171 #define R_TILEGX_IMM16_X1_HW1_LAST_PCREL 61 /* X1 pipe PC-rel last hword 1 */ 3172 #define R_TILEGX_IMM16_X0_HW2_LAST_PCREL 62 /* X0 pipe PC-rel last hword 2 */ 3173 #define R_TILEGX_IMM16_X1_HW2_LAST_PCREL 63 /* X1 pipe PC-rel last hword 2 */ 3174 #define R_TILEGX_IMM16_X0_HW0_GOT 64 /* X0 pipe hword 0 GOT offset */ 3175 #define R_TILEGX_IMM16_X1_HW0_GOT 65 /* X1 pipe hword 0 GOT offset */ 3176 #define R_TILEGX_IMM16_X0_HW0_PLT_PCREL 66 /* X0 pipe PC-rel PLT hword 0 */ 3177 #define R_TILEGX_IMM16_X1_HW0_PLT_PCREL 67 /* X1 pipe PC-rel PLT hword 0 */ 3178 #define R_TILEGX_IMM16_X0_HW1_PLT_PCREL 68 /* X0 pipe PC-rel PLT hword 1 */ 3179 #define R_TILEGX_IMM16_X1_HW1_PLT_PCREL 69 /* X1 pipe PC-rel PLT hword 1 */ 3180 #define R_TILEGX_IMM16_X0_HW2_PLT_PCREL 70 /* X0 pipe PC-rel PLT hword 2 */ 3181 #define R_TILEGX_IMM16_X1_HW2_PLT_PCREL 71 /* X1 pipe PC-rel PLT hword 2 */ 3182 #define R_TILEGX_IMM16_X0_HW0_LAST_GOT 72 /* X0 pipe last hword 0 GOT offset */ 3183 #define R_TILEGX_IMM16_X1_HW0_LAST_GOT 73 /* X1 pipe last hword 0 GOT offset */ 3184 #define R_TILEGX_IMM16_X0_HW1_LAST_GOT 74 /* X0 pipe last hword 1 GOT offset */ 3185 #define R_TILEGX_IMM16_X1_HW1_LAST_GOT 75 /* X1 pipe last hword 1 GOT offset */ 3186 #define R_TILEGX_IMM16_X0_HW3_PLT_PCREL 76 /* X0 pipe PC-rel PLT hword 3 */ 3187 #define R_TILEGX_IMM16_X1_HW3_PLT_PCREL 77 /* X1 pipe PC-rel PLT hword 3 */ 3188 #define R_TILEGX_IMM16_X0_HW0_TLS_GD 78 /* X0 pipe hword 0 TLS GD offset */ 3189 #define R_TILEGX_IMM16_X1_HW0_TLS_GD 79 /* X1 pipe hword 0 TLS GD offset */ 3190 #define R_TILEGX_IMM16_X0_HW0_TLS_LE 80 /* X0 pipe hword 0 TLS LE offset */ 3191 #define R_TILEGX_IMM16_X1_HW0_TLS_LE 81 /* X1 pipe hword 0 TLS LE offset */ 3192 #define R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE 82 /* X0 pipe last hword 0 LE off */ 3193 #define R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE 83 /* X1 pipe last hword 0 LE off */ 3194 #define R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE 84 /* X0 pipe last hword 1 LE off */ 3195 #define R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE 85 /* X1 pipe last hword 1 LE off */ 3196 #define R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD 86 /* X0 pipe last hword 0 GD off */ 3197 #define R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD 87 /* X1 pipe last hword 0 GD off */ 3198 #define R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD 88 /* X0 pipe last hword 1 GD off */ 3199 #define R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD 89 /* X1 pipe last hword 1 GD off */ 3200 /* Relocs 90-91 are currently not defined. */ 3201 #define R_TILEGX_IMM16_X0_HW0_TLS_IE 92 /* X0 pipe hword 0 TLS IE offset */ 3202 #define R_TILEGX_IMM16_X1_HW0_TLS_IE 93 /* X1 pipe hword 0 TLS IE offset */ 3203 #define R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL 94 /* X0 pipe PC-rel PLT last hword 0 */ 3204 #define R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL 95 /* X1 pipe PC-rel PLT last hword 0 */ 3205 #define R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL 96 /* X0 pipe PC-rel PLT last hword 1 */ 3206 #define R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL 97 /* X1 pipe PC-rel PLT last hword 1 */ 3207 #define R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL 98 /* X0 pipe PC-rel PLT last hword 2 */ 3208 #define R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL 99 /* X1 pipe PC-rel PLT last hword 2 */ 3209 #define R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE 100 /* X0 pipe last hword 0 IE off */ 3210 #define R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE 101 /* X1 pipe last hword 0 IE off */ 3211 #define R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE 102 /* X0 pipe last hword 1 IE off */ 3212 #define R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE 103 /* X1 pipe last hword 1 IE off */ 3213 /* Relocs 104-105 are currently not defined. */ 3214 #define R_TILEGX_TLS_DTPMOD64 106 /* 64-bit ID of symbol's module */ 3215 #define R_TILEGX_TLS_DTPOFF64 107 /* 64-bit offset in TLS block */ 3216 #define R_TILEGX_TLS_TPOFF64 108 /* 64-bit offset in static TLS block */ 3217 #define R_TILEGX_TLS_DTPMOD32 109 /* 32-bit ID of symbol's module */ 3218 #define R_TILEGX_TLS_DTPOFF32 110 /* 32-bit offset in TLS block */ 3219 #define R_TILEGX_TLS_TPOFF32 111 /* 32-bit offset in static TLS block */ 3220 #define R_TILEGX_TLS_GD_CALL 112 /* "jal" for TLS GD */ 3221 #define R_TILEGX_IMM8_X0_TLS_GD_ADD 113 /* X0 pipe "addi" for TLS GD */ 3222 #define R_TILEGX_IMM8_X1_TLS_GD_ADD 114 /* X1 pipe "addi" for TLS GD */ 3223 #define R_TILEGX_IMM8_Y0_TLS_GD_ADD 115 /* Y0 pipe "addi" for TLS GD */ 3224 #define R_TILEGX_IMM8_Y1_TLS_GD_ADD 116 /* Y1 pipe "addi" for TLS GD */ 3225 #define R_TILEGX_TLS_IE_LOAD 117 /* "ld_tls" for TLS IE */ 3226 #define R_TILEGX_IMM8_X0_TLS_ADD 118 /* X0 pipe "addi" for TLS GD/IE */ 3227 #define R_TILEGX_IMM8_X1_TLS_ADD 119 /* X1 pipe "addi" for TLS GD/IE */ 3228 #define R_TILEGX_IMM8_Y0_TLS_ADD 120 /* Y0 pipe "addi" for TLS GD/IE */ 3229 #define R_TILEGX_IMM8_Y1_TLS_ADD 121 /* Y1 pipe "addi" for TLS GD/IE */ 3230 3231 #define R_TILEGX_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */ 3232 #define R_TILEGX_GNU_VTENTRY 129 /* GNU C++ vtable member usage */ 3233 3234 #define R_TILEGX_NUM 130 3235 3236 3237 #endif /* elf.h */ -
EcnlProtoTool/trunk/tcc-0.9.27/examples/ex3.c
r321 r331 1 #include <stdlib.h> 2 #include <stdio.h> 1 #include <tcclib.h> 3 2 4 3 int fib(n) -
EcnlProtoTool/trunk/tcc-0.9.27/i386-asm.c
r321 r331 22 22 #include "tcc.h" 23 23 24 // #define NB_ASM_REGS 825 24 #define MAX_OPERANDS 3 26 #define NB_SAVED_REGS 327 25 28 26 #define TOK_ASM_first TOK_ASM_clc 29 27 #define TOK_ASM_last TOK_ASM_emms 30 31 #define OPC_JMP 0x01 /* jmp operand */ 32 #define OPC_B 0x0 2/* only used with OPC_WL */33 #define OPC_WL 0x0 4/* accepts w, l or no suffix */28 #define TOK_ASM_alllast TOK_ASM_subps 29 30 #define OPC_B 0x01 /* only used with OPC_WL */ 31 #define OPC_WL 0x02 /* accepts w, l or no suffix */ 34 32 #define OPC_BWL (OPC_B | OPC_WL) /* accepts b, w, l or no suffix */ 35 #define OPC_REG 0x08 /* register is added to opcode */ 36 #define OPC_MODRM 0x10 /* modrm encoding */ 37 #define OPC_FWAIT 0x20 /* add fwait opcode */ 38 #define OPC_TEST 0x40 /* test opcodes */ 39 #define OPC_SHIFT 0x80 /* shift opcodes */ 40 #define OPC_D16 0x0100 /* generate data16 prefix */ 41 #define OPC_ARITH 0x0200 /* arithmetic opcodes */ 42 #define OPC_SHORTJMP 0x0400 /* short jmp operand */ 43 #define OPC_FARITH 0x0800 /* FPU arithmetic opcodes */ 33 #define OPC_REG 0x04 /* register is added to opcode */ 34 #define OPC_MODRM 0x08 /* modrm encoding */ 35 36 #define OPCT_MASK 0x70 37 #define OPC_FWAIT 0x10 /* add fwait opcode */ 38 #define OPC_SHIFT 0x20 /* shift opcodes */ 39 #define OPC_ARITH 0x30 /* arithmetic opcodes */ 40 #define OPC_FARITH 0x40 /* FPU arithmetic opcodes */ 41 #define OPC_TEST 0x50 /* test opcodes */ 42 #define OPCT_IS(v,i) (((v) & OPCT_MASK) == (i)) 43 44 #define OPC_0F 0x100 /* Is secondary map (0x0f prefix) */ 45 #define OPC_48 0x200 /* Always has REX prefix */ 44 46 #ifdef TCC_TARGET_X86_64 45 47 # define OPC_WLQ 0x1000 /* accepts w, l, q or no suffix */ 46 48 # define OPC_BWLQ (OPC_B | OPC_WLQ) /* accepts b, w, l, q or no suffix */ 47 49 # define OPC_WLX OPC_WLQ 50 # define OPC_BWLX OPC_BWLQ 48 51 #else 49 52 # define OPC_WLX OPC_WL 53 # define OPC_BWLX OPC_BWL 50 54 #endif 51 55 … … 68 72 OPT_SEG, 69 73 OPT_ST, 74 #ifdef TCC_TARGET_X86_64 75 OPT_REG8_LOW, /* %spl,%bpl,%sil,%dil, encoded like ah,ch,dh,bh, but 76 with REX prefix, not used in insn templates */ 77 #endif 70 78 OPT_IM8, 71 79 OPT_IM8S, … … 83 91 /* composite types */ 84 92 OPT_COMPOSITE_FIRST, 85 OPT_IM, /* IM8 | IM16 | IM32 | IM64*/93 OPT_IM, /* IM8 | IM16 | IM32 */ 86 94 OPT_REG, /* REG8 | REG16 | REG32 | REG64 */ 87 95 OPT_REGW, /* REG16 | REG32 | REG64 */ 88 OPT_IMW, /* IM16 | IM32 | IM64*/89 #ifdef TCC_TARGET_X86_64 90 OPT_ IMNO64, /* IM16 | IM32*/91 #endif 96 OPT_IMW, /* IM16 | IM32 */ 97 OPT_MMXSSE, /* MMX | SSE */ 98 OPT_DISP, /* Like OPT_ADDR, but emitted as displacement (for jumps) */ 99 OPT_DISP8, /* Like OPT_ADDR, but only 8bit (short jumps) */ 92 100 /* can be ored with any OPT_xxx */ 93 101 OPT_EA = 0x80 … … 115 123 #define OP_INDIR (1 << OPT_INDIR) 116 124 #ifdef TCC_TARGET_X86_64 117 # define OP_REG64 (1 << OPT_REG64) 118 # define OP_IM64 (1 << OPT_IM64) 125 # define OP_REG64 (1 << OPT_REG64) 126 # define OP_REG8_LOW (1 << OPT_REG8_LOW) 127 # define OP_IM64 (1 << OPT_IM64) 128 # define OP_EA32 (OP_EA << 1) 119 129 #else 120 130 # define OP_REG64 0 131 # define OP_REG8_LOW 0 121 132 # define OP_IM64 0 133 # define OP_EA32 0 122 134 #endif 123 135 … … 126 138 127 139 #ifdef TCC_TARGET_X86_64 128 # define OP_IM OP_IM64129 140 # define TREG_XAX TREG_RAX 130 141 # define TREG_XCX TREG_RCX 131 142 # define TREG_XDX TREG_RDX 132 143 #else 133 # define OP_IM OP_IM32134 144 # define TREG_XAX TREG_EAX 135 145 # define TREG_XCX TREG_ECX … … 211 221 static const ASMInstr asm_instrs[] = { 212 222 #define ALT(x) x 223 /* This removes a 0x0f in the second byte */ 224 #define O(o) ((uint64_t) ((((o) & 0xff00) == 0x0f00) ? ((((o) >> 8) & ~0xff) | ((o) & 0xff)) : (o))) 225 /* This constructs instr_type from opcode, type and group. */ 226 #define T(o,i,g) ((i) | ((g) << OPC_GROUP_SHIFT) | ((((o) & 0xff00) == 0x0f00) ? OPC_0F : 0)) 213 227 #define DEF_ASM_OP0(name, opcode) 214 #define DEF_ASM_OP0L(name, opcode, group, instr_type) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 0},215 #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 1, { op0 }},216 #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 2, { op0, op1 }},217 #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 3, { op0, op1, op2 }},228 #define DEF_ASM_OP0L(name, opcode, group, instr_type) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 0, { 0 } }, 229 #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 1, { op0 }}, 230 #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 2, { op0, op1 }}, 231 #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 3, { op0, op1, op2 }}, 218 232 #ifdef TCC_TARGET_X86_64 219 233 # include "x86_64-asm.h" … … 242 256 { 243 257 int shift, v; 244 #ifdef I386_ASM_16245 if (s1->seg_size == 16)246 tcc_error("invalid effective address");247 #endif248 258 v = asm_int_expr(s1); 249 259 switch(v) { … … 268 278 } 269 279 270 static int asm_parse_reg(void) 280 #ifdef TCC_TARGET_X86_64 281 static int asm_parse_numeric_reg(int t, unsigned int *type) 282 { 283 int reg = -1; 284 if (t >= TOK_IDENT && t < tok_ident) { 285 const char *s = table_ident[t - TOK_IDENT]->str; 286 char c; 287 *type = OP_REG64; 288 if (*s == 'c') { 289 s++; 290 *type = OP_CR; 291 } 292 if (*s++ != 'r') 293 return -1; 294 /* Don't allow leading '0'. */ 295 if ((c = *s++) >= '1' && c <= '9') 296 reg = c - '0'; 297 else 298 return -1; 299 if ((c = *s) >= '0' && c <= '5') 300 s++, reg = reg * 10 + c - '0'; 301 if (reg > 15) 302 return -1; 303 if ((c = *s) == 0) 304 ; 305 else if (*type != OP_REG64) 306 return -1; 307 else if (c == 'b' && !s[1]) 308 *type = OP_REG8; 309 else if (c == 'w' && !s[1]) 310 *type = OP_REG16; 311 else if (c == 'd' && !s[1]) 312 *type = OP_REG32; 313 else 314 return -1; 315 } 316 return reg; 317 } 318 #endif 319 320 static int asm_parse_reg(unsigned int *type) 271 321 { 272 322 int reg = 0; 323 *type = 0; 273 324 if (tok != '%') 274 325 goto error_32; … … 276 327 if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) { 277 328 reg = tok - TOK_ASM_eax; 329 *type = OP_REG32; 278 330 #ifdef TCC_TARGET_X86_64 279 331 } else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) { 280 332 reg = tok - TOK_ASM_rax; 281 #endif 282 #ifdef I386_ASM_16 283 } else if (tok >= TOK_ASM_ax && tok <= TOK_ASM_di) { 284 reg = tok - TOK_ASM_ax; 333 *type = OP_REG64; 334 } else if (tok == TOK_ASM_rip) { 335 reg = -2; /* Probably should use different escape code. */ 336 *type = OP_REG64; 337 } else if ((reg = asm_parse_numeric_reg(tok, type)) >= 0 338 && (*type == OP_REG32 || *type == OP_REG64)) { 339 ; 285 340 #endif 286 341 } else { … … 330 385 if (tok != TOK_PPNUM) 331 386 goto reg_error; 332 p = tokc. cstr->data;387 p = tokc.str.data; 333 388 reg = p[0] - '0'; 334 389 if ((unsigned)reg >= 8 || p[1] != '\0') … … 341 396 op->type |= OP_ST0; 342 397 goto no_skip; 398 #ifdef TCC_TARGET_X86_64 399 } else if (tok >= TOK_ASM_spl && tok <= TOK_ASM_dil) { 400 op->type = OP_REG8 | OP_REG8_LOW; 401 op->reg = 4 + tok - TOK_ASM_spl; 402 } else if ((op->reg = asm_parse_numeric_reg(tok, &op->type)) >= 0) { 403 ; 404 #endif 343 405 } else { 344 406 reg_error: 345 tcc_error("unknown register ");407 tcc_error("unknown register %%%s", get_tok_str(tok, &tokc)); 346 408 } 347 409 next(); … … 351 413 next(); 352 414 asm_expr(s1, &e); 353 op->type = OP_IM; 354 op->e.v = e.v; 355 op->e.sym = e.sym; 415 op->type = OP_IM32; 416 op->e = e; 356 417 if (!op->e.sym) { 357 418 if (op->e.v == (uint8_t)op->e.v) … … 362 423 op->type |= OP_IM16; 363 424 #ifdef TCC_TARGET_X86_64 364 if (op->e.v == (uint32_t)op->e.v)365 op->type |= OP_IM32;425 if (op->e.v != (int32_t)op->e.v && op->e.v != (uint32_t)op->e.v) 426 op->type = OP_IM64; 366 427 #endif 367 428 } … … 374 435 if (tok != '(') { 375 436 asm_expr(s1, &e); 376 op->e.v = e.v; 377 op->e.sym = e.sym; 437 op->e = e; 378 438 } else { 379 439 next(); … … 391 451 op->e.sym = e.sym; 392 452 } 453 op->e.pcrel = 0; 393 454 } 394 455 if (tok == '(') { 456 unsigned int type = 0; 395 457 next(); 396 458 if (tok != ',') { 397 op->reg = asm_parse_reg( );459 op->reg = asm_parse_reg(&type); 398 460 } 399 461 if (tok == ',') { 400 462 next(); 401 463 if (tok != ',') { 402 op->reg2 = asm_parse_reg( );464 op->reg2 = asm_parse_reg(&type); 403 465 } 404 466 if (tok == ',') { … … 407 469 } 408 470 } 471 if (type & OP_REG32) 472 op->type |= OP_EA32; 409 473 skip(')'); 410 474 } … … 418 482 ST_FUNC void gen_expr32(ExprValue *pe) 419 483 { 420 gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v); 484 if (pe->pcrel) 485 /* If PC-relative, always set VT_SYM, even without symbol, 486 so as to force a relocation to be emitted. */ 487 gen_addrpc32(VT_SYM, pe->sym, pe->v); 488 else 489 gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v); 421 490 } 422 491 423 492 #ifdef TCC_TARGET_X86_64 424 staticvoid gen_expr64(ExprValue *pe)493 ST_FUNC void gen_expr64(ExprValue *pe) 425 494 { 426 495 gen_addr64(pe->sym ? VT_SYM : 0, pe->sym, pe->v); … … 432 501 { 433 502 Sym *sym = pe->sym; 434 if (sym && sym->r == cur_text_section->sh_num) { 503 ElfSym *esym = elfsym(sym); 504 if (esym && esym->st_shndx == cur_text_section->sh_num) { 435 505 /* same section: we can output an absolute value. Note 436 506 that the TCC compiler behaves differently here because 437 507 it always outputs a relocation to ease (future) code 438 508 elimination in the linker */ 439 gen_le32(pe->v + sym->jnext- ind - 4);509 gen_le32(pe->v + esym->st_value - ind - 4); 440 510 } else { 441 511 if (sym && sym->type.t == VT_VOID) { … … 447 517 } 448 518 449 #ifdef I386_ASM_16450 static void gen_expr16(ExprValue *pe)451 {452 if (pe->sym)453 greloc(cur_text_section, pe->sym, ind, R_386_16);454 gen_le16(pe->v);455 }456 static void gen_disp16(ExprValue *pe)457 {458 Sym *sym;459 sym = pe->sym;460 if (sym) {461 if (sym->r == cur_text_section->sh_num) {462 /* same section: we can output an absolute value. Note463 that the TCC compiler behaves differently here because464 it always outputs a relocation to ease (future) code465 elimination in the linker */466 gen_le16(pe->v + sym->jnext - ind - 2);467 } else {468 greloc(cur_text_section, sym, ind, R_386_PC16);469 gen_le16(pe->v - 2);470 }471 } else {472 /* put an empty PC32 relocation */473 put_elf_reloc(symtab_section, cur_text_section,474 ind, R_386_PC16, 0);475 gen_le16(pe->v - 2);476 }477 }478 #endif479 480 519 /* generate the modrm operand */ 481 static inline voidasm_modrm(int reg, Operand *op)520 static inline int asm_modrm(int reg, Operand *op) 482 521 { 483 522 int mod, reg1, reg2, sib_reg1; … … 487 526 } else if (op->reg == -1 && op->reg2 == -1) { 488 527 /* displacement only */ 489 #ifdef I386_ASM_16 490 if (tcc_state->seg_size == 16) { 491 g(0x06 + (reg << 3)); 492 gen_expr16(&op->e); 493 } else if (tcc_state->seg_size == 32) 494 #endif 495 { 496 g(0x05 + (reg << 3)); 497 gen_expr32(&op->e); 498 } 528 #ifdef TCC_TARGET_X86_64 529 g(0x04 + (reg << 3)); 530 g(0x25); 531 #else 532 g(0x05 + (reg << 3)); 533 #endif 534 gen_expr32(&op->e); 535 #ifdef TCC_TARGET_X86_64 536 } else if (op->reg == -2) { 537 ExprValue *pe = &op->e; 538 g(0x05 + (reg << 3)); 539 gen_addrpc32(pe->sym ? VT_SYM : 0, pe->sym, pe->v); 540 return ind; 541 #endif 499 542 } else { 500 543 sib_reg1 = op->reg; … … 514 557 if (op->reg2 != -1) 515 558 reg1 = 4; 516 #ifdef I386_ASM_16517 if (tcc_state->seg_size == 32) {518 #endif519 559 g(mod + (reg << 3) + reg1); 520 560 if (reg1 == 4) { … … 525 565 g((op->shift << 6) + (reg2 << 3) + sib_reg1); 526 566 } 527 #ifdef I386_ASM_16528 } else if (tcc_state->seg_size == 16) {529 /* edi = 7, esi = 6 --> di = 5, si = 4 */530 if ((reg1 == 6) || (reg1 == 7)) {531 reg1 -= 2;532 /* ebx = 3 --> bx = 7 */533 } else if (reg1 == 3) {534 reg1 = 7;535 /* o32 = 5 --> o16 = 6 */536 } else if (reg1 == 5) {537 reg1 = 6;538 /* sib not valid in 16-bit mode */539 } else if (reg1 == 4) {540 reg2 = op->reg2;541 /* bp + si + offset */542 if ((sib_reg1 == 5) && (reg2 == 6)) {543 reg1 = 2;544 /* bp + di + offset */545 } else if ((sib_reg1 == 5) && (reg2 == 7)) {546 reg1 = 3;547 /* bx + si + offset */548 } else if ((sib_reg1 == 3) && (reg2 == 6)) {549 reg1 = 0;550 /* bx + di + offset */551 } else if ((sib_reg1 == 3) && (reg2 == 7)) {552 reg1 = 1;553 } else {554 tcc_error("invalid effective address");555 }556 if (op->e.v == 0)557 mod = 0;558 } else {559 tcc_error("invalid register");560 }561 g(mod + (reg << 3) + reg1);562 }563 #endif564 567 /* add offset */ 565 568 if (mod == 0x40) { 566 569 g(op->e.v); 567 570 } else if (mod == 0x80 || op->reg == -1) { 568 #ifdef I386_ASM_16 569 if (tcc_state->seg_size == 16) 570 gen_expr16(&op->e); 571 else if (tcc_state->seg_size == 32) 572 #endif 573 gen_expr32(&op->e); 574 } 571 gen_expr32(&op->e); 572 } 573 } 574 return 0; 575 } 576 577 #ifdef TCC_TARGET_X86_64 578 #define REX_W 0x48 579 #define REX_R 0x44 580 #define REX_X 0x42 581 #define REX_B 0x41 582 583 static void asm_rex(int width64, Operand *ops, int nb_ops, int *op_type, 584 int regi, int rmi) 585 { 586 unsigned char rex = width64 ? 0x48 : 0; 587 int saw_high_8bit = 0; 588 int i; 589 if (rmi == -1) { 590 /* No mod/rm byte, but we might have a register op nevertheless 591 (we will add it to the opcode later). */ 592 for(i = 0; i < nb_ops; i++) { 593 if (op_type[i] & (OP_REG | OP_ST)) { 594 if (ops[i].reg >= 8) { 595 rex |= REX_B; 596 ops[i].reg -= 8; 597 } else if (ops[i].type & OP_REG8_LOW) 598 rex |= 0x40; 599 else if (ops[i].type & OP_REG8 && ops[i].reg >= 4) 600 /* An 8 bit reg >= 4 without REG8 is ah/ch/dh/bh */ 601 saw_high_8bit = ops[i].reg; 602 break; 603 } 604 } 605 } else { 606 if (regi != -1) { 607 if (ops[regi].reg >= 8) { 608 rex |= REX_R; 609 ops[regi].reg -= 8; 610 } else if (ops[regi].type & OP_REG8_LOW) 611 rex |= 0x40; 612 else if (ops[regi].type & OP_REG8 && ops[regi].reg >= 4) 613 /* An 8 bit reg >= 4 without REG8 is ah/ch/dh/bh */ 614 saw_high_8bit = ops[regi].reg; 615 } 616 if (ops[rmi].type & (OP_REG | OP_MMX | OP_SSE | OP_CR | OP_EA)) { 617 if (ops[rmi].reg >= 8) { 618 rex |= REX_B; 619 ops[rmi].reg -= 8; 620 } else if (ops[rmi].type & OP_REG8_LOW) 621 rex |= 0x40; 622 else if (ops[rmi].type & OP_REG8 && ops[rmi].reg >= 4) 623 /* An 8 bit reg >= 4 without REG8 is ah/ch/dh/bh */ 624 saw_high_8bit = ops[rmi].reg; 625 } 626 if (ops[rmi].type & OP_EA && ops[rmi].reg2 >= 8) { 627 rex |= REX_X; 628 ops[rmi].reg2 -= 8; 629 } 630 } 631 if (rex) { 632 if (saw_high_8bit) 633 tcc_error("can't encode register %%%ch when REX prefix is required", 634 "acdb"[saw_high_8bit-4]); 635 g(rex); 636 } 637 } 638 #endif 639 640 static void maybe_print_stats (void) 641 { 642 static int already = 1; 643 if (!already) 644 /* print stats about opcodes */ 645 { 646 const struct ASMInstr *pa; 647 int freq[4]; 648 int op_vals[500]; 649 int nb_op_vals, i, j; 650 651 already = 1; 652 nb_op_vals = 0; 653 memset(freq, 0, sizeof(freq)); 654 for(pa = asm_instrs; pa->sym != 0; pa++) { 655 freq[pa->nb_ops]++; 656 //for(i=0;i<pa->nb_ops;i++) { 657 for(j=0;j<nb_op_vals;j++) { 658 //if (pa->op_type[i] == op_vals[j]) 659 if (pa->instr_type == op_vals[j]) 660 goto found; 661 } 662 //op_vals[nb_op_vals++] = pa->op_type[i]; 663 op_vals[nb_op_vals++] = pa->instr_type; 664 found: ; 665 //} 666 } 667 for(i=0;i<nb_op_vals;i++) { 668 int v = op_vals[i]; 669 //if ((v & (v - 1)) != 0) 670 printf("%3d: %08x\n", i, v); 671 } 672 printf("size=%d nb=%d f0=%d f1=%d f2=%d f3=%d\n", 673 (int)sizeof(asm_instrs), 674 (int)sizeof(asm_instrs) / (int)sizeof(ASMInstr), 675 freq[0], freq[1], freq[2], freq[3]); 575 676 } 576 677 } … … 579 680 { 580 681 const ASMInstr *pa; 581 int i, modrm_index, reg, v, op1, is_short_jmp, seg_prefix;682 int i, modrm_index, modreg_index, reg, v, op1, seg_prefix, pc; 582 683 int nb_ops, s; 583 684 Operand ops[MAX_OPERANDS], *pop; 584 685 int op_type[3]; /* decoded op type */ 585 #ifdef I386_ASM_16 586 static int a32 = 0, o32 = 0, addr32 = 0, data32 = 0; 587 #endif 588 686 int alltypes; /* OR of all operand types */ 687 int autosize; 688 int p66; 689 #ifdef TCC_TARGET_X86_64 690 int rex64; 691 #endif 692 693 maybe_print_stats(); 589 694 /* force synthetic ';' after prefix instruction, so we can handle */ 590 695 /* one-line things like "rep stosb" instead of only "rep\nstosb" */ … … 596 701 nb_ops = 0; 597 702 seg_prefix = 0; 703 alltypes = 0; 598 704 for(;;) { 599 705 if (tok == ';' || tok == TOK_LINEFEED) … … 609 715 next(); 610 716 parse_operand(s1, pop); 611 #ifndef I386_ASM_16612 717 if (!(pop->type & OP_EA)) { 613 718 tcc_error("segment prefix must be followed by memory reference"); 614 719 } 615 #endif616 720 } 617 721 pop++; … … 622 726 } 623 727 624 is_short_jmp = 0;625 728 s = 0; /* avoid warning */ 626 729 730 again: 627 731 /* optimize matching by using a lookup table (no hashing is needed 628 732 !) */ 629 733 for(pa = asm_instrs; pa->sym != 0; pa++) { 734 int it = pa->instr_type & OPCT_MASK; 630 735 s = 0; 631 if ( pa->instr_type &OPC_FARITH) {736 if (it == OPC_FARITH) { 632 737 v = opcode - pa->sym; 633 738 if (!((unsigned)v < 8 * 6 && (v % 6) == 0)) 634 739 continue; 635 } else if ( pa->instr_type &OPC_ARITH) {740 } else if (it == OPC_ARITH) { 636 741 if (!(opcode >= pa->sym && opcode < pa->sym + 8*NBWLX)) 637 742 continue; 638 743 s = (opcode - pa->sym) % NBWLX; 639 } else if (pa->instr_type & OPC_SHIFT) { 744 if ((pa->instr_type & OPC_BWLX) == OPC_WLX) 745 { 746 /* We need to reject the xxxb opcodes that we accepted above. 747 Note that pa->sym for WLX opcodes is the 'w' token, 748 to get the 'b' token subtract one. */ 749 if (((opcode - pa->sym + 1) % NBWLX) == 0) 750 continue; 751 s++; 752 } 753 } else if (it == OPC_SHIFT) { 640 754 if (!(opcode >= pa->sym && opcode < pa->sym + 7*NBWLX)) 641 755 continue; 642 756 s = (opcode - pa->sym) % NBWLX; 643 } else if ( pa->instr_type &OPC_TEST) {757 } else if (it == OPC_TEST) { 644 758 if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES)) 645 759 continue; 760 /* cmovxx is a test opcode but accepts multiple sizes. 761 The suffixes aren't encoded in the table, instead we 762 simply force size autodetection always and deal with suffixed 763 variants below when we don't find e.g. "cmovzl". */ 764 if (pa->instr_type & OPC_WLX) 765 s = NBWLX - 1; 646 766 } else if (pa->instr_type & OPC_B) { 767 #ifdef TCC_TARGET_X86_64 768 /* Some instructions don't have the full size but only 769 bwl form. insb e.g. */ 770 if ((pa->instr_type & OPC_WLQ) != OPC_WLQ 771 && !(opcode >= pa->sym && opcode < pa->sym + NBWLX-1)) 772 continue; 773 #endif 647 774 if (!(opcode >= pa->sym && opcode < pa->sym + NBWLX)) 648 775 continue; … … 658 785 if (pa->nb_ops != nb_ops) 659 786 continue; 787 #ifdef TCC_TARGET_X86_64 788 /* Special case for moves. Selecting the IM64->REG64 form 789 should only be done if we really have an >32bit imm64, and that 790 is hardcoded. Ignore it here. */ 791 if (pa->opcode == 0xb0 && ops[0].type != OP_IM64 792 && (ops[1].type & OP_REG) == OP_REG64 793 && !(pa->instr_type & OPC_0F)) 794 continue; 795 #endif 660 796 /* now decode and check each operand */ 797 alltypes = 0; 661 798 for(i = 0; i < nb_ops; i++) { 662 799 int op1, op2; … … 665 802 switch(op2) { 666 803 case OPT_IM: 667 v = OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64;804 v = OP_IM8 | OP_IM16 | OP_IM32; 668 805 break; 669 806 case OPT_REG: … … 674 811 break; 675 812 case OPT_IMW: 676 v = OP_IM16 | OP_IM32 | OP_IM64;677 break;678 #ifdef TCC_TARGET_X86_64679 case OPT_IMNO64:680 813 v = OP_IM16 | OP_IM32; 681 814 break; 682 #endif 815 case OPT_MMXSSE: 816 v = OP_MMX | OP_SSE; 817 break; 818 case OPT_DISP: 819 case OPT_DISP8: 820 v = OP_ADDR; 821 break; 683 822 default: 684 823 v = 1 << op2; … … 687 826 if (op1 & OPT_EA) 688 827 v |= OP_EA; 689 828 op_type[i] = v; 690 829 if ((ops[i].type & v) == 0) 691 830 goto next; 831 alltypes |= ops[i].type; 692 832 } 693 833 /* all is matching ! */ … … 699 839 int b; 700 840 b = op0_codes[opcode - TOK_ASM_first]; 701 #ifdef I386_ASM_16702 if (opcode == TOK_ASM_o32) {703 if (s1->seg_size == 32)704 tcc_error("incorrect prefix");705 else706 o32 = data32 = 1;707 } else if (opcode == TOK_ASM_a32) {708 if (s1->seg_size == 32)709 tcc_error("incorrect prefix");710 else711 a32 = addr32 = 1;712 }713 #endif714 841 if (b & 0xff00) 715 842 g(b >> 8); 716 843 g(b); 717 844 return; 845 } else if (opcode <= TOK_ASM_alllast) { 846 tcc_error("bad operand with opcode '%s'", 847 get_tok_str(opcode, NULL)); 718 848 } else { 719 tcc_error("unknown opcode '%s'", 720 get_tok_str(opcode, NULL)); 849 /* Special case for cmovcc, we accept size suffixes but ignore 850 them, but we don't want them to blow up our tables. */ 851 TokenSym *ts = table_ident[opcode - TOK_IDENT]; 852 if (ts->len >= 6 853 && strchr("wlq", ts->str[ts->len-1]) 854 && !memcmp(ts->str, "cmov", 4)) { 855 opcode = tok_alloc(ts->str, ts->len-1)->tok; 856 goto again; 857 } 858 tcc_error("unknown opcode '%s'", ts->str); 721 859 } 722 860 } 723 861 /* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */ 724 if (s == NBWLX-1) { 725 for(i = 0; s == NBWLX-1 && i < nb_ops; i++) { 862 autosize = NBWLX-1; 863 #ifdef TCC_TARGET_X86_64 864 /* XXX the autosize should rather be zero, to not have to adjust this 865 all the time. */ 866 if ((pa->instr_type & OPC_BWLQ) == OPC_B) 867 autosize = NBWLX-2; 868 #endif 869 if (s == autosize) { 870 /* Check for register operands providing hints about the size. 871 Start from the end, i.e. destination operands. This matters 872 only for opcodes accepting different sized registers, lar and lsl 873 are such opcodes. */ 874 for(i = nb_ops - 1; s == autosize && i >= 0; i--) { 726 875 if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX))) 727 876 s = reg_to_size[ops[i].type & OP_REG]; 728 877 } 729 if (s == NBWLX-1) {878 if (s == autosize) { 730 879 if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) && 731 (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32 | OP_IM64)))880 (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32))) 732 881 s = 2; 882 else if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) && 883 (ops[0].type & OP_EA)) 884 s = NBWLX - 2; 733 885 else 734 886 tcc_error("cannot infer opcode suffix"); … … 736 888 } 737 889 738 #ifdef I386_ASM_16 890 #ifdef TCC_TARGET_X86_64 891 /* Generate addr32 prefix if needed */ 739 892 for(i = 0; i < nb_ops; i++) { 740 if (ops[i].type & OP_REG32) { 741 if (s1->seg_size == 16) 742 o32 = 1; 743 } else if (!(ops[i].type & OP_REG32)) { 744 if (s1->seg_size == 32) 745 o32 = 1; 746 } 747 } 748 749 750 if (s == 1 || (pa->instr_type & OPC_D16)) { 751 if (s1->seg_size == 32) 752 o32 = 1; 753 } else if (s == 2) { 754 if (s1->seg_size == 16) { 755 if (!(pa->instr_type & OPC_D16)) 756 o32 = 1; 757 } 758 } 759 760 /* generate a16/a32 prefix if needed */ 761 if ((a32 == 1) && (addr32 == 0)) 762 g(0x67); 763 /* generate o16/o32 prefix if needed */ 764 if ((o32 == 1) && (data32 == 0)) 893 if (ops[i].type & OP_EA32) { 894 g(0x67); 895 break; 896 } 897 } 898 #endif 899 /* generate data16 prefix if needed */ 900 p66 = 0; 901 if (s == 1) 902 p66 = 1; 903 else { 904 /* accepting mmx+sse in all operands --> needs 0x66 to 905 switch to sse mode. Accepting only sse in an operand --> is 906 already SSE insn and needs 0x66/f2/f3 handling. */ 907 for (i = 0; i < nb_ops; i++) 908 if ((op_type[i] & (OP_MMX | OP_SSE)) == (OP_MMX | OP_SSE) 909 && ops[i].type & OP_SSE) 910 p66 = 1; 911 } 912 if (p66) 765 913 g(0x66); 766 767 addr32 = data32 = 0; 768 #else 769 /* generate data16 prefix if needed */ 770 if (s == 1 || (pa->instr_type & OPC_D16)) 771 g(0x66); 772 #ifdef TCC_TARGET_X86_64 773 else if (s == 3) { 914 #ifdef TCC_TARGET_X86_64 915 rex64 = 0; 916 if (pa->instr_type & OPC_48) 917 rex64 = 1; 918 else if (s == 3 || (alltypes & OP_REG64)) { 774 919 /* generate REX prefix */ 775 if ((opcode != TOK_ASM_push && opcode != TOK_ASM_pop) 776 || !(ops[0].type & OP_REG64)) 777 g(0x48); 778 } 779 #endif 920 int default64 = 0; 921 for(i = 0; i < nb_ops; i++) { 922 if (op_type[i] == OP_REG64 && pa->opcode != 0xb8) { 923 /* If only 64bit regs are accepted in one operand 924 this is a default64 instruction without need for 925 REX prefixes, except for movabs(0xb8). */ 926 default64 = 1; 927 break; 928 } 929 } 930 /* XXX find better encoding for the default64 instructions. */ 931 if (((opcode != TOK_ASM_push && opcode != TOK_ASM_pop 932 && opcode != TOK_ASM_pushw && opcode != TOK_ASM_pushl 933 && opcode != TOK_ASM_pushq && opcode != TOK_ASM_popw 934 && opcode != TOK_ASM_popl && opcode != TOK_ASM_popq 935 && opcode != TOK_ASM_call && opcode != TOK_ASM_jmp)) 936 && !default64) 937 rex64 = 1; 938 } 780 939 #endif 781 940 782 941 /* now generates the operation */ 783 if ( pa->instr_type & OPC_FWAIT)942 if (OPCT_IS(pa->instr_type, OPC_FWAIT)) 784 943 g(0x9b); 785 944 if (seg_prefix) … … 787 946 788 947 v = pa->opcode; 948 if (pa->instr_type & OPC_0F) 949 v = ((v & ~0xff) << 8) | 0x0f00 | (v & 0xff); 789 950 if ((v == 0x69 || v == 0x6b) && nb_ops == 2) { 790 951 /* kludge for imul $im, %reg */ … … 806 967 /* arith case */ 807 968 v += ((opcode - TOK_ASM_addb) / NBWLX) << 3; 808 } else if ((pa->instr_type & (OPC _FARITH| OPC_MODRM)) == OPC_FARITH) {969 } else if ((pa->instr_type & (OPCT_MASK | OPC_MODRM)) == OPC_FARITH) { 809 970 /* fpu arith case */ 810 971 v += ((opcode - pa->sym) / 6) << 3; 811 972 } 973 974 /* search which operand will be used for modrm */ 975 modrm_index = -1; 976 modreg_index = -1; 977 if (pa->instr_type & OPC_MODRM) { 978 if (!nb_ops) { 979 /* A modrm opcode without operands is a special case (e.g. mfence). 980 It has a group and acts as if there's an register operand 0 981 (ax). */ 982 i = 0; 983 ops[i].type = OP_REG; 984 ops[i].reg = 0; 985 goto modrm_found; 986 } 987 /* first look for an ea operand */ 988 for(i = 0;i < nb_ops; i++) { 989 if (op_type[i] & OP_EA) 990 goto modrm_found; 991 } 992 /* then if not found, a register or indirection (shift instructions) */ 993 for(i = 0;i < nb_ops; i++) { 994 if (op_type[i] & (OP_REG | OP_MMX | OP_SSE | OP_INDIR)) 995 goto modrm_found; 996 } 997 #ifdef ASM_DEBUG 998 tcc_error("bad op table"); 999 #endif 1000 modrm_found: 1001 modrm_index = i; 1002 /* if a register is used in another operand then it is 1003 used instead of group */ 1004 for(i = 0;i < nb_ops; i++) { 1005 int t = op_type[i]; 1006 if (i != modrm_index && 1007 (t & (OP_REG | OP_MMX | OP_SSE | OP_CR | OP_TR | OP_DB | OP_SEG))) { 1008 modreg_index = i; 1009 break; 1010 } 1011 } 1012 } 1013 #ifdef TCC_TARGET_X86_64 1014 asm_rex (rex64, ops, nb_ops, op_type, modreg_index, modrm_index); 1015 #endif 1016 812 1017 if (pa->instr_type & OPC_REG) { 1018 /* mov $im, %reg case */ 1019 if (v == 0xb0 && s >= 1) 1020 v += 7; 813 1021 for(i = 0; i < nb_ops; i++) { 814 1022 if (op_type[i] & (OP_REG | OP_ST)) { … … 817 1025 } 818 1026 } 819 /* mov $im, %reg case */820 if (pa->opcode == 0xb0 && s >= 1)821 v += 7;822 1027 } 823 1028 if (pa->instr_type & OPC_B) 824 1029 v += s >= 1; 825 if (pa->instr_type & OPC_TEST) 826 v += test_bits[opcode - pa->sym]; 827 if (pa->instr_type & OPC_SHORTJMP) { 828 Sym *sym; 1030 if (nb_ops == 1 && pa->op_type[0] == OPT_DISP8) { 1031 ElfSym *esym; 829 1032 int jmp_disp; 830 1033 831 1034 /* see if we can really generate the jump with a byte offset */ 832 sym = ops[0].e.sym;833 if (! sym)1035 esym = elfsym(ops[0].e.sym); 1036 if (!esym || esym->st_shndx != cur_text_section->sh_num) 834 1037 goto no_short_jump; 835 if (sym->r != cur_text_section->sh_num) 836 goto no_short_jump; 837 jmp_disp = ops[0].e.v + sym->jnext - ind - 2; 1038 jmp_disp = ops[0].e.v + esym->st_value - ind - 2 - (v >= 0xff); 838 1039 if (jmp_disp == (int8_t)jmp_disp) { 839 1040 /* OK to generate jump */ 840 is_short_jmp = 1;1041 ops[0].e.sym = 0; 841 1042 ops[0].e.v = jmp_disp; 1043 op_type[0] = OP_IM8S; 842 1044 } else { 843 1045 no_short_jump: 844 if (pa->instr_type & OPC_JMP) { 845 /* long jump will be allowed. need to modify the 846 opcode slightly */ 847 if (v == 0xeb) 848 v = 0xe9; 849 else 850 v += 0x0f10; 851 } else { 852 tcc_error("invalid displacement"); 853 } 854 } 855 } 856 op1 = v >> 8; 1046 /* long jump will be allowed. need to modify the 1047 opcode slightly */ 1048 if (v == 0xeb) /* jmp */ 1049 v = 0xe9; 1050 else if (v == 0x70) /* jcc */ 1051 v += 0x0f10; 1052 else 1053 tcc_error("invalid displacement"); 1054 } 1055 } 1056 if (OPCT_IS(pa->instr_type, OPC_TEST)) 1057 v += test_bits[opcode - pa->sym]; 1058 op1 = v >> 16; 1059 if (op1) 1060 g(op1); 1061 op1 = (v >> 8) & 0xff; 857 1062 if (op1) 858 1063 g(op1); 859 1064 g(v); 860 1065 861 /* search which operand will used for modrm */ 862 modrm_index = 0; 863 if (pa->instr_type & OPC_SHIFT) { 1066 if (OPCT_IS(pa->instr_type, OPC_SHIFT)) { 864 1067 reg = (opcode - pa->sym) / NBWLX; 865 1068 if (reg == 6) 866 1069 reg = 7; 867 } else if ( pa->instr_type & OPC_ARITH) {1070 } else if (OPCT_IS(pa->instr_type, OPC_ARITH)) { 868 1071 reg = (opcode - pa->sym) / NBWLX; 869 } else if ( pa->instr_type & OPC_FARITH) {1072 } else if (OPCT_IS(pa->instr_type, OPC_FARITH)) { 870 1073 reg = (opcode - pa->sym) / 6; 871 1074 } else { 872 1075 reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7; 873 1076 } 1077 1078 pc = 0; 874 1079 if (pa->instr_type & OPC_MODRM) { 875 /* first look for an ea operand */876 for(i = 0;i < nb_ops; i++) {877 if (op_type[i] & OP_EA)878 goto modrm_found;879 }880 /* then if not found, a register or indirection (shift instructions) */881 for(i = 0;i < nb_ops; i++) {882 if (op_type[i] & (OP_REG | OP_MMX | OP_SSE | OP_INDIR))883 goto modrm_found;884 }885 #ifdef ASM_DEBUG886 tcc_error("bad op table");887 #endif888 modrm_found:889 modrm_index = i;890 1080 /* if a register is used in another operand then it is 891 1081 used instead of group */ 892 for(i = 0;i < nb_ops; i++) { 893 v = op_type[i]; 894 if (i != modrm_index && 895 (v & (OP_REG | OP_MMX | OP_SSE | OP_CR | OP_TR | OP_DB | OP_SEG))) { 896 reg = ops[i].reg; 897 break; 898 } 899 } 900 901 asm_modrm(reg, &ops[modrm_index]); 1082 if (modreg_index >= 0) 1083 reg = ops[modreg_index].reg; 1084 pc = asm_modrm(reg, &ops[modrm_index]); 902 1085 } 903 1086 904 1087 /* emit constants */ 905 1088 #ifndef TCC_TARGET_X86_64 906 if (pa->opcode == 0x9a || pa->opcode == 0xea) { 1089 if (!(pa->instr_type & OPC_0F) 1090 && (pa->opcode == 0x9a || pa->opcode == 0xea)) { 907 1091 /* ljmp or lcall kludge */ 908 #ifdef I386_ASM_16 909 if (s1->seg_size == 16 && o32 == 0) 910 gen_expr16(&ops[1].e); 911 else 912 #endif 913 gen_expr32(&ops[1].e); 1092 gen_expr32(&ops[1].e); 914 1093 if (ops[0].e.sym) 915 1094 tcc_error("cannot relocate"); … … 933 1112 v = OP_IM64; 934 1113 } 1114 1115 if ((v & (OP_IM8 | OP_IM8S | OP_IM16)) && ops[i].e.sym) 1116 tcc_error("cannot relocate"); 1117 935 1118 if (v & (OP_IM8 | OP_IM8S)) { 936 if (ops[i].e.sym)937 goto error_relocate;938 1119 g(ops[i].e.v); 939 1120 } else if (v & OP_IM16) { 940 #ifdef I386_ASM_16 941 if (s1->seg_size == 16) 942 gen_expr16(&ops[i].e); 943 else 944 #endif 945 if (ops[i].e.sym) 946 error_relocate: 947 tcc_error("cannot relocate"); 948 else 949 gen_le16(ops[i].e.v); 1121 gen_le16(ops[i].e.v); 1122 #ifdef TCC_TARGET_X86_64 1123 } else if (v & OP_IM64) { 1124 gen_expr64(&ops[i].e); 1125 #endif 1126 } else if (pa->op_type[i] == OPT_DISP || pa->op_type[i] == OPT_DISP8) { 1127 gen_disp32(&ops[i].e); 950 1128 } else { 951 if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) { 952 if (is_short_jmp) 953 g(ops[i].e.v); 954 #ifdef I386_ASM_16 955 else if (s1->seg_size == 16) 956 gen_disp16(&ops[i].e); 957 #endif 958 else 959 gen_disp32(&ops[i].e); 960 } else { 961 #ifdef I386_ASM_16 962 if (s1->seg_size == 16 && !((o32 == 1) && (v & OP_IM32))) 963 gen_expr16(&ops[i].e); 964 else 965 #endif 966 #ifdef TCC_TARGET_X86_64 967 if (v & OP_IM64) 968 gen_expr64(&ops[i].e); 969 else 970 #endif 971 gen_expr32(&ops[i].e); 972 } 1129 gen_expr32(&ops[i].e); 973 1130 } 974 #ifdef I386_ASM_16 975 } else if (v & (OP_REG16 | OP_REG32)) { 976 if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) { 977 /* jmp $r */ 978 g(0xE0 + ops[i].reg); 979 } 980 #endif 981 #ifdef TCC_TARGET_X86_64 982 } else if (v & (OP_REG32 | OP_REG64)) { 983 if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) { 984 /* jmp $r */ 985 g(0xE0 + ops[i].reg); 986 } 987 #endif 988 } 989 } 990 #ifdef I386_ASM_16 991 a32 = o32 = 0; 992 #endif 1131 } 1132 } 1133 1134 /* after immediate operands, adjust pc-relative address */ 1135 if (pc) 1136 add32le(cur_text_section->data + pc - 4, pc - ind); 993 1137 } 994 1138 … … 1022 1166 break; 1023 1167 case 'r': 1168 case 'R': 1169 case 'p': 1024 1170 pr = 3; 1025 1171 break; … … 1027 1173 case 'M': 1028 1174 case 'I': 1175 case 'e': 1029 1176 case 'i': 1030 1177 case 'm': … … 1047 1194 p++; 1048 1195 return p; 1196 } 1197 1198 /* If T (a token) is of the form "%reg" returns the register 1199 number and type, otherwise return -1. */ 1200 ST_FUNC int asm_parse_regvar (int t) 1201 { 1202 const char *s; 1203 Operand op; 1204 if (t < TOK_IDENT) 1205 return -1; 1206 s = table_ident[t - TOK_IDENT]->str; 1207 if (s[0] != '%') 1208 return -1; 1209 t = tok_alloc(s+1, strlen(s)-1)->tok; 1210 unget_tok(t); 1211 unget_tok('%'); 1212 parse_operand(tcc_state, &op); 1213 /* Accept only integer regs for now. */ 1214 if (op.type & OP_REG) 1215 return op.reg; 1216 else 1217 return -1; 1049 1218 } 1050 1219 … … 1091 1260 operands[k].input_index = i; 1092 1261 op->priority = 5; 1262 } else if ((op->vt->r & VT_VALMASK) == VT_LOCAL 1263 && op->vt->sym 1264 && (reg = op->vt->sym->r & VT_VALMASK) < VT_CONST) { 1265 op->priority = 1; 1266 op->reg = reg; 1093 1267 } else { 1094 1268 op->priority = constraint_priority(str); … … 1138 1312 reg_mask = REG_IN_MASK; 1139 1313 } 1314 if (op->reg >= 0) { 1315 if (is_reg_allocated(op->reg)) 1316 tcc_error("asm regvar requests register that's taken already"); 1317 reg = op->reg; 1318 goto reg_found; 1319 } 1140 1320 try_next: 1141 1321 c = *str++; … … 1190 1370 goto try_next; 1191 1371 case 'r': 1372 case 'R': 1373 case 'p': /* A general address, for x86(64) any register is acceptable*/ 1192 1374 /* any general register */ 1193 1375 for(reg = 0; reg < 8; reg++) { … … 1202 1384 regs_allocated[reg] |= reg_mask; 1203 1385 break; 1386 case 'e': 1204 1387 case 'i': 1205 1388 if (!((op->vt->r & (VT_VALMASK | VT_LVAL)) == VT_CONST)) … … 1294 1477 r = sv->r; 1295 1478 if ((r & VT_VALMASK) == VT_CONST) { 1296 if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n') 1479 if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n' && 1480 modifier != 'P') 1297 1481 cstr_ccat(add_str, '$'); 1298 1482 if (r & VT_SYM) { 1299 cstr_cat(add_str, get_tok_str(sv->sym->v, NULL)); 1300 if (sv->c.i != 0) { 1301 cstr_ccat(add_str, '+'); 1302 } else { 1303 return; 1304 } 1483 const char *name = get_tok_str(sv->sym->v, NULL); 1484 if (sv->sym->v >= SYM_FIRST_ANOM) { 1485 /* In case of anonymous symbols ("L.42", used 1486 for static data labels) we can't find them 1487 in the C symbol table when later looking up 1488 this name. So enter them now into the asm label 1489 list when we still know the symbol. */ 1490 get_asm_sym(tok_alloc(name, strlen(name))->tok, sv->sym); 1491 } 1492 cstr_cat(add_str, name, -1); 1493 if ((uint32_t)sv->c.i == 0) 1494 goto no_offset; 1495 cstr_ccat(add_str, '+'); 1305 1496 } 1306 1497 val = sv->c.i; 1307 1498 if (modifier == 'n') 1308 1499 val = -val; 1309 snprintf(buf, sizeof(buf), "%d", sv->c.i); 1310 cstr_cat(add_str, buf); 1500 snprintf(buf, sizeof(buf), "%d", (int)sv->c.i); 1501 cstr_cat(add_str, buf, -1); 1502 no_offset:; 1503 #ifdef TCC_TARGET_X86_64 1504 if (r & VT_LVAL) 1505 cstr_cat(add_str, "(%rip)", -1); 1506 #endif 1311 1507 } else if ((r & VT_VALMASK) == VT_LOCAL) { 1312 snprintf(buf, sizeof(buf), "%d(%%ebp)", sv->c.i); 1313 cstr_cat(add_str, buf); 1508 #ifdef TCC_TARGET_X86_64 1509 snprintf(buf, sizeof(buf), "%d(%%rbp)", (int)sv->c.i); 1510 #else 1511 snprintf(buf, sizeof(buf), "%d(%%ebp)", (int)sv->c.i); 1512 #endif 1513 cstr_cat(add_str, buf, -1); 1314 1514 } else if (r & VT_LVAL) { 1315 1515 reg = r & VT_VALMASK; … … 1317 1517 tcc_error("internal compiler error"); 1318 1518 snprintf(buf, sizeof(buf), "(%%%s)", 1319 get_tok_str(TOK_ASM_eax + reg, NULL)); 1320 cstr_cat(add_str, buf); 1519 #ifdef TCC_TARGET_X86_64 1520 get_tok_str(TOK_ASM_rax + reg, NULL) 1521 #else 1522 get_tok_str(TOK_ASM_eax + reg, NULL) 1523 #endif 1524 ); 1525 cstr_cat(add_str, buf, -1); 1321 1526 } else { 1322 1527 /* register case */ … … 1326 1531 1327 1532 /* choose register operand size */ 1328 if ((sv->type.t & VT_BTYPE) == VT_BYTE) 1533 if ((sv->type.t & VT_BTYPE) == VT_BYTE || 1534 (sv->type.t & VT_BTYPE) == VT_BOOL) 1329 1535 size = 1; 1330 1536 else if ((sv->type.t & VT_BTYPE) == VT_SHORT) 1331 1537 size = 2; 1332 1538 #ifdef TCC_TARGET_X86_64 1333 else if ((sv->type.t & VT_BTYPE) == VT_LLONG) 1539 else if ((sv->type.t & VT_BTYPE) == VT_LLONG || 1540 (sv->type.t & VT_BTYPE) == VT_PTR) 1334 1541 size = 8; 1335 1542 #endif … … 1349 1556 } else if (modifier == 'w') { 1350 1557 size = 2; 1558 } else if (modifier == 'k') { 1559 size = 4; 1351 1560 #ifdef TCC_TARGET_X86_64 1352 1561 } else if (modifier == 'q') { … … 1375 1584 } 1376 1585 snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL)); 1377 cstr_cat(add_str, buf );1586 cstr_cat(add_str, buf, -1); 1378 1587 } 1379 1588 } 1380 1589 1381 /* generate prolog and epilog code for asm stat ment */1590 /* generate prolog and epilog code for asm statement */ 1382 1591 ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, 1383 1592 int nb_outputs, int is_output, … … 1388 1597 ASMOperand *op; 1389 1598 int i, reg; 1390 static uint8_t reg_saved[NB_SAVED_REGS] = { 3, 6, 7 }; 1599 1600 /* Strictly speaking %Xbp and %Xsp should be included in the 1601 call-preserved registers, but currently it doesn't matter. */ 1602 #ifdef TCC_TARGET_X86_64 1603 #ifdef TCC_TARGET_PE 1604 static uint8_t reg_saved[] = { 3, 6, 7, 12, 13, 14, 15 }; 1605 #else 1606 static uint8_t reg_saved[] = { 3, 12, 13, 14, 15 }; 1607 #endif 1608 #else 1609 static uint8_t reg_saved[] = { 3, 6, 7 }; 1610 #endif 1391 1611 1392 1612 /* mark all used registers */ … … 1399 1619 if (!is_output) { 1400 1620 /* generate reg save code */ 1401 for(i = 0; i < NB_SAVED_REGS; i++) {1621 for(i = 0; i < sizeof(reg_saved)/sizeof(reg_saved[0]); i++) { 1402 1622 reg = reg_saved[i]; 1403 1623 if (regs_allocated[reg]) { 1404 #ifdef I386_ASM_16 1405 if (tcc_state->seg_size == 16) 1406 g(0x66); 1407 #endif 1624 if (reg >= 8) 1625 g(0x41), reg-=8; 1408 1626 g(0x50 + reg); 1409 1627 } … … 1420 1638 SValue sv; 1421 1639 sv = *op->vt; 1422 sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL; 1640 sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL; 1641 sv.type.t = VT_PTR; 1423 1642 load(op->reg, &sv); 1424 1643 } else if (i >= nb_outputs || op->is_rw) { … … 1428 1647 SValue sv; 1429 1648 sv = *op->vt; 1430 sv.c. ul+= 4;1649 sv.c.i += 4; 1431 1650 load(TREG_XDX, &sv); 1432 1651 } … … 1444 1663 sv = *op->vt; 1445 1664 sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL; 1665 sv.type.t = VT_PTR; 1446 1666 load(out_reg, &sv); 1447 1667 1668 sv = *op->vt; 1448 1669 sv.r = (sv.r & ~VT_VALMASK) | out_reg; 1449 1670 store(op->reg, &sv); … … 1454 1675 SValue sv; 1455 1676 sv = *op->vt; 1456 sv.c. ul+= 4;1677 sv.c.i += 4; 1457 1678 store(TREG_XDX, &sv); 1458 1679 } … … 1461 1682 } 1462 1683 /* generate reg restore code */ 1463 for(i = NB_SAVED_REGS- 1; i >= 0; i--) {1684 for(i = sizeof(reg_saved)/sizeof(reg_saved[0]) - 1; i >= 0; i--) { 1464 1685 reg = reg_saved[i]; 1465 1686 if (regs_allocated[reg]) { 1466 #ifdef I386_ASM_16 1467 if (tcc_state->seg_size == 16) 1468 g(0x66); 1469 #endif 1687 if (reg >= 8) 1688 g(0x41), reg-=8; 1470 1689 g(0x58 + reg); 1471 1690 } … … 1478 1697 int reg; 1479 1698 TokenSym *ts; 1699 #ifdef TCC_TARGET_X86_64 1700 unsigned int type; 1701 #endif 1480 1702 1481 1703 if (!strcmp(str, "memory") || 1482 !strcmp(str, "cc")) 1704 !strcmp(str, "cc") || 1705 !strcmp(str, "flags")) 1483 1706 return; 1484 1707 ts = tok_alloc(str, strlen(str)); … … 1491 1714 } else if (reg >= TOK_ASM_rax && reg <= TOK_ASM_rdi) { 1492 1715 reg -= TOK_ASM_rax; 1716 } else if ((reg = asm_parse_numeric_reg(reg, &type)) >= 0) { 1717 ; 1493 1718 #endif 1494 1719 } else { -
EcnlProtoTool/trunk/tcc-0.9.27/i386-asm.h
r321 r331 39 39 40 40 /* strings */ 41 ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL ))42 ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL ))41 ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWLX)) 42 ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWLX)) 43 43 44 44 ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL)) 45 45 ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL)) 46 46 47 ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL ))48 ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL ))49 50 ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL ))51 ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL ))52 53 ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL ))54 ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL ))55 56 ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL ))57 ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL ))47 ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWLX)) 48 ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWLX)) 49 50 ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWLX)) 51 ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWLX)) 52 53 ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWLX)) 54 ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWLX)) 55 56 ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWLX)) 57 ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWLX)) 58 58 59 59 /* bits */ 60 60 61 ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL , OPT_REGW | OPT_EA, OPT_REGW))62 ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL , OPT_REGW | OPT_EA, OPT_REGW))63 64 ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL , OPT_REGW, OPT_REGW | OPT_EA))65 ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL , OPT_IM8, OPT_REGW | OPT_EA))66 67 ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL , OPT_REGW, OPT_REGW | OPT_EA))68 ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL , OPT_IM8, OPT_REGW | OPT_EA))69 70 ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL , OPT_REGW, OPT_REGW | OPT_EA))71 ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL , OPT_IM8, OPT_REGW | OPT_EA))72 73 ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL , OPT_REGW, OPT_REGW | OPT_EA))74 ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL , OPT_IM8, OPT_REGW | OPT_EA))61 ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW)) 62 ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW)) 63 64 ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA)) 65 ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA)) 66 67 ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA)) 68 ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA)) 69 70 ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA)) 71 ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA)) 72 73 ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA)) 74 ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA)) 75 75 76 76 /* prefixes */ 77 77 DEF_ASM_OP0(wait, 0x9b) 78 78 DEF_ASM_OP0(fwait, 0x9b) 79 #ifdef I386_ASM_1680 DEF_ASM_OP0(a32, 0x67)81 DEF_ASM_OP0(o32, 0x66)82 #else83 79 DEF_ASM_OP0(aword, 0x67) 84 80 DEF_ASM_OP0(addr16, 0x67) 85 81 ALT(DEF_ASM_OP0(word, 0x66)) 86 82 DEF_ASM_OP0(data16, 0x66) 87 #endif88 83 DEF_ASM_OP0(lock, 0xf0) 89 84 DEF_ASM_OP0(rep, 0xf3) … … 103 98 104 99 /* NOTE: we took the same order as gas opcode definition order */ 105 ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL , OPT_ADDR, OPT_EAX))106 ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL , OPT_EAX, OPT_ADDR))107 ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL , OPT_REG, OPT_EA | OPT_REG))108 ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL , OPT_EA | OPT_REG, OPT_REG))109 ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL , OPT_IM, OPT_REG))110 ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL , OPT_IM, OPT_REG | OPT_EA))111 112 ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL , OPT_SEG, OPT_EA | OPT_REG))113 ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL , OPT_EA | OPT_REG, OPT_SEG))114 115 ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL , OPT_CR, OPT_REG32))116 ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL , OPT_DB, OPT_REG32))117 ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL , OPT_TR, OPT_REG32))118 ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL , OPT_REG32, OPT_CR))119 ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL , OPT_REG32, OPT_DB))120 ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL , OPT_REG32, OPT_TR))100 ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWLX, OPT_ADDR, OPT_EAX)) 101 ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWLX, OPT_EAX, OPT_ADDR)) 102 ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) 103 ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) 104 ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWLX, OPT_IM, OPT_REG)) 105 ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWLX, OPT_IM, OPT_REG | OPT_EA)) 106 107 ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WLX, OPT_SEG, OPT_EA | OPT_REG)) 108 ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WLX, OPT_EA | OPT_REG, OPT_SEG)) 109 110 ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WLX, OPT_CR, OPT_REG32)) 111 ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WLX, OPT_DB, OPT_REG32)) 112 ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WLX, OPT_TR, OPT_REG32)) 113 ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WLX, OPT_REG32, OPT_CR)) 114 ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WLX, OPT_REG32, OPT_DB)) 115 ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WLX, OPT_REG32, OPT_TR)) 121 116 122 117 ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32)) 123 ALT(DEF_ASM_OP2(movsbw, 0x 0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))118 ALT(DEF_ASM_OP2(movsbw, 0x660fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG16)) 124 119 ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32)) 125 ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL , OPT_REG8 | OPT_EA, OPT_REGW))120 ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WLX, OPT_REG8 | OPT_EA, OPT_REGW)) 126 121 ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32)) 127 122 128 ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL , OPT_REGW))129 ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL , OPT_REGW | OPT_EA))130 ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL , OPT_IM8S))131 ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL , OPT_IM32))132 ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL , OPT_SEG))133 134 ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL , OPT_REGW))135 ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL , OPT_REGW | OPT_EA))136 ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL , OPT_SEG))137 138 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL , OPT_REG, OPT_EAX))139 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL , OPT_EAX, OPT_REG))140 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL , OPT_REG, OPT_EA | OPT_REG))141 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL , OPT_EA | OPT_REG, OPT_REG))123 ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WLX, OPT_REGW)) 124 ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA)) 125 ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WLX, OPT_IM8S)) 126 ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WLX, OPT_IM32)) 127 ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WLX, OPT_SEG)) 128 129 ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WLX, OPT_REGW)) 130 ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA)) 131 ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WLX, OPT_SEG)) 132 133 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WLX, OPT_REGW, OPT_EAX)) 134 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WLX, OPT_EAX, OPT_REGW)) 135 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) 136 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) 142 137 143 138 ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX)) … … 151 146 ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX)) 152 147 153 ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL , OPT_EA, OPT_REG))148 ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WLX, OPT_EA, OPT_REG)) 154 149 155 150 ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32)) … … 160 155 161 156 /* arith */ 162 ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL , OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */163 ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL , OPT_EA | OPT_REG, OPT_REG))164 ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL , OPT_IM, OPT_EAX))165 ALT(DEF_ASM_OP2(add b, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))166 ALT(DEF_ASM_OP2(add w, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))167 168 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL , OPT_EA | OPT_REG,OPT_REG))169 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL , OPT_REG, OPT_EA |OPT_REG))170 ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL , OPT_IM, OPT_EAX))171 ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL , OPT_IM, OPT_EA | OPT_REG))172 173 ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL , OPT_REGW))174 ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL , OPT_REG | OPT_EA))175 ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL , OPT_REGW))176 ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL , OPT_REG | OPT_EA))177 178 ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL , OPT_REG | OPT_EA))179 ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL , OPT_REG | OPT_EA))180 181 ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL , OPT_REG | OPT_EA))182 ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL , OPT_REG | OPT_EA))183 184 ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL , OPT_REG | OPT_EA, OPT_REG))185 ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL , OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))186 ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL , OPT_IM8S, OPT_REGW))187 ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL , OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))188 ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL , OPT_IMW, OPT_REGW))189 190 ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL , OPT_REG | OPT_EA))191 ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL , OPT_REG | OPT_EA, OPT_EAX))192 ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL , OPT_REG | OPT_EA))193 ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL , OPT_REG | OPT_EA, OPT_EAX))157 ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */ 158 ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) 159 ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWLX, OPT_IM, OPT_EAX)) 160 ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_EA | OPT_REGW)) 161 ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG)) 162 163 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) 164 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) 165 ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWLX, OPT_IM, OPT_EAX)) 166 ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG)) 167 168 ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WLX, OPT_REGW)) 169 ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 170 ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WLX, OPT_REGW)) 171 ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 172 173 ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 174 ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 175 176 ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 177 ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 178 179 ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WLX, OPT_REG | OPT_EA, OPT_REG)) 180 ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW)) 181 ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_REGW)) 182 ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WLX, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW)) 183 ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WLX, OPT_IMW, OPT_REGW)) 184 185 ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 186 ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA, OPT_EAX)) 187 ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 188 ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA, OPT_EAX)) 194 189 195 190 /* shifts */ 196 ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))197 ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))198 ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))199 200 ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL , OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))201 ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL , OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))202 ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL , OPT_REGW, OPT_EA | OPT_REGW))203 ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL , OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))204 ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL , OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))205 ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL , OPT_REGW, OPT_EA | OPT_REGW))191 ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG)) 192 ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG)) 193 ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_EA | OPT_REG)) 194 195 ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW)) 196 ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WLX, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW)) 197 ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_EA | OPT_REGW)) 198 ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW)) 199 ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WLX, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW)) 200 ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_EA | OPT_REGW)) 206 201 207 202 ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR)) 208 ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))203 ALT(DEF_ASM_OP1(call, 0xe8, 0, 0, OPT_DISP)) 209 204 ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR)) 210 ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR)) 211 #ifdef I386_ASM_16 212 ALT(DEF_ASM_OP1(jmp, 0xff, 0, OPC_JMP | OPC_WL, OPT_REGW)) 213 #endif 205 ALT(DEF_ASM_OP1(jmp, 0xeb, 0, 0, OPT_DISP8)) 214 206 215 207 ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32)) 216 ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))208 ALT(DEF_ASM_OP1(lcall, 0xff, 3, OPC_MODRM, OPT_EA)) 217 209 ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32)) 218 ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))210 ALT(DEF_ASM_OP1(ljmp, 0xff, 5, OPC_MODRM, OPT_EA)) 219 211 220 212 ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8)) 221 213 ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA)) 214 ALT(DEF_ASM_OP1(setob, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA)) 222 215 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8) 223 216 DEF_ASM_OP0(leave, 0xc9) … … 229 222 ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16)) 230 223 231 ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_ SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))232 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)233 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)234 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)235 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)236 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)237 DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)224 ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_TEST, OPT_DISP8)) 225 DEF_ASM_OP1(loopne, 0xe0, 0, 0, OPT_DISP8) 226 DEF_ASM_OP1(loopnz, 0xe0, 0, 0, OPT_DISP8) 227 DEF_ASM_OP1(loope, 0xe1, 0, 0, OPT_DISP8) 228 DEF_ASM_OP1(loopz, 0xe1, 0, 0, OPT_DISP8) 229 DEF_ASM_OP1(loop, 0xe2, 0, 0, OPT_DISP8) 230 DEF_ASM_OP1(jecxz, 0xe3, 0, 0, OPT_DISP8) 238 231 239 232 /* float */ … … 349 342 /* segments */ 350 343 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA) 351 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)344 ALT(DEF_ASM_OP2(larw, 0x0f02, 0, OPC_MODRM | OPC_WLX, OPT_REG | OPT_EA, OPT_REG)) 352 345 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA) 353 346 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA) 354 347 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG) 355 348 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG) 356 ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL , OPT_EA | OPT_REG, OPT_REG))349 ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WLX, OPT_EA | OPT_REG, OPT_REG)) 357 350 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG) 358 351 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA) … … 364 357 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA) 365 358 366 #ifdef I386_ASM_16367 /* 386 */368 DEF_ASM_OP0(loadall386, 0x0f07)369 #endif370 371 359 /* 486 */ 372 360 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 ) 373 ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL , OPT_REG, OPT_REG | OPT_EA ))374 ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL , OPT_REG, OPT_REG | OPT_EA ))361 ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA )) 362 ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA )) 375 363 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA ) 376 364 377 365 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA) 378 DEF_ASM_OP2(boundw, 0x6 2, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)366 DEF_ASM_OP2(boundw, 0x6662, 0, OPC_MODRM, OPT_REG16, OPT_EA) 379 367 380 368 /* pentium */ … … 382 370 383 371 /* pentium pro */ 384 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 385 #ifdef I386_ASM_16 386 ALT(DEF_ASM_OP2(cmovno, 0x0f41, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 387 ALT(DEF_ASM_OP2(cmovc, 0x0f42, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 388 ALT(DEF_ASM_OP2(cmovnc, 0x0f43, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 389 ALT(DEF_ASM_OP2(cmovz, 0x0f44, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 390 ALT(DEF_ASM_OP2(cmovnz, 0x0f45, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 391 ALT(DEF_ASM_OP2(cmovna, 0x0f46, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 392 ALT(DEF_ASM_OP2(cmova, 0x0f47, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 393 #endif 372 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW)) 394 373 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 ) 395 374 DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 ) … … 408 387 /* mmx */ 409 388 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */ 410 411 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX ) 412 ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 )) 389 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMXSSE ) 413 390 DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 391 ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG32 )) 414 392 ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX )) 415 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 416 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 417 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 418 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 419 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 420 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 421 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 422 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 423 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 424 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 425 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 426 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 427 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 428 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 429 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 430 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 431 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 432 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 433 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 434 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 435 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 436 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 437 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 438 ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX )) 439 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 440 ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX )) 441 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 442 ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX )) 443 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 444 ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX )) 445 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 446 ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX )) 447 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 448 ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX )) 449 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 450 ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX )) 451 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 452 ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX )) 453 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 454 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 455 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 456 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 457 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 458 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 459 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 460 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 461 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 462 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 463 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 464 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 465 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 466 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 393 ALT(DEF_ASM_OP2(movq, 0x660fd6, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_SSE )) 394 ALT(DEF_ASM_OP2(movq, 0xf30f7e, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )) 395 396 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 397 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 398 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 399 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 400 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 401 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 402 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 403 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 404 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 405 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 406 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 407 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 408 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 409 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 410 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 411 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 412 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 413 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 414 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 415 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 416 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 417 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 418 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 419 ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 420 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 421 ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 422 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 423 ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 424 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 425 ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 426 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 427 ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 428 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 429 ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 430 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 431 ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 432 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 433 ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 434 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 435 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 436 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 437 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 438 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 439 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 440 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 441 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 442 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 443 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 444 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 445 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 446 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 447 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 448 449 /* sse */ 450 DEF_ASM_OP2(movups, 0x0f10, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE ) 451 ALT(DEF_ASM_OP2(movups, 0x0f11, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 )) 452 DEF_ASM_OP2(movaps, 0x0f28, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE ) 453 ALT(DEF_ASM_OP2(movaps, 0x0f29, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 )) 454 DEF_ASM_OP2(movhps, 0x0f16, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE ) 455 ALT(DEF_ASM_OP2(movhps, 0x0f17, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 )) 456 DEF_ASM_OP2(addps, 0x0f58, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 457 DEF_ASM_OP2(cvtpi2ps, 0x0f2a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_SSE ) 458 DEF_ASM_OP2(cvtps2pi, 0x0f2d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX ) 459 DEF_ASM_OP2(cvttps2pi, 0x0f2c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX ) 460 DEF_ASM_OP2(divps, 0x0f5e, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 461 DEF_ASM_OP2(maxps, 0x0f5f, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 462 DEF_ASM_OP2(minps, 0x0f5d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 463 DEF_ASM_OP2(mulps, 0x0f59, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 464 DEF_ASM_OP2(pavgb, 0x0fe0, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 465 DEF_ASM_OP2(pavgw, 0x0fe3, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 466 DEF_ASM_OP2(pmaxsw, 0x0fee, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 467 DEF_ASM_OP2(pmaxub, 0x0fde, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 468 DEF_ASM_OP2(pminsw, 0x0fea, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 469 DEF_ASM_OP2(pminub, 0x0fda, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 470 DEF_ASM_OP2(rcpss, 0x0f53, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 471 DEF_ASM_OP2(rsqrtps, 0x0f52, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 472 DEF_ASM_OP2(sqrtps, 0x0f51, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 473 DEF_ASM_OP2(subps, 0x0f5c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 467 474 468 475 #undef ALT -
EcnlProtoTool/trunk/tcc-0.9.27/i386-gen.c
r321 r331 22 22 23 23 /* number of available registers */ 24 #define NB_REGS 424 #define NB_REGS 5 25 25 #define NB_ASM_REGS 8 26 #define CONFIG_TCC_ASM 26 27 27 28 /* a register can belong to several classes. The classes must be … … 34 35 #define RC_ECX 0x0010 35 36 #define RC_EDX 0x0020 37 #define RC_EBX 0x0040 38 36 39 #define RC_IRET RC_EAX /* function return: integer register */ 37 40 #define RC_LRET RC_EDX /* function return: second integer register */ … … 43 46 TREG_ECX, 44 47 TREG_EDX, 48 TREG_EBX, 45 49 TREG_ST0, 50 TREG_ESP = 4 46 51 }; 47 52 … … 56 61 /* defined if structures are passed as pointers. Otherwise structures 57 62 are directly pushed on stack. */ 58 / /#define FUNC_STRUCT_PARAM_AS_PTR63 /* #define FUNC_STRUCT_PARAM_AS_PTR */ 59 64 60 65 /* pointer size, in bytes */ … … 67 72 #define MAX_ALIGN 8 68 73 69 70 #define psym oad71 72 /******************************************************/73 /* ELF defines */74 75 #define EM_TCC_TARGET EM_38676 77 /* relocation type for 32 bit data relocation */78 #define R_DATA_32 R_386_3279 #define R_DATA_PTR R_386_3280 #define R_JMP_SLOT R_386_JMP_SLOT81 #define R_COPY R_386_COPY82 83 #define ELF_START_ADDR 0x0804800084 #define ELF_PAGE_SIZE 0x100085 86 74 /******************************************************/ 87 75 #else /* ! TARGET_DEFS_ONLY */ … … 89 77 #include "tcc.h" 90 78 79 /* define to 1/0 to [not] have EBX as 4th register */ 80 #define USE_EBX 0 81 91 82 ST_DATA const int reg_classes[NB_REGS] = { 92 83 /* eax */ RC_INT | RC_EAX, 93 84 /* ecx */ RC_INT | RC_ECX, 94 85 /* edx */ RC_INT | RC_EDX, 86 /* ebx */ (RC_INT | RC_EBX) * USE_EBX, 95 87 /* st0 */ RC_FLOAT | RC_ST0, 96 88 }; … … 99 91 static int func_ret_sub; 100 92 #ifdef CONFIG_TCC_BCHECK 101 static unsigned long func_bound_offset; 93 static addr_t func_bound_offset; 94 static unsigned long func_bound_ind; 102 95 #endif 103 96 … … 106 99 { 107 100 int ind1; 101 if (nocode_wanted) 102 return; 108 103 ind1 = ind + 1; 109 104 if (ind1 > cur_text_section->data_allocated) … … 138 133 ST_FUNC void gsym_addr(int t, int a) 139 134 { 140 int n, *ptr;141 135 while (t) { 142 ptr = (int *)(cur_text_section->data + t);143 n = *ptr; /* next value */144 *ptr = a - t - 4;136 unsigned char *ptr = cur_text_section->data + t; 137 uint32_t n = read32le(ptr); /* next value */ 138 write32le(ptr, a - t - 4); 145 139 t = n; 146 140 } … … 152 146 } 153 147 154 /* psym is used to put an instruction with a data field which is a155 reference to a symbol. It is in fact the same as oad ! */156 #define psym oad157 158 148 /* instruction + 4 bytes data. Return the address of the data */ 159 ST_FUNC int oad(int c, int s) 160 { 161 int ind1; 162 149 static int oad(int c, int s) 150 { 151 int t; 152 if (nocode_wanted) 153 return s; 163 154 o(c); 164 ind1 = ind + 4; 165 if (ind1 > cur_text_section->data_allocated) 166 section_realloc(cur_text_section, ind1); 167 *(int *)(cur_text_section->data + ind) = s; 168 s = ind; 169 ind = ind1; 170 return s; 171 } 155 t = ind; 156 gen_le32(s); 157 return t; 158 } 159 160 /* generate jmp to a label */ 161 #define gjmp2(instr,lbl) oad(instr,lbl) 172 162 173 163 /* output constant with relocation if 'r & VT_SYM' is true */ … … 186 176 } 187 177 188 /* generate a modrm reference. 'op_reg' contains the add tionnal 3178 /* generate a modrm reference. 'op_reg' contains the additional 3 189 179 opcode bits */ 190 180 static void gen_modrm(int op_reg, int r, Sym *sym, int c) … … 221 211 222 212 fr = sv->r; 223 ft = sv->type.t; 224 fc = sv->c.ul; 213 ft = sv->type.t & ~VT_DEFSIGN; 214 fc = sv->c.i; 215 216 ft &= ~(VT_VOLATILE | VT_CONSTANT); 225 217 226 218 v = fr & VT_VALMASK; … … 229 221 v1.type.t = VT_INT; 230 222 v1.r = VT_LOCAL | VT_LVAL; 231 v1.c. ul= fc;223 v1.c.i = fc; 232 224 fr = r; 233 225 if (!(reg_classes[fr] & RC_INT)) … … 244 236 o(0xdb); /* fldt */ 245 237 r = 5; 246 } else if ((ft & VT_TYPE) == VT_BYTE ) {238 } else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) { 247 239 o(0xbe0f); /* movsbl */ 248 240 } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { … … 297 289 298 290 ft = v->type.t; 299 fc = v->c. ul;291 fc = v->c.i; 300 292 fr = v->r & VT_VALMASK; 293 ft &= ~(VT_VOLATILE | VT_CONSTANT); 301 294 bt = ft & VT_BTYPE; 302 295 /* XXX: incorrect if float reg to reg */ … … 338 331 } 339 332 333 #if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE 334 static void gen_static_call(int v) 335 { 336 Sym *sym; 337 338 sym = external_global_sym(v, &func_old_type, 0); 339 oad(0xe8, -4); 340 greloc(cur_text_section, sym, ind-4, R_386_PC32); 341 } 342 #endif 343 340 344 /* 'is_jmp' is '1' if it is a jump */ 341 345 static void gcall_or_jmp(int is_jmp) 342 346 { 343 347 int r; 344 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { 345 /* constant case */ 346 if (vtop->r & VT_SYM) { 347 /* relocation case */ 348 greloc(cur_text_section, vtop->sym, 349 ind + 1, R_386_PC32); 350 } else { 351 /* put an empty PC32 relocation */ 352 put_elf_reloc(symtab_section, cur_text_section, 353 ind + 1, R_386_PC32, 0); 354 } 355 oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */ 348 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) { 349 /* constant and relocation case */ 350 greloc(cur_text_section, vtop->sym, ind + 1, R_386_PC32); 351 oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */ 356 352 } else { 357 353 /* otherwise, indirect call */ … … 360 356 o(0xd0 + r + (is_jmp << 4)); 361 357 } 358 if (!is_jmp) { 359 int rt; 360 /* extend the return value to the whole register if necessary 361 visual studio and gcc do not always set the whole eax register 362 when assigning the return value of a function */ 363 rt = vtop->type.ref->type.t; 364 switch (rt & VT_BTYPE) { 365 case VT_BYTE: 366 if (rt & VT_UNSIGNED) { 367 o(0xc0b60f); /* movzx %al, %eax */ 368 } 369 else { 370 o(0xc0be0f); /* movsx %al, %eax */ 371 } 372 break; 373 case VT_SHORT: 374 if (rt & VT_UNSIGNED) { 375 o(0xc0b70f); /* movzx %ax, %eax */ 376 } 377 else { 378 o(0xc0bf0f); /* movsx %ax, %eax */ 379 } 380 break; 381 default: 382 break; 383 } 384 } 362 385 } 363 386 364 387 static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX }; 365 388 static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX }; 389 390 /* Return the number of registers needed to return the struct, or 0 if 391 returning via struct pointer. */ 392 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) 393 { 394 #ifdef TCC_TARGET_PE 395 int size, align; 396 *ret_align = 1; // Never have to re-align return values for x86 397 *regsize = 4; 398 size = type_size(vt, &align); 399 if (size > 8 || (size & (size - 1))) 400 return 0; 401 if (size == 8) 402 ret->t = VT_LLONG; 403 else if (size == 4) 404 ret->t = VT_INT; 405 else if (size == 2) 406 ret->t = VT_SHORT; 407 else 408 ret->t = VT_BYTE; 409 ret->ref = NULL; 410 return 1; 411 #else 412 *ret_align = 1; // Never have to re-align return values for x86 413 return 0; 414 #endif 415 } 366 416 367 417 /* Generate function call. The function address is pushed first, then … … 422 472 save_regs(0); /* save used temporary registers */ 423 473 func_sym = vtop->type.ref; 424 func_call = FUNC_CALL(func_sym->r);474 func_call = func_sym->f.func_call; 425 475 /* fast call case */ 426 476 if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || … … 443 493 } 444 494 } 495 #ifndef TCC_TARGET_PE 496 else if ((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT) 497 args_size -= 4; 498 #endif 445 499 gcall_or_jmp(0); 446 500 447 #ifdef TCC_TARGET_PE 448 if ((func_sym->type.t & VT_BTYPE) == VT_STRUCT) 449 args_size -= 4; 450 #endif 451 if (args_size && func_call != FUNC_STDCALL) 501 if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW) 452 502 gadd_sp(args_size); 453 503 vtop--; … … 455 505 456 506 #ifdef TCC_TARGET_PE 457 #define FUNC_PROLOG_SIZE 10507 #define FUNC_PROLOG_SIZE (10 + USE_EBX) 458 508 #else 459 #define FUNC_PROLOG_SIZE 9509 #define FUNC_PROLOG_SIZE (9 + USE_EBX) 460 510 #endif 461 511 … … 470 520 471 521 sym = func_type->ref; 472 func_call = FUNC_CALL(sym->r);522 func_call = sym->f.func_call; 473 523 addr = 8; 474 524 loc = 0; … … 492 542 implicit pointer parameter */ 493 543 func_vt = sym->type; 544 func_var = (sym->f.func_type == FUNC_ELLIPSIS); 545 #ifdef TCC_TARGET_PE 546 size = type_size(&func_vt,&align); 547 if (((func_vt.t & VT_BTYPE) == VT_STRUCT) 548 && (size > 8 || (size & (size - 1)))) { 549 #else 494 550 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { 551 #endif 495 552 /* XXX: fastcall case ? */ 496 553 func_vc = addr; … … 524 581 } 525 582 func_ret_sub = 0; 526 /* pascal type call ? */527 if (func_call == FUNC_STDCALL )583 /* pascal type call or fastcall ? */ 584 if (func_call == FUNC_STDCALL || func_call == FUNC_FASTCALLW) 528 585 func_ret_sub = addr - 8; 529 #if def TCC_TARGET_PE586 #ifndef TCC_TARGET_PE 530 587 else if (func_vc) 531 588 func_ret_sub = 4; … … 535 592 /* leave some room for bound checking code */ 536 593 if (tcc_state->do_bounds_check) { 594 func_bound_offset = lbounds_section->data_offset; 595 func_bound_ind = ind; 537 596 oad(0xb8, 0); /* lbound section pointer */ 538 597 oad(0xb8, 0); /* call to function */ 539 func_bound_offset = lbounds_section->data_offset;540 598 } 541 599 #endif … … 545 603 ST_FUNC void gfunc_epilog(void) 546 604 { 547 int v, saved_ind;605 addr_t v, saved_ind; 548 606 549 607 #ifdef CONFIG_TCC_BCHECK 550 608 if (tcc_state->do_bounds_check 551 609 && func_bound_offset != lbounds_section->data_offset) { 552 int saved_ind; 553 int *bounds_ptr; 554 Sym *sym, *sym_data; 610 addr_t saved_ind; 611 addr_t *bounds_ptr; 612 Sym *sym_data; 613 555 614 /* add end of table info */ 556 bounds_ptr = section_ptr_add(lbounds_section, sizeof( int));615 bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); 557 616 *bounds_ptr = 0; 617 558 618 /* generate bound local allocation */ 559 619 saved_ind = ind; 560 ind = func_ sub_sp_offset;620 ind = func_bound_ind; 561 621 sym_data = get_sym_ref(&char_pointer_type, lbounds_section, 562 622 func_bound_offset, lbounds_section->data_offset); … … 564 624 ind + 1, R_386_32); 565 625 oad(0xb8, 0); /* mov %eax, xxx */ 566 sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0); 567 greloc(cur_text_section, sym, 568 ind + 1, R_386_PC32); 569 oad(0xe8, -4); 626 gen_static_call(TOK___bound_local_new); 570 627 ind = saved_ind; 628 571 629 /* generate bound check local freeing */ 572 630 o(0x5250); /* save returned value, if any */ 573 greloc(cur_text_section, sym_data, 574 ind + 1, R_386_32); 631 greloc(cur_text_section, sym_data, ind + 1, R_386_32); 575 632 oad(0xb8, 0); /* mov %eax, xxx */ 576 sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0); 577 greloc(cur_text_section, sym, 578 ind + 1, R_386_PC32); 579 oad(0xe8, -4); 633 gen_static_call(TOK___bound_local_delete); 580 634 o(0x585a); /* restore returned value, if any */ 581 635 } 582 636 #endif 637 638 /* align local size to word & save local variables */ 639 v = (-loc + 3) & -4; 640 641 #if USE_EBX 642 o(0x8b); 643 gen_modrm(TREG_EBX, VT_LOCAL, NULL, -(v+4)); 644 #endif 645 583 646 o(0xc9); /* leave */ 584 647 if (func_ret_sub == 0) { … … 589 652 g(func_ret_sub >> 8); 590 653 } 591 /* align local size to word & save local variables */592 593 v = (-loc + 3) & -4;594 654 saved_ind = ind; 595 655 ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; 596 656 #ifdef TCC_TARGET_PE 597 657 if (v >= 4096) { 598 Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);599 658 oad(0xb8, v); /* mov stacksize, %eax */ 600 oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */ 601 greloc(cur_text_section, sym, ind-4, R_386_PC32); 659 gen_static_call(TOK___chkstk); /* call __chkstk, (does the stackframe too) */ 602 660 } else 603 661 #endif … … 606 664 o(0xec81); /* sub esp, stacksize */ 607 665 gen_le32(v); 608 #if FUNC_PROLOG_SIZE == 10666 #ifdef TCC_TARGET_PE 609 667 o(0x90); /* adjust to FUNC_PROLOG_SIZE */ 610 668 #endif 611 669 } 670 o(0x53 * USE_EBX); /* push ebx */ 612 671 ind = saved_ind; 613 672 } … … 616 675 ST_FUNC int gjmp(int t) 617 676 { 618 return psym(0xe9, t);677 return gjmp2(0xe9, t); 619 678 } 620 679 … … 632 691 } 633 692 693 ST_FUNC void gtst_addr(int inv, int a) 694 { 695 int v = vtop->r & VT_VALMASK; 696 if (v == VT_CMP) { 697 inv ^= (vtop--)->c.i; 698 a -= ind + 2; 699 if (a == (char)a) { 700 g(inv - 32); 701 g(a); 702 } else { 703 g(0x0f); 704 oad(inv - 16, a - 4); 705 } 706 } else if ((v & ~1) == VT_JMP) { 707 if ((v & 1) != inv) { 708 gjmp_addr(a); 709 gsym(vtop->c.i); 710 } else { 711 gsym(vtop->c.i); 712 o(0x05eb); 713 gjmp_addr(a); 714 } 715 vtop--; 716 } 717 } 718 634 719 /* generate a test. set 'inv' to invert test. Stack entry is popped */ 635 720 ST_FUNC int gtst(int inv, int t) 636 721 { 637 int v , *p;638 639 v = vtop->r & VT_VALMASK;640 if (v == VT_CMP) {722 int v = vtop->r & VT_VALMASK; 723 if (nocode_wanted) { 724 ; 725 } else if (v == VT_CMP) { 641 726 /* fast case : can jump directly since flags are set */ 642 727 g(0x0f); 643 t = psym((vtop->c.i - 16) ^ inv, t);728 t = gjmp2((vtop->c.i - 16) ^ inv, t); 644 729 } else if (v == VT_JMP || v == VT_JMPI) { 645 730 /* && or || optimization */ 646 731 if ((v & 1) == inv) { 647 732 /* insert vtop->c jump list in t */ 648 p = &vtop->c.i; 649 while (*p != 0) 650 p = (int *)(cur_text_section->data + *p); 651 *p = t; 652 t = vtop->c.i; 733 uint32_t n1, n = vtop->c.i; 734 if (n) { 735 while ((n1 = read32le(cur_text_section->data + n))) 736 n = n1; 737 write32le(cur_text_section->data + n, t); 738 t = vtop->c.i; 739 } 653 740 } else { 654 741 t = gjmp(t); 655 742 gsym(vtop->c.i); 656 }657 } else {658 if (is_float(vtop->type.t) ||659 (vtop->type.t & VT_BTYPE) == VT_LLONG) {660 vpushi(0);661 gen_op(TOK_NE);662 }663 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {664 /* constant jmp optimization */665 if ((vtop->c.i != 0) != inv)666 t = gjmp(t);667 } else {668 v = gv(RC_INT);669 o(0x85);670 o(0xc0 + v * 9);671 g(0x0f);672 t = psym(0x85 ^ inv, t);673 743 } 674 744 } … … 695 765 if (c == (char)c) { 696 766 /* generate inc and dec for smaller code */ 697 if (c==1 && opc==0 ) {767 if (c==1 && opc==0 && op != TOK_ADDC1) { 698 768 o (0x40 | r); // inc 699 } else if (c==1 && opc==5 ) {769 } else if (c==1 && opc==5 && op != TOK_SUBC1) { 700 770 o (0x48 | r); // dec 701 771 } else { … … 789 859 vtop--; 790 860 save_reg(TREG_EDX); 861 /* save EAX too if used otherwise */ 862 save_reg_upstack(TREG_EAX, 1); 791 863 if (op == TOK_UMULL) { 792 864 o(0xf7); /* mul fr */ … … 816 888 817 889 /* generate a floating point operation 'v = t1 op t2' instruction. The 818 two operands are guarante d to have the same floating point type */890 two operands are guaranteed to have the same floating point type */ 819 891 /* XXX: need to use ST1 too */ 820 892 ST_FUNC void gen_opf(int op) … … 855 927 if (swapped) 856 928 o(0xc9d9); /* fxch %st(1) */ 857 o(0xe9da); /* fucompp */ 929 if (op == TOK_EQ || op == TOK_NE) 930 o(0xe9da); /* fucompp */ 931 else 932 o(0xd9de); /* fcompp */ 858 933 o(0xe0df); /* fnstsw %ax */ 859 934 if (op == TOK_EQ) { … … 901 976 } 902 977 ft = vtop->type.t; 903 fc = vtop->c. ul;978 fc = vtop->c.i; 904 979 if ((ft & VT_BTYPE) == VT_LDOUBLE) { 905 980 o(0xde); /* fxxxp %st, %st(1) */ … … 913 988 v1.type.t = VT_INT; 914 989 v1.r = VT_LOCAL | VT_LVAL; 915 v1.c. ul= fc;990 v1.c.i = fc; 916 991 load(r, &v1); 917 992 fc = 0; … … 959 1034 960 1035 /* convert fp to int 't' type */ 961 /* XXX: handle long long case */962 1036 ST_FUNC void gen_cvt_ftoi(int t) 963 1037 { 964 int r, r2, size; 965 Sym *sym; 966 CType ushort_type; 967 968 ushort_type.t = VT_SHORT | VT_UNSIGNED; 969 ushort_type.ref = 0; 970 971 gv(RC_FLOAT); 972 if (t != VT_INT) 973 size = 8; 974 else 975 size = 4; 976 977 o(0x2dd9); /* ldcw xxx */ 978 sym = external_global_sym(TOK___tcc_int_fpu_control, 979 &ushort_type, VT_LVAL); 980 greloc(cur_text_section, sym, 981 ind, R_386_32); 982 gen_le32(0); 983 984 oad(0xec81, size); /* sub $xxx, %esp */ 985 if (size == 4) 986 o(0x1cdb); /* fistpl */ 1038 int bt = vtop->type.t & VT_BTYPE; 1039 if (bt == VT_FLOAT) 1040 vpush_global_sym(&func_old_type, TOK___fixsfdi); 1041 else if (bt == VT_LDOUBLE) 1042 vpush_global_sym(&func_old_type, TOK___fixxfdi); 987 1043 else 988 o(0x3cdf); /* fistpll */ 989 o(0x24); 990 o(0x2dd9); /* ldcw xxx */ 991 sym = external_global_sym(TOK___tcc_fpu_control, 992 &ushort_type, VT_LVAL); 993 greloc(cur_text_section, sym, 994 ind, R_386_32); 995 gen_le32(0); 996 997 r = get_reg(RC_INT); 998 o(0x58 + r); /* pop r */ 999 if (size == 8) { 1000 if (t == VT_LLONG) { 1001 vtop->r = r; /* mark reg as used */ 1002 r2 = get_reg(RC_INT); 1003 o(0x58 + r2); /* pop r2 */ 1004 vtop->r2 = r2; 1005 } else { 1006 o(0x04c483); /* add $4, %esp */ 1007 } 1008 } 1009 vtop->r = r; 1044 vpush_global_sym(&func_old_type, TOK___fixdfdi); 1045 vswap(); 1046 gfunc_call(1); 1047 vpushi(0); 1048 vtop->r = REG_IRET; 1049 vtop->r2 = REG_LRET; 1010 1050 } 1011 1051 … … 1030 1070 ST_FUNC void gen_bounded_ptr_add(void) 1031 1071 { 1032 Sym *sym;1033 1034 1072 /* prepare fast i386 function call (args in eax and edx) */ 1035 1073 gv2(RC_EAX, RC_EDX); … … 1038 1076 save_regs(0); 1039 1077 /* do a fast function call */ 1040 sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0); 1041 greloc(cur_text_section, sym, 1042 ind + 1, R_386_PC32); 1043 oad(0xe8, -4); 1078 gen_static_call(TOK___bound_ptr_add); 1044 1079 /* returned pointer is in eax */ 1045 1080 vtop++; 1046 1081 vtop->r = TREG_EAX | VT_BOUNDED; 1047 1082 /* address of bounding function call point */ 1048 vtop->c. ul = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel));1083 vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel)); 1049 1084 } 1050 1085 … … 1053 1088 ST_FUNC void gen_bounded_ptr_deref(void) 1054 1089 { 1055 int func;1056 int size, align;1090 addr_t func; 1091 int size, align; 1057 1092 Elf32_Rel *rel; 1058 1093 Sym *sym; … … 1083 1118 /* patch relocation */ 1084 1119 /* XXX: find a better solution ? */ 1085 rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c. ul);1120 rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.i); 1086 1121 sym = external_global_sym(func, &func_old_type, 0); 1087 1122 if (!sym->c) … … 1091 1126 #endif 1092 1127 1128 /* Save the stack pointer onto the stack */ 1129 ST_FUNC void gen_vla_sp_save(int addr) { 1130 /* mov %esp,addr(%ebp)*/ 1131 o(0x89); 1132 gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr); 1133 } 1134 1135 /* Restore the SP from a location on the stack */ 1136 ST_FUNC void gen_vla_sp_restore(int addr) { 1137 o(0x8b); 1138 gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr); 1139 } 1140 1141 /* Subtract from the stack pointer, and push the resulting value onto the stack */ 1142 ST_FUNC void gen_vla_alloc(CType *type, int align) { 1143 #ifdef TCC_TARGET_PE 1144 /* alloca does more than just adjust %rsp on Windows */ 1145 vpush_global_sym(&func_old_type, TOK_alloca); 1146 vswap(); /* Move alloca ref past allocation size */ 1147 gfunc_call(1); 1148 #else 1149 int r; 1150 r = gv(RC_INT); /* allocation size */ 1151 /* sub r,%rsp */ 1152 o(0x2b); 1153 o(0xe0 | r); 1154 /* We align to 16 bytes rather than align */ 1155 /* and ~15, %esp */ 1156 o(0xf0e483); 1157 vpop(); 1158 #endif 1159 } 1160 1093 1161 /* end of X86 code generator */ 1094 1162 /*************************************************************/ -
EcnlProtoTool/trunk/tcc-0.9.27/i386-tok.h
r321 r331 92 92 DEF_ASM(gs) 93 93 DEF_ASM(st) 94 94 DEF_ASM(rip) 95 96 #ifdef TCC_TARGET_X86_64 97 /* The four low parts of sp/bp/si/di that exist only on 98 x86-64 (encoding aliased to ah,ch,dh,dh when not using REX). */ 99 DEF_ASM(spl) 100 DEF_ASM(bpl) 101 DEF_ASM(sil) 102 DEF_ASM(dil) 103 #endif 95 104 /* generic two operands */ 96 105 DEF_BWLX(mov) … … 127 136 DEF_BWLX(sar) 128 137 129 DEF_ASM(shldw) 130 DEF_ASM(shldl) 131 DEF_ASM(shld) 132 DEF_ASM(shrdw) 133 DEF_ASM(shrdl) 134 DEF_ASM(shrd) 138 DEF_WLX(shld) 139 DEF_WLX(shrd) 135 140 136 141 DEF_ASM(pushw) … … 151 156 DEF_BWL(out) 152 157 153 DEF_WL (movzb)158 DEF_WLX(movzb) 154 159 DEF_ASM(movzwl) 155 160 DEF_ASM(movsbw) … … 157 162 DEF_ASM(movswl) 158 163 #ifdef TCC_TARGET_X86_64 164 DEF_ASM(movsbq) 165 DEF_ASM(movswq) 166 DEF_ASM(movzwq) 159 167 DEF_ASM(movslq) 160 168 #endif … … 173 181 DEF_ASM(ljmp) 174 182 175 DEF_ASMTEST(j) 176 177 DEF_ASMTEST(set) 178 DEF_ASMTEST(cmov) 183 DEF_ASMTEST(j,) 184 185 DEF_ASMTEST(set,) 186 DEF_ASMTEST(set,b) 187 DEF_ASMTEST(cmov,) 179 188 180 189 DEF_WLX(bsf) … … 185 194 DEF_WLX(btc) 186 195 196 DEF_WLX(lar) 187 197 DEF_WLX(lsl) 188 198 … … 192 202 193 203 DEF_ASM(fcom) 194 DEF_ASM(fcom_1) /* non exist ant op, just to have a regular table */204 DEF_ASM(fcom_1) /* non existent op, just to have a regular table */ 195 205 DEF_FP1(com) 196 206 -
EcnlProtoTool/trunk/tcc-0.9.27/il-gen.c
r321 r331 18 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 #ifdef TARGET_DEFS_ONLY 20 21 #error this code has bit-rotted since 2003 21 22 22 23 /* number of available registers */ 23 24 #define NB_REGS 3 24 #define NB_ASM_REGS 8 // TODO:25 #define ELF_PAGE_SIZE 0x1000 // TODO:26 #define MAX_ALIGN 8 // TODO:27 #define R_DATA_32 R_386_32 // TODO:28 #define R_DATA_PTR R_386_32 // TODO:29 #define R_JMP_SLOT R_386_JMP_SLOT // TODO:30 #define R_COPY R_386_COPY // TODO:31 #define ELF_START_ADDR 0x08048000 // TODO:32 #define EM_TCC_TARGET 0xFF // TODO:33 25 34 26 /* a register can belong to several classes. The classes must be … … 52 44 }; 53 45 46 const int reg_classes[NB_REGS] = { 47 /* ST0 */ RC_ST | RC_ST0, 48 /* ST1 */ RC_ST | RC_ST1, 49 /* ST2 */ RC_ST, 50 }; 51 54 52 /* return registers for function */ 55 53 #define REG_IRET REG_ST0 /* single word int return register */ … … 58 56 59 57 /* defined if function parameters must be evaluated in reverse order */ 60 / /#define INVERT_FUNC_PARAMS58 /* #define INVERT_FUNC_PARAMS */ 61 59 62 60 /* defined if structures are passed as pointers. Otherwise structures 63 61 are directly pushed on stack. */ 64 / /#define FUNC_STRUCT_PARAM_AS_PTR62 /* #define FUNC_STRUCT_PARAM_AS_PTR */ 65 63 66 64 /* pointer size, in bytes */ … … 82 80 83 81 enum ILOPCodes { 84 #define ENUM_ILOPCODES_DEF85 82 #define OP(name, str, n) IL_OP_ ## name = n, 86 83 #include "il-opcodes.h" 87 84 #undef OP 88 #undef ENUM_ILOPCODES_DEF89 85 }; 90 86 91 /******************************************************/92 #else /* ! TARGET_DEFS_ONLY */93 /******************************************************/94 #include "tcc.h"95 96 const int reg_classes[NB_REGS] = {97 /* ST0 */ RC_ST | RC_ST0,98 /* ST1 */ RC_ST | RC_ST1,99 /* ST2 */ RC_ST,100 };101 102 87 char *il_opcodes_str[] = { 103 #define OP(name, str, n) /*[n] = */str,88 #define OP(name, str, n) [n] = str, 104 89 #include "il-opcodes.h" 105 90 #undef OP … … 115 100 static void out_byte(int c) 116 101 { 117 int ind1 = ind + 1; 118 if (ind1 > cur_text_section->data_allocated) 119 section_realloc(cur_text_section, ind1); 120 *(char *)(cur_text_section->data + ind) = c; 121 ind++; 102 *(char *)ind++ = c; 122 103 } 123 104 … … 219 200 case VT_FUNC: 220 201 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT); 221 if (s == NULL) 222 break; 223 il_type_to_str(buf, buf_size, s->type.t, varstr); 202 il_type_to_str(buf, buf_size, s->t, varstr); 224 203 pstrcat(buf, buf_size, "("); 225 204 sa = s->next; 226 205 while (sa != NULL) { 227 il_type_to_str(buf1, sizeof(buf1), sa->t ype.t, NULL);206 il_type_to_str(buf1, sizeof(buf1), sa->t, NULL); 228 207 pstrcat(buf, buf_size, buf1); 229 208 sa = sa->next; … … 235 214 case VT_PTR: 236 215 s = sym_find((unsigned)t >> VT_STRUCT_SHIFT); 237 if (s == NULL)238 break;239 216 pstrcpy(buf1, sizeof(buf1), "*"); 240 217 if (varstr) 241 218 pstrcat(buf1, sizeof(buf1), varstr); 242 il_type_to_str(buf, buf_size, s->t ype.t, buf1);219 il_type_to_str(buf, buf_size, s->t, buf1); 243 220 goto no_var; 244 221 } … … 250 227 } 251 228 252 #define Reloc void 229 253 230 /* patch relocation entry with value 'val' */ 254 231 void greloc_patch1(Reloc *p, int val) … … 285 262 v = sv->r & VT_VALMASK; 286 263 fc = sv->c.i; 287 ft = sv->t ype.t;264 ft = sv->t; 288 265 289 266 if (sv->r & VT_LVAL) { … … 364 341 v = sv->r & VT_VALMASK; 365 342 fc = sv->c.i; 366 ft = sv->t ype.t;343 ft = sv->t; 367 344 if (v == VT_LOCAL) { 368 345 if (fc >= ARG_BASE) { … … 412 389 void gfunc_param(GFuncContext *c) 413 390 { 414 if ((vtop->t ype.t& VT_BTYPE) == VT_STRUCT) {391 if ((vtop->t & VT_BTYPE) == VT_STRUCT) { 415 392 tcc_error("structures passed as value not handled yet"); 416 393 } else { … … 429 406 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { 430 407 /* XXX: more info needed from tcc */ 431 il_type_to_str(buf, sizeof(buf), vtop->t ype.t, "xxx");408 il_type_to_str(buf, sizeof(buf), vtop->t, "xxx"); 432 409 fprintf(il_outfile, " call %s\n", buf); 433 410 } else { 434 411 /* indirect call */ 435 412 gv(RC_INT); 436 il_type_to_str(buf, sizeof(buf), vtop->t ype.t, NULL);413 il_type_to_str(buf, sizeof(buf), vtop->t, NULL); 437 414 fprintf(il_outfile, " calli %s\n", buf); 438 415 } … … 461 438 462 439 sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT); 463 if (sym == NULL) 464 return; 440 func_call = sym->r; 465 441 466 442 addr = ARG_BASE; 467 443 /* if the function returns a structure, then add an 468 444 implicit pointer parameter */ 469 func_vt = sym->type; 470 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { 445 func_vt = sym->t; 446 func_var = (sym->c == FUNC_ELLIPSIS); 447 if ((func_vt & VT_BTYPE) == VT_STRUCT) { 471 448 func_vc = addr; 472 449 addr++; … … 474 451 /* define parameters */ 475 452 while ((sym = sym->next) != NULL) { 476 u = sym->t ype.t;453 u = sym->t; 477 454 sym_push(sym->v & ~SYM_FIELD, u, 478 455 VT_LOCAL | lvalue_type(sym->type.t), addr); … … 555 532 gsym(vtop->c.i); 556 533 } 557 } else {558 if (is_float(vtop->type.t)) {559 vpushi(0);560 gen_op(TOK_NE);561 }562 #define VT_FORWARD 0563 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) {564 /* constant jmp optimization */565 if ((vtop->c.i != 0) != inv)566 t = gjmp(t);567 } else {568 v = gv(RC_INT);569 t = out_opj(IL_OP_BRTRUE - inv, t);570 }571 534 } 572 535 vtop--; … … 640 603 641 604 /* generate a floating point operation 'v = t1 op t2' instruction. The 642 two operands are guarante d to have the same floating point type */605 two operands are guaranteed to have the same floating point type */ 643 606 void gen_opf(int op) 644 607 { … … 690 653 } 691 654 692 void ggoto(void) { }693 void gen_bounded_ptr_add(void) {}694 void gen_bounded_ptr_deref(int t) {}695 void gen_expr32(void) {}696 void asm_opcode(TCCState *s1, int opcode) {}697 void asm_compute_constraints(ASMOperand *operands,698 int nb_operands, int nb_outputs,699 const uint8_t *clobber_regs,700 int *pout_reg) {}701 void subst_asm_operand(CString *add_str,702 SValue *sv, int modifier) {}703 void asm_gen_code(ASMOperand *operands, int nb_operands,704 int nb_outputs, int is_output,705 uint8_t *clobber_regs,706 int out_reg) {}707 void asm_clobber(uint8_t *clobber_regs, const char *str) {}708 void gen_le32(int c) {}709 void g(int c) {}710 void gen_le16(int v) {}711 712 655 /* end of CIL code generator */ 713 656 /*************************************************************/ 714 #endif 715 /*************************************************************/ 657 -
EcnlProtoTool/trunk/tcc-0.9.27/il-opcodes.h
r321 r331 138 138 OP(CONV_R_UN, "conv.r.un", 0x76) 139 139 OP(ANN_DATA_S, "ann.data.s", 0x77) 140 #ifndef ENUM_ILOPCODES_DEF141 OP(0, NULL, 0x78)142 #endif143 140 OP(UNBOX, "unbox", 0x79) 144 141 OP(THROW, "throw", 0x7a) … … 183 180 OP(STELEM_R8, "stelem.r8", 0xa1) 184 181 OP(STELEM_REF, "stelem.ref", 0xa2) 185 #ifndef ENUM_ILOPCODES_DEF186 OP(0, NULL, 0xa3)187 OP(0, NULL, 0xa4)188 OP(0, NULL, 0xa5)189 OP(0, NULL, 0xa6)190 OP(0, NULL, 0xa7)191 OP(0, NULL, 0xa8)192 OP(0, NULL, 0xa9)193 OP(0, NULL, 0xaa)194 OP(0, NULL, 0xab)195 OP(0, NULL, 0xac)196 OP(0, NULL, 0xad)197 OP(0, NULL, 0xae)198 OP(0, NULL, 0xaf)199 OP(0, NULL, 0xb0)200 OP(0, NULL, 0xb1)201 OP(0, NULL, 0xb2)202 #endif203 182 OP(CONV_OVF_I1, "conv.ovf.i1", 0xb3) 204 183 OP(CONV_OVF_U1, "conv.ovf.u1", 0xb4) … … 209 188 OP(CONV_OVF_I8, "conv.ovf.i8", 0xb9) 210 189 OP(CONV_OVF_U8, "conv.ovf.u8", 0xba) 211 #ifndef ENUM_ILOPCODES_DEF212 OP(0, NULL, 0xbb)213 OP(0, NULL, 0xbc)214 OP(0, NULL, 0xbd)215 OP(0, NULL, 0xbe)216 OP(0, NULL, 0xbf)217 OP(0, NULL, 0xc0)218 OP(0, NULL, 0xc1)219 #endif220 190 OP(REFANYVAL, "refanyval", 0xc2) 221 191 OP(CKFINITE, "ckfinite", 0xc3) 222 #ifndef ENUM_ILOPCODES_DEF223 OP(0, NULL, 0xc4)224 OP(0, NULL, 0xc5)225 #endif226 192 OP(MKREFANY, "mkrefany", 0xc6) 227 193 OP(ANN_CALL, "ann.call", 0xc7) … … 251 217 OP(STIND_I, "stind.i", 0xdf) 252 218 OP(CONV_U, "conv.u", 0xe0) 253 #ifndef ENUM_ILOPCODES_DEF254 OP(0, NULL, 0xe1)255 OP(0, NULL, 0xe2)256 OP(0, NULL, 0xe3)257 OP(0, NULL, 0xe4)258 OP(0, NULL, 0xe5)259 OP(0, NULL, 0xe6)260 OP(0, NULL, 0xe7)261 OP(0, NULL, 0xe8)262 OP(0, NULL, 0xe9)263 OP(0, NULL, 0xea)264 OP(0, NULL, 0xeb)265 OP(0, NULL, 0xec)266 OP(0, NULL, 0xed)267 OP(0, NULL, 0xee)268 OP(0, NULL, 0xef)269 OP(0, NULL, 0xf0)270 OP(0, NULL, 0xf1)271 OP(0, NULL, 0xf2)272 OP(0, NULL, 0xf3)273 OP(0, NULL, 0xf4)274 OP(0, NULL, 0xf5)275 OP(0, NULL, 0xf6)276 OP(0, NULL, 0xf7)277 OP(0, NULL, 0xf8)278 OP(0, NULL, 0xf9)279 OP(0, NULL, 0xfa)280 OP(0, NULL, 0xfb)281 OP(0, NULL, 0xfc)282 OP(0, NULL, 0xfd)283 OP(0, NULL, 0xfe)284 OP(0, NULL, 0xff)285 #endif286 219 287 220 /* prefix instructions. we use an opcode >= 256 to ease coding */ … … 303 236 OP(STLOC, "stloc", 0x10e) 304 237 OP(LOCALLOC, "localloc", 0x10f) 305 #ifndef ENUM_ILOPCODES_DEF306 OP(0, NULL, 0x110)307 #endif308 238 OP(ENDFILTER, "endfilter", 0x111) 309 239 OP(UNALIGNED, "unaligned", 0x112) … … 316 246 OP(ANN_REF, "ann.ref", 0x119) 317 247 OP(RETHROW, "rethrow", 0x11a) 318 #ifndef ENUM_ILOPCODES_DEF319 OP(0, NULL, 0x11b)320 #endif321 248 OP(SIZEOF, "sizeof", 0x11c) 322 249 OP(REFANYTYPE, "refanytype", 0x11d) 323 #ifndef ENUM_ILOPCODES_DEF324 OP(0, NULL, 0x11e)325 OP(0, NULL, 0x11f)326 OP(0, NULL, 0x120)327 OP(0, NULL, 0x121)328 #endif329 250 OP(ANN_DATA, "ann.data", 0x122) 330 251 OP(ANN_ARG, "ann.arg", 0x123) -
EcnlProtoTool/trunk/tcc-0.9.27/include/float.h
r321 r331 28 28 29 29 /* horrible intel long double */ 30 #if def __i386__30 #if defined __i386__ || defined __x86_64__ 31 31 32 32 #define LDBL_MANT_DIG 64 -
EcnlProtoTool/trunk/tcc-0.9.27/include/stdarg.h
r321 r331 5 5 #ifndef _WIN64 6 6 7 typedef void *va_list; 7 //This should be in sync with the declaration on our lib/libtcc1.c 8 /* GCC compatible definition of va_list. */ 9 typedef struct { 10 unsigned int gp_offset; 11 unsigned int fp_offset; 12 union { 13 unsigned int overflow_offset; 14 char *overflow_arg_area; 15 }; 16 char *reg_save_area; 17 } __va_list_struct; 8 18 9 va_list __va_start(void *fp); 10 void *__va_arg(va_list ap, int arg_type, int size); 11 va_list __va_copy(va_list src); 12 void __va_end(va_list ap); 19 typedef __va_list_struct va_list[1]; 13 20 14 #define va_start(ap, last) ((ap) = __va_start(__builtin_frame_address(0))) 21 void __va_start(__va_list_struct *ap, void *fp); 22 void *__va_arg(__va_list_struct *ap, int arg_type, int size, int align); 23 24 #define va_start(ap, last) __va_start(ap, __builtin_frame_address(0)) 15 25 #define va_arg(ap, type) \ 16 (*(type *)(__va_arg(ap, __builtin_va_arg_types(type), sizeof(type)))) 17 #define va_copy(dest, src) ((dest) = __va_copy(src)) 18 #define va_end(ap) __va_end(ap) 26 (*(type *)(__va_arg(ap, __builtin_va_arg_types(type), sizeof(type), __alignof__(type)))) 27 #define va_copy(dest, src) (*(dest) = *(src)) 28 #define va_end(ap) 29 30 /* avoid conflicting definition for va_list on Macs. */ 31 #define _VA_LIST_T 19 32 20 33 #else /* _WIN64 */ 21 34 typedef char *va_list; 22 #define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+7)&~7) 23 #define va_arg(ap,type) (ap += (sizeof(type)+7)&~7, *(type *)(ap - ((sizeof(type)+7)&~7))) 35 #define va_start(ap,last) __builtin_va_start(ap,last) 36 #define va_arg(ap, t) ((sizeof(t) > 8 || (sizeof(t) & (sizeof(t) - 1))) \ 37 ? **(t **)((ap += 8) - 8) : *(t *)((ap += 8) - 8)) 38 #define va_copy(dest, src) ((dest) = (src)) 39 #define va_end(ap) 40 #endif 41 42 #elif __arm__ 43 typedef char *va_list; 44 #define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x) 45 #define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \ 46 & ~(_tcc_alignof(type) - 1)) 47 #define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3) 48 #define va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \ 49 &~3), *(type *)(ap - ((sizeof(type)+3)&~3))) 24 50 #define va_copy(dest, src) (dest) = (src) 25 51 #define va_end(ap) 26 #endif 52 53 #elif defined(__aarch64__) 54 typedef struct { 55 void *__stack; 56 void *__gr_top; 57 void *__vr_top; 58 int __gr_offs; 59 int __vr_offs; 60 } va_list; 61 #define va_start(ap, last) __va_start(ap, last) 62 #define va_arg(ap, type) __va_arg(ap, type) 63 #define va_end(ap) 64 #define va_copy(dest, src) ((dest) = (src)) 27 65 28 66 #else /* __i386__ */ -
EcnlProtoTool/trunk/tcc-0.9.27/include/stdbool.h
r321 r331 7 7 #define true 1 8 8 #define false 0 9 #define __bool_true_false_are_defined 1 9 10 10 11 #endif /* _STDBOOL_H */ -
EcnlProtoTool/trunk/tcc-0.9.27/include/stddef.h
r321 r331 14 14 typedef signed short int int16_t; 15 15 typedef signed int int32_t; 16 #ifdef __LP64__ 17 typedef signed long int int64_t; 18 #else 16 19 typedef signed long long int int64_t; 20 #endif 17 21 typedef unsigned char uint8_t; 18 22 typedef unsigned short int uint16_t; 19 23 typedef unsigned int uint32_t; 24 #ifdef __LP64__ 25 typedef unsigned long int uint64_t; 26 #else 20 27 typedef unsigned long long int uint64_t; 21 28 #endif 29 #endif 22 30 31 #ifndef NULL 23 32 #define NULL ((void*)0) 33 #endif 34 24 35 #define offsetof(type, field) ((size_t)&((type *)0)->field) 25 36 … … 27 38 28 39 #endif 40 41 /* Older glibc require a wint_t from <stddef.h> (when requested 42 by __need_wint_t, as otherwise stddef.h isn't allowed to 43 define this type). Note that this must be outside the normal 44 _STDDEF_H guard, so that it works even when we've included the file 45 already (without requiring wint_t). Some other libs define _WINT_T 46 if they've already provided that type, so we can use that as guard. 47 TCC defines __WINT_TYPE__ for us. */ 48 #if defined (__need_wint_t) 49 #ifndef _WINT_T 50 #define _WINT_T 51 typedef __WINT_TYPE__ wint_t; 52 #endif 53 #undef __need_wint_t 54 #endif -
EcnlProtoTool/trunk/tcc-0.9.27/lib/Makefile
r279 r331 5 5 TOP = .. 6 6 include $(TOP)/Makefile 7 VPATH = $(top_srcdir)/lib $(top_srcdir)/win32/lib 7 VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib 8 T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown) 9 X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-) 10 BIN = $(TOP)/$(X)libtcc1.a 8 11 9 ifndef TARGET 10 ifdef CONFIG_WIN64 11 TARGET = x86_64-win32 12 else 13 ifdef CONFIG_WIN32 14 TARGET = i386-win32 15 else 16 ifeq ($(ARCH),i386) 17 TARGET = i386 18 ifneq ($(TARGETOS),Darwin) 19 XCC = $(CC) 20 endif 21 else 22 ifeq ($(ARCH),x86-64) 23 TARGET = x86_64 24 ifneq ($(TARGETOS),Darwin) 25 XCC = $(CC) 26 endif 27 endif 28 endif 29 endif 30 endif 31 BCHECK_O = bcheck.o 12 XTCC ?= $(TOP)/$(X)tcc$(EXESUF) 13 XCC = $(XTCC) 14 XAR = $(XTCC) -ar 15 XFLAGS-unx = -B$(TOPSRC) 16 XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include 17 XFLAGS = $(XFLAGS$(XCFG)) 18 XCFG = $(or $(findstring -win,$T),-unx) 19 20 # in order to use gcc, tyoe: make <target>-libtcc1-usegcc=yes 21 arm-libtcc1-usegcc ?= no 22 23 ifeq "$($(T)-libtcc1-usegcc)" "yes" 24 XCC = $(CC) 25 XAR = $(AR) 26 XFLAGS = $(CFLAGS) -fPIC 32 27 endif 33 28 34 DIR = $(TARGET) 29 # only for native compiler 30 $(X)BCHECK_O = bcheck.o 35 31 36 native : ../libtcc1.a 37 cross : $(DIR)/libtcc1.a 38 39 native : TCC = $(TOP)/tcc$(EXESUF) 40 cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF) 41 42 I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O) 43 X86_64_O = libtcc1.o alloca86_64.o 44 WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o 45 WIN64_O = $(X86_64_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o 46 47 ifeq "$(TARGET)" "i386-win32" 48 OBJ = $(addprefix $(DIR)/,$(WIN32_O)) 49 TGT = -DTCC_TARGET_I386 -DTCC_TARGET_PE 50 XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include 51 XAR = $(DIR)/tiny_libmaker$(EXESUF) 52 else 53 ifeq "$(TARGET)" "x86_64-win32" 54 OBJ = $(addprefix $(DIR)/,$(WIN64_O)) 55 TGT = -DTCC_TARGET_X86_64 -DTCC_TARGET_PE 56 XCC = $(TCC) -B$(top_srcdir)/win32 -I$(top_srcdir)/include 57 XAR = $(DIR)/tiny_libmaker$(EXESUF) 58 else 59 ifeq "$(TARGET)" "i386" 60 OBJ = $(addprefix $(DIR)/,$(I386_O)) 61 TGT = -DTCC_TARGET_I386 62 XCC ?= $(TCC) -B$(TOP) 63 else 64 ifeq "$(TARGET)" "x86_64" 65 OBJ = $(addprefix $(DIR)/,$(X86_64_O)) 66 TGT = -DTCC_TARGET_X86_64 67 XCC ?= $(TCC) -B$(TOP) 68 else 69 $(error libtcc1.a not supported on target '$(TARGET)') 70 endif 71 endif 72 endif 73 endif 74 75 XFLAGS = $(CPPFLAGS) $(CFLAGS) $(TGT) 76 77 ifeq ($(TARGETOS),Darwin) 78 XAR = $(DIR)/tiny_libmaker$(EXESUF) 79 XFLAGS += -D_ANSI_SOURCE 32 ifeq ($(CONFIG_musl)$(CONFIG_uClibc),yes) 80 33 BCHECK_O = 81 34 endif 82 35 83 ifdef XAR84 AR = $(XAR) 36 ifdef CONFIG_OSX 37 XFLAGS += -D_ANSI_SOURCE 85 38 endif 86 39 87 $(DIR)/libtcc1.a ../libtcc1.a : $(OBJ) $(XAR) 88 $(AR) rcs $@ $(OBJ) 89 $(DIR)/%.o : %.c 40 I386_O = libtcc1.o alloca86.o alloca86-bt.o 41 X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o 42 ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o 43 ARM64_O = lib-arm64.o 44 WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o 45 46 OBJ-i386 = $(I386_O) $(BCHECK_O) 47 OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) 48 OBJ-x86_64-osx = $(X86_64_O) va_list.o 49 OBJ-i386-win32 = $(I386_O) chkstk.o bcheck.o $(WIN_O) 50 OBJ-x86_64-win32 = $(X86_64_O) chkstk.o bcheck.o $(WIN_O) 51 OBJ-arm64 = $(ARM64_O) 52 OBJ-arm = $(ARM_O) 53 OBJ-arm-fpa = $(ARM_O) 54 OBJ-arm-fpa-ld = $(ARM_O) 55 OBJ-arm-vfp = $(ARM_O) 56 OBJ-arm-eabi = $(ARM_O) 57 OBJ-arm-eabihf = $(ARM_O) 58 OBJ-arm-wince = $(ARM_O) $(WIN_O) 59 60 $(BIN) : $(patsubst %.o,$(X)%.o,$(OBJ-$T)) 61 $(XAR) rcs $@ $^ 62 63 $(X)%.o : %.c 90 64 $(XCC) -c $< -o $@ $(XFLAGS) 91 $(DIR)/%.o : %.S 65 66 $(X)%.o : %.S 92 67 $(XCC) -c $< -o $@ $(XFLAGS) 93 $(DIR)/%$(EXESUF) : $(TOP)/win32/tools/%.c94 $(CC) -o $@ $< $(XFLAGS) $(LDFLAGS)95 68 96 $(OBJ) $(XAR) : $(DIR)/exists 97 $(DIR)/exists : 98 mkdir -p $(DIR) 99 @echo $@ > $@ 69 $(X)crt1w.o : crt1.c 70 $(X)wincrt1w.o : wincrt1.c 100 71 101 72 clean : 102 rm - rfv i386-win32 x86_64-win32 i386 x86_6473 rm -f *.a *.o $(BIN) -
EcnlProtoTool/trunk/tcc-0.9.27/lib/alloca86-bt.S
- Property svn:keywords deleted
r279 r331 12 12 jz p6 13 13 14 #ifdef TCC_TARGET_PE14 #ifdef _WIN32 15 15 p4: 16 16 cmp $4096,%eax 17 jle p5 17 jbe p5 18 test %eax,-4096(%esp) 18 19 sub $4096,%esp 19 20 sub $4096,%eax 20 test %eax,(%esp)21 21 jmp p4 22 22 -
EcnlProtoTool/trunk/tcc-0.9.27/lib/alloca86.S
- Property svn:keywords deleted
r279 r331 11 11 jz p3 12 12 13 #ifdef TCC_TARGET_PE13 #ifdef _WIN32 14 14 p1: 15 15 cmp $4096,%eax 16 jle p2 16 jbe p2 17 test %eax,-4096(%esp) 17 18 sub $4096,%esp 18 19 sub $4096,%eax 19 test %eax,(%esp)20 20 jmp p1 21 21 p2: … … 29 29 ret 30 30 31 /* mark stack as nonexecutable */32 #if defined __ELF__ && defined __linux__33 .section .note.GNU-stack,"",@progbits34 #endif35 31 /* ---------------------------------------------- */ -
EcnlProtoTool/trunk/tcc-0.9.27/lib/alloca86_64.S
- Property svn:keywords deleted
r279 r331 6 6 alloca: 7 7 pop %rdx 8 #ifdef TCC_TARGET_PE8 #ifdef _WIN32 9 9 mov %rcx,%rax 10 10 #else … … 15 15 jz p3 16 16 17 #ifdef TCC_TARGET_PE17 #ifdef _WIN32 18 18 p1: 19 19 cmp $4096,%rax 20 jle p2 20 jbe p2 21 test %rax,-4096(%rsp) 21 22 sub $4096,%rsp 22 23 sub $4096,%rax 23 test %rax,(%rsp)24 24 jmp p1 25 25 p2: … … 28 28 sub %rax,%rsp 29 29 mov %rsp,%rax 30 #ifdef TCC_TARGET_PE31 add $32,%rax32 #endif33 34 30 p3: 35 31 push %rdx 36 32 ret 37 33 38 /* mark stack as nonexecutable */39 #if defined __ELF__ && defined __linux__40 .section .note.GNU-stack,"",@progbits41 #endif42 34 /* ---------------------------------------------- */ -
EcnlProtoTool/trunk/tcc-0.9.27/lib/bcheck.c
r321 r331 22 22 #include <stdarg.h> 23 23 #include <string.h> 24 #if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) \ 25 && !defined(__DragonFly__) && !defined(__OpenBSD__) 24 25 #if !defined(__FreeBSD__) \ 26 && !defined(__FreeBSD_kernel__) \ 27 && !defined(__DragonFly__) \ 28 && !defined(__OpenBSD__) \ 29 && !defined(__NetBSD__) 26 30 #include <malloc.h> 27 31 #endif 32 28 33 #if !defined(_WIN32) 29 34 #include <unistd.h> 30 35 #endif 31 36 32 //#define BOUND_DEBUG 37 /* #define BOUND_DEBUG */ 38 39 #ifdef BOUND_DEBUG 40 #define dprintf(a...) fprintf(a) 41 #else 42 #define dprintf(a...) 43 #endif 33 44 34 45 /* define so that bound array is static (faster, but use memory if 35 46 bound checking not used) */ 36 / /#define BOUND_STATIC47 /* #define BOUND_STATIC */ 37 48 38 49 /* use malloc hooks. Currently the code cannot be reliable if no hooks */ … … 40 51 #define HAVE_MEMALIGN 41 52 42 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \ 43 || defined(__DragonFly__) || defined(__dietlibc__) \ 44 || defined(__UCLIBC__) || defined(__OpenBSD__) \ 45 || defined(_WIN32) || defined(TCC_UCLIBC) 46 #warning Bound checking does not support malloc (etc.) in this environment. 53 #if defined(__FreeBSD__) \ 54 || defined(__FreeBSD_kernel__) \ 55 || defined(__DragonFly__) \ 56 || defined(__OpenBSD__) \ 57 || defined(__NetBSD__) \ 58 || defined(__dietlibc__) \ 59 || defined(_WIN32) 60 //#warning Bound checking does not support malloc (etc.) in this environment. 47 61 #undef CONFIG_TCC_MALLOC_HOOKS 48 62 #undef HAVE_MEMALIGN … … 51 65 #define BOUND_T1_BITS 13 52 66 #define BOUND_T2_BITS 11 53 #define BOUND_T3_BITS ( 32- BOUND_T1_BITS - BOUND_T2_BITS)54 55 #define BOUND_T1_SIZE (1 << BOUND_T1_BITS) 56 #define BOUND_T 2_SIZE (1 << BOUND_T2_BITS)57 #define BOUND_T 3_SIZE (1 << BOUND_T3_BITS)58 #define BOUND_ E_BITS 467 #define BOUND_T3_BITS (sizeof(size_t)*8 - BOUND_T1_BITS - BOUND_T2_BITS) 68 #define BOUND_E_BITS (sizeof(size_t)) 69 70 #define BOUND_T1_SIZE ((size_t)1 << BOUND_T1_BITS) 71 #define BOUND_T2_SIZE ((size_t)1 << BOUND_T2_BITS) 72 #define BOUND_T3_SIZE ((size_t)1 << BOUND_T3_BITS) 59 73 60 74 #define BOUND_T23_BITS (BOUND_T2_BITS + BOUND_T3_BITS) 61 #define BOUND_T23_SIZE ( 1 << BOUND_T23_BITS)75 #define BOUND_T23_SIZE ((size_t)1 << BOUND_T23_BITS) 62 76 63 77 … … 65 79 #define INVALID_POINTER ((void *)(-2)) 66 80 /* size of an empty region */ 67 #define EMPTY_SIZE 0xffffffff81 #define EMPTY_SIZE ((size_t)(-1)) 68 82 /* size of an invalid region */ 69 83 #define INVALID_SIZE 0 70 84 71 85 typedef struct BoundEntry { 72 unsigned longstart;73 unsigned longsize;86 size_t start; 87 size_t size; 74 88 struct BoundEntry *next; 75 unsigned longis_invalid; /* true if pointers outside region are invalid */89 size_t is_invalid; /* true if pointers outside region are invalid */ 76 90 } BoundEntry; 77 91 78 92 /* external interface */ 79 93 void __bound_init(void); 80 void __bound_new_region(void *p, unsigned longsize);94 void __bound_new_region(void *p, size_t size); 81 95 int __bound_delete_region(void *p); 82 96 97 #ifdef __attribute__ 98 /* an __attribute__ macro is defined in the system headers */ 99 #undef __attribute__ 100 #endif 83 101 #define FASTCALL __attribute__((regparm(3))) 84 102 … … 105 123 106 124 /* runtime error output */ 107 extern void rt_error( unsigned longpc, const char *fmt, ...);125 extern void rt_error(size_t pc, const char *fmt, ...); 108 126 109 127 #ifdef BOUND_STATIC … … 117 135 static BoundEntry *__bound_find_region(BoundEntry *e1, void *p) 118 136 { 119 unsigned longaddr, tmp;137 size_t addr, tmp; 120 138 BoundEntry *e; 121 139 122 140 e = e1; 123 141 while (e != NULL) { 124 addr = ( unsigned long)p;142 addr = (size_t)p; 125 143 addr -= e->start; 126 144 if (addr <= e->size) { … … 147 165 { 148 166 __bound_error_msg = fmt; 149 *(int *)0 = 0; /* force a runtime error */ 167 fprintf(stderr,"%s %s: %s\n", __FILE__, __FUNCTION__, fmt); 168 *(void **)0 = 0; /* force a runtime error */ 150 169 } 151 170 … … 157 176 /* return '(p + offset)' for pointer arithmetic (a pointer can reach 158 177 the end of a region in this case */ 159 void * FASTCALL __bound_ptr_add(void *p, int offset)160 { 161 unsigned long addr = (unsigned long)p;178 void * FASTCALL __bound_ptr_add(void *p, size_t offset) 179 { 180 size_t addr = (size_t)p; 162 181 BoundEntry *e; 163 #if defined(BOUND_DEBUG) 164 printf("add: 0x%x %d\n", (int)p, offset); 165 #endif 182 183 dprintf(stderr, "%s %s: %p %x\n", 184 __FILE__, __FUNCTION__, p, (unsigned)offset); 185 186 __bound_init(); 166 187 167 188 e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; … … 172 193 if (addr > e->size) { 173 194 e = __bound_find_region(e, p); 174 addr = ( unsigned long)p - e->start;195 addr = (size_t)p - e->start; 175 196 } 176 197 addr += offset; 177 if (addr > e->size) 198 if (addr >= e->size) { 199 fprintf(stderr,"%s %s: %p is outside of the region\n", 200 __FILE__, __FUNCTION__, p + offset); 178 201 return INVALID_POINTER; /* return an invalid pointer */ 202 } 179 203 return p + offset; 180 204 } … … 183 207 be strictly inside the region */ 184 208 #define BOUND_PTR_INDIR(dsize) \ 185 void * FASTCALL __bound_ptr_indir ## dsize (void *p, int offset)\209 void * FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ 186 210 { \ 187 unsigned long addr = (unsigned long)p;\211 size_t addr = (size_t)p; \ 188 212 BoundEntry *e; \ 189 213 \ 214 dprintf(stderr, "%s %s: %p %x start\n", \ 215 __FILE__, __FUNCTION__, p, (unsigned)offset); \ 216 \ 217 __bound_init(); \ 190 218 e = __bound_t1[addr >> (BOUND_T2_BITS + BOUND_T3_BITS)]; \ 191 219 e = (BoundEntry *)((char *)e + \ … … 195 223 if (addr > e->size) { \ 196 224 e = __bound_find_region(e, p); \ 197 addr = ( unsigned long)p - e->start;\225 addr = (size_t)p - e->start; \ 198 226 } \ 199 227 addr += offset + dsize; \ 200 if (addr > e->size) \ 228 if (addr > e->size) { \ 229 fprintf(stderr,"%s %s: %p is outside of the region\n", \ 230 __FILE__, __FUNCTION__, p + offset); \ 201 231 return INVALID_POINTER; /* return an invalid pointer */ \ 232 } \ 233 dprintf(stderr, "%s %s: return p+offset = %p\n", \ 234 __FILE__, __FUNCTION__, p + offset); \ 202 235 return p + offset; \ 203 236 } … … 210 243 BOUND_PTR_INDIR(16) 211 244 245 #if defined(__GNUC__) && (__GNUC__ >= 6) 246 /* 247 * At least gcc 6.2 complains when __builtin_frame_address is used with 248 * nonzero argument. 249 */ 250 #pragma GCC diagnostic push 251 #pragma GCC diagnostic ignored "-Wframe-address" 252 #endif 253 212 254 /* return the frame pointer of the caller */ 213 255 #define GET_CALLER_FP(fp)\ 214 256 {\ 215 fp = ( unsigned long)__builtin_frame_address(1);\257 fp = (size_t)__builtin_frame_address(1);\ 216 258 } 217 259 … … 219 261 void FASTCALL __bound_local_new(void *p1) 220 262 { 221 unsigned long addr, size, fp, *p = p1; 263 size_t addr, size, fp, *p = p1; 264 265 dprintf(stderr, "%s, %s start p1=%p\n", __FILE__, __FUNCTION__, p); 222 266 GET_CALLER_FP(fp); 223 267 for(;;) { … … 230 274 __bound_new_region((void *)addr, size); 231 275 } 276 dprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); 232 277 } 233 278 … … 235 280 void FASTCALL __bound_local_delete(void *p1) 236 281 { 237 unsigned longaddr, fp, *p = p1;282 size_t addr, fp, *p = p1; 238 283 GET_CALLER_FP(fp); 239 284 for(;;) { … … 247 292 } 248 293 294 #if defined(__GNUC__) && (__GNUC__ >= 6) 295 #pragma GCC diagnostic pop 296 #endif 297 249 298 static BoundEntry *__bound_new_page(void) 250 299 { 251 300 BoundEntry *page; 252 int i;301 size_t i; 253 302 254 303 page = libc_malloc(sizeof(BoundEntry) * BOUND_T2_SIZE); … … 278 327 } 279 328 280 static inline BoundEntry *get_page(int index)329 static BoundEntry *get_page(size_t index) 281 330 { 282 331 BoundEntry *page; 283 332 page = __bound_t1[index]; 284 if ( page == __bound_empty_t2 || page == __bound_invalid_t2) {333 if (!page || page == __bound_empty_t2 || page == __bound_invalid_t2) { 285 334 /* create a new page if necessary */ 286 335 page = __bound_new_page(); … … 291 340 292 341 /* mark a region as being invalid (can only be used during init) */ 293 static void mark_invalid( unsigned long addr, unsigned longsize)294 { 295 unsigned longstart, end;342 static void mark_invalid(size_t addr, size_t size) 343 { 344 size_t start, end; 296 345 BoundEntry *page; 297 int t1_start, t1_end, i, j, t2_start, t2_end;346 size_t t1_start, t1_end, i, j, t2_start, t2_end; 298 347 299 348 start = addr; … … 307 356 308 357 #if 0 309 printf("mark_invalid: start = %x %x\n", t2_start, t2_end);358 dprintf(stderr, "mark_invalid: start = %x %x\n", t2_start, t2_end); 310 359 #endif 311 360 … … 346 395 void __bound_init(void) 347 396 { 348 int i;397 size_t i; 349 398 BoundEntry *page; 350 unsigned long start, size; 351 int *p; 399 size_t start, size; 400 size_t *p; 401 402 static int inited; 403 if (inited) 404 return; 405 406 inited = 1; 407 408 dprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__); 352 409 353 410 /* save malloc hooks and install bound check hooks */ … … 375 432 376 433 /* invalid pointer zone */ 377 start = ( unsigned long)INVALID_POINTER & ~(BOUND_T23_SIZE - 1);434 start = (size_t)INVALID_POINTER & ~(BOUND_T23_SIZE - 1); 378 435 size = BOUND_T23_SIZE; 379 436 mark_invalid(start, size); … … 406 463 * start_brk from /proc/self/stat 407 464 */ 408 start = ( unsigned long)sbrk(0);465 start = (size_t)sbrk(0); 409 466 size = 128 * 0x100000; 410 467 mark_invalid(start, size); … … 412 469 413 470 /* add all static bound check values */ 414 p = ( int *)&__bounds_start;471 p = (size_t *)&__bounds_start; 415 472 while (p[0] != 0) { 416 473 __bound_new_region((void *)p[0], p[1]); 417 474 p += 2; 418 475 } 476 477 dprintf(stderr, "%s, %s() end\n\n", __FILE__, __FUNCTION__); 478 } 479 480 void __bound_main_arg(void **p) 481 { 482 void *start = p; 483 while (*p++); 484 485 dprintf(stderr, "%s, %s calling __bound_new_region(%p %x)\n", 486 __FILE__, __FUNCTION__, start, (unsigned)((void *)p - start)); 487 488 __bound_new_region(start, (void *) p - start); 419 489 } 420 490 421 491 void __bound_exit(void) 422 492 { 493 dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__); 423 494 restore_malloc_hooks(); 424 495 } 425 496 426 497 static inline void add_region(BoundEntry *e, 427 unsigned long start, unsigned longsize)498 size_t start, size_t size) 428 499 { 429 500 BoundEntry *e1; … … 445 516 446 517 /* create a new region. It should not already exist in the region list */ 447 void __bound_new_region(void *p, unsigned longsize)448 { 449 unsigned longstart, end;518 void __bound_new_region(void *p, size_t size) 519 { 520 size_t start, end; 450 521 BoundEntry *page, *e, *e2; 451 int t1_start, t1_end, i, t2_start, t2_end; 452 453 start = (unsigned long)p; 522 size_t t1_start, t1_end, i, t2_start, t2_end; 523 524 dprintf(stderr, "%s, %s(%p, %x) start\n", 525 __FILE__, __FUNCTION__, p, (unsigned)size); 526 527 __bound_init(); 528 529 start = (size_t)p; 454 530 end = start + size; 455 531 t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); … … 462 538 t2_end = (end >> (BOUND_T3_BITS - BOUND_E_BITS)) & 463 539 ((BOUND_T2_SIZE - 1) << BOUND_E_BITS); 464 #ifdef BOUND_DEBUG 465 printf("new %lx %lx %x %x %x %x\n", 466 start, end, t1_start, t1_end, t2_start, t2_end); 467 #endif 540 468 541 469 542 e = (BoundEntry *)((char *)page + t2_start); … … 507 580 add_region(e, start, size); 508 581 } 582 583 dprintf(stderr, "%s, %s end\n", __FILE__, __FUNCTION__); 509 584 } 510 585 511 586 /* delete a region */ 512 static inline void delete_region(BoundEntry *e, 513 void *p, unsigned long empty_size) 514 { 515 unsigned long addr; 587 static inline void delete_region(BoundEntry *e, void *p, size_t empty_size) 588 { 589 size_t addr; 516 590 BoundEntry *e1; 517 591 518 addr = ( unsigned long)p;592 addr = (size_t)p; 519 593 addr -= e->start; 520 594 if (addr <= e->size) { … … 540 614 if (e == NULL) 541 615 break; 542 addr = ( unsigned long)p - e->start;616 addr = (size_t)p - e->start; 543 617 if (addr <= e->size) { 544 618 /* found: remove entry */ … … 555 629 int __bound_delete_region(void *p) 556 630 { 557 unsigned longstart, end, addr, size, empty_size;631 size_t start, end, addr, size, empty_size; 558 632 BoundEntry *page, *e, *e2; 559 int t1_start, t1_end, t2_start, t2_end, i; 560 561 start = (unsigned long)p; 633 size_t t1_start, t1_end, t2_start, t2_end, i; 634 635 dprintf(stderr, "%s %s() start\n", __FILE__, __FUNCTION__); 636 637 __bound_init(); 638 639 start = (size_t)p; 562 640 t1_start = start >> (BOUND_T2_BITS + BOUND_T3_BITS); 563 641 t2_start = (start >> (BOUND_T3_BITS - BOUND_E_BITS)) & … … 571 649 e = __bound_find_region(e, p); 572 650 /* test if invalid region */ 573 if (e->size == EMPTY_SIZE || ( unsigned long)p != e->start)651 if (e->size == EMPTY_SIZE || (size_t)p != e->start) 574 652 return -1; 575 653 /* compute the size we put in invalid regions */ … … 625 703 delete_region(e, p, empty_size); 626 704 } 705 706 dprintf(stderr, "%s %s() end\n", __FILE__, __FUNCTION__); 707 627 708 return 0; 628 709 } 629 710 630 711 /* return the size of the region starting at p, or EMPTY_SIZE if non 631 exist ant region. */632 static unsigned longget_region_size(void *p)633 { 634 unsigned long addr = (unsigned long)p;712 existent region. */ 713 static size_t get_region_size(void *p) 714 { 715 size_t addr = (size_t)p; 635 716 BoundEntry *e; 636 717 … … 642 723 if (addr > e->size) 643 724 e = __bound_find_region(e, p); 644 if (e->start != ( unsigned long)p)725 if (e->start != (size_t)p) 645 726 return EMPTY_SIZE; 646 727 return e->size; … … 710 791 if (!ptr) 711 792 return NULL; 793 794 dprintf(stderr, "%s, %s calling __bound_new_region(%p, %x)\n", 795 __FILE__, __FUNCTION__, ptr, (unsigned)size); 796 712 797 __bound_new_region(ptr, size); 713 798 return ptr; … … 739 824 if (!ptr) 740 825 return NULL; 826 827 dprintf(stderr, "%s, %s calling __bound_new_region(%p, %x)\n", 828 __FILE__, __FUNCTION__, ptr, (unsigned)size); 829 741 830 __bound_new_region(ptr, size); 742 831 return ptr; … … 756 845 { 757 846 void *ptr1; 758 int old_size;847 size_t old_size; 759 848 760 849 if (size == 0) { … … 791 880 { 792 881 BoundEntry *page, *e; 793 int i, j;794 795 printf("region dump:\n");882 size_t i, j; 883 884 fprintf(stderr, "region dump:\n"); 796 885 for(i=0;i<BOUND_T1_SIZE;i++) { 797 886 page = __bound_t1[i]; … … 800 889 /* do not print invalid or empty entries */ 801 890 if (e->size != EMPTY_SIZE && e->start != 0) { 802 printf("%08x:",891 fprintf(stderr, "%08x:", 803 892 (i << (BOUND_T2_BITS + BOUND_T3_BITS)) + 804 893 (j << BOUND_T3_BITS)); 805 894 do { 806 printf(" %08lx:%08lx", e->start, e->start + e->size);895 fprintf(stderr, " %08lx:%08lx", e->start, e->start + e->size); 807 896 e = e->next; 808 897 } while (e != NULL); 809 printf("\n");898 fprintf(stderr, "\n"); 810 899 } 811 900 } … … 821 910 if (size == 0) 822 911 return; 823 p = __bound_ptr_add((void *)p, size );912 p = __bound_ptr_add((void *)p, size - 1); 824 913 if (p == INVALID_POINTER) 825 914 bound_error("invalid pointer"); … … 828 917 void *__bound_memcpy(void *dst, const void *src, size_t size) 829 918 { 919 void* p; 920 921 dprintf(stderr, "%s %s: start, dst=%p src=%p size=%x\n", 922 __FILE__, __FUNCTION__, dst, src, (unsigned)size); 923 830 924 __bound_check(dst, size); 831 925 __bound_check(src, size); … … 833 927 if (src >= dst && src < dst + size) 834 928 bound_error("overlapping regions in memcpy()"); 835 return memcpy(dst, src, size); 929 930 p = memcpy(dst, src, size); 931 932 dprintf(stderr, "%s %s: end, p=%p\n", __FILE__, __FUNCTION__, p); 933 return p; 836 934 } 837 935 … … 853 951 { 854 952 const char *p; 855 int len;953 size_t len; 856 954 857 955 len = 0; … … 869 967 char *__bound_strcpy(char *dst, const char *src) 870 968 { 871 int len; 969 size_t len; 970 void *p; 971 972 dprintf(stderr, "%s %s: strcpy start, dst=%p src=%p\n", 973 __FILE__, __FUNCTION__, dst, src); 872 974 len = __bound_strlen(src); 873 return __bound_memcpy(dst, src, len + 1); 874 } 875 975 p = __bound_memcpy(dst, src, len + 1); 976 dprintf(stderr, "%s %s: strcpy end, p = %p\n", 977 __FILE__, __FUNCTION__, p); 978 return p; 979 } -
EcnlProtoTool/trunk/tcc-0.9.27/lib/libtcc1.c
r321 r331 104 104 union float_long { 105 105 float f; 106 longl;106 unsigned int l; 107 107 }; 108 108 109 109 /* XXX: we don't support several builtin supports for now */ 110 #if ndef __x86_64__110 #if !defined __x86_64__ && !defined __arm__ 111 111 112 112 /* XXX: use gcc/tcc intrinsic ? */ 113 #if defined (__i386__)113 #if defined __i386__ 114 114 #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ 115 115 __asm__ ("subl %5,%1\n\tsbbl %3,%0" \ … … 479 479 } 480 480 481 #if defined(__i386__)482 /* FPU control word for rounding to nearest mode */483 unsigned short __tcc_fpu_control = 0x137f;484 /* FPU control word for round to zero mode for int conversion */485 unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00;486 #endif487 488 481 #endif /* !__x86_64__ */ 489 482 … … 558 551 } 559 552 553 long long __fixsfdi (float a1) 554 { 555 long long ret; int s; 556 ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1); 557 return s ? ret : -ret; 558 } 559 560 560 unsigned long long __fixunsdfdi (double a1) 561 561 { … … 583 583 } 584 584 585 long long __fixdfdi (double a1) 586 { 587 long long ret; int s; 588 ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1); 589 return s ? ret : -ret; 590 } 591 592 #ifndef __arm__ 585 593 unsigned long long __fixunsxfdi (long double a1) 586 594 { … … 606 614 } 607 615 608 #if defined(__x86_64__) && !defined(_WIN64) 609 610 /* helper functions for stdarg.h */ 611 612 #include <stdlib.h> 613 #ifndef __TINYC__ 614 /* gives "incompatible types for redefinition of __va_arg" below */ 615 #include <stdio.h> 616 #endif 617 618 enum __va_arg_type { 619 __va_gen_reg, __va_float_reg, __va_stack 620 }; 621 622 /* GCC compatible definition of va_list. */ 623 struct __va_list_struct { 624 unsigned int gp_offset; 625 unsigned int fp_offset; 626 union { 627 unsigned int overflow_offset; 628 char *overflow_arg_area; 629 }; 630 char *reg_save_area; 631 }; 632 633 void *__va_start(void *fp) 634 { 635 struct __va_list_struct *ap = 636 (struct __va_list_struct *)malloc(sizeof(struct __va_list_struct)); 637 *ap = *(struct __va_list_struct *)((char *)fp - 16); 638 ap->overflow_arg_area = (char *)fp + ap->overflow_offset; 639 ap->reg_save_area = (char *)fp - 176 - 16; 640 return ap; 641 } 642 643 void *__va_arg(struct __va_list_struct *ap, 644 enum __va_arg_type arg_type, 645 int size) 646 { 647 size = (size + 7) & ~7; 648 switch (arg_type) { 649 case __va_gen_reg: 650 if (ap->gp_offset < 48) { 651 ap->gp_offset += 8; 652 return ap->reg_save_area + ap->gp_offset - 8; 653 } 654 size = 8; 655 goto use_overflow_area; 656 657 case __va_float_reg: 658 if (ap->fp_offset < 128 + 48) { 659 ap->fp_offset += 16; 660 return ap->reg_save_area + ap->fp_offset - 16; 661 } 662 size = 8; 663 goto use_overflow_area; 664 665 case __va_stack: 666 use_overflow_area: 667 ap->overflow_arg_area += size; 668 return ap->overflow_arg_area - size; 669 670 default: 671 #ifndef __TINYC__ 672 fprintf(stderr, "unknown ABI type for __va_arg\n"); 673 #endif 674 abort(); 675 } 676 } 677 678 void *__va_copy(struct __va_list_struct *src) 679 { 680 struct __va_list_struct *dest = 681 (struct __va_list_struct *)malloc(sizeof(struct __va_list_struct)); 682 *dest = *src; 683 return dest; 684 } 685 686 void __va_end(struct __va_list_struct *ap) 687 { 688 free(ap); 689 } 690 691 #endif /* __x86_64__ */ 616 long long __fixxfdi (long double a1) 617 { 618 long long ret; int s; 619 ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1); 620 return s ? ret : -ret; 621 } 622 #endif /* !ARM */ -
EcnlProtoTool/trunk/tcc-0.9.27/libtcc.c
r321 r331 1 1 /* 2 2 * TCC - Tiny C Compiler 3 * 3 * 4 4 * Copyright (c) 2001-2004 Fabrice Bellard 5 5 * … … 33 33 ST_DATA struct TCCState *tcc_state; 34 34 35 static int nb_states; 36 35 37 /********************************************************/ 36 38 37 #if defONE_SOURCE39 #if ONE_SOURCE 38 40 #include "tccpp.c" 39 41 #include "tccgen.c" … … 42 44 #ifdef TCC_TARGET_I386 43 45 #include "i386-gen.c" 46 #include "i386-link.c" 47 #include "i386-asm.c" 44 48 #endif 45 49 #ifdef TCC_TARGET_ARM 46 50 #include "arm-gen.c" 51 #include "arm-link.c" 52 #include "arm-asm.c" 53 #endif 54 #ifdef TCC_TARGET_ARM64 55 #include "arm64-gen.c" 56 #include "arm64-link.c" 47 57 #endif 48 58 #ifdef TCC_TARGET_C67 49 59 #include "c67-gen.c" 60 #include "c67-link.c" 61 #include "tcccoff.c" 50 62 #endif 51 63 #ifdef TCC_TARGET_X86_64 52 64 #include "x86_64-gen.c" 53 #endif 54 #ifdef TCC_TARGET_IL 55 #include "il-gen.c" 65 #include "x86_64-link.c" 66 #include "i386-asm.c" 56 67 #endif 57 68 #ifdef CONFIG_TCC_ASM 58 69 #include "tccasm.c" 59 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_6460 #include "i386-asm.c"61 #endif62 #endif63 #ifdef TCC_TARGET_COFF64 #include "tcccoff.c"65 70 #endif 66 71 #ifdef TCC_TARGET_PE … … 82 87 83 88 /********************************************************/ 84 85 89 #ifdef _WIN32 86 char *normalize_slashes(char *path)90 ST_FUNC char *normalize_slashes(char *path) 87 91 { 88 92 char *p; … … 93 97 } 94 98 95 #if 096 99 static HMODULE tcc_module; 97 100 … … 102 105 GetModuleFileNameA(tcc_module, path, sizeof path); 103 106 p = tcc_basename(normalize_slashes(strlwr(path))); 104 if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5)) 105 p -= 5; 106 else if (p > path) 107 p--; 107 if (p > path) 108 --p; 108 109 *p = 0; 109 110 tcc_set_lib_path(s, path); … … 119 120 #endif 120 121 121 #ifndef CONFIG_TCC_STATIC122 void dlclose(void *p)123 {124 FreeLibrary((HMODULE)p);125 }126 #endif127 #else128 extern void tcc_set_lib_path_w32(TCCState *s);129 extern void dlclose(void *p);130 #endif131 132 122 #ifdef LIBTCC_AS_DLL 133 BOOL WINAPI DllMain (H ANDLE hDll, DWORD dwReason, LPVOID lpReserved)123 BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved) 134 124 { 135 125 if (DLL_PROCESS_ATTACH == dwReason) … … 142 132 /********************************************************/ 143 133 /* copy a string and truncate it. */ 144 PUB_FUNC char *pstrcpy(char *buf, int buf_size, const char *s)134 ST_FUNC char *pstrcpy(char *buf, int buf_size, const char *s) 145 135 { 146 136 char *q, *q_end; … … 162 152 163 153 /* strcat and truncate. */ 164 PUB_FUNC char *pstrcat(char *buf, int buf_size, const char *s)154 ST_FUNC char *pstrcat(char *buf, int buf_size, const char *s) 165 155 { 166 156 int len; 167 157 len = strlen(buf); 168 if (len < buf_size) 158 if (len < buf_size) 169 159 pstrcpy(buf + len, buf_size - len, s); 170 160 return buf; 171 161 } 172 162 173 PUB_FUNC char *pstrncpy(char *out, const char *in, size_t num)163 ST_FUNC char *pstrncpy(char *out, const char *in, size_t num) 174 164 { 175 165 memcpy(out, in, num); … … 205 195 #undef realloc 206 196 207 #ifdef MEM_DEBUG 208 ST_DATA int mem_cur_size; 209 ST_DATA int mem_max_size; 210 unsigned malloc_usable_size(void*); 211 #endif 197 #ifndef MEM_DEBUG 212 198 213 199 PUB_FUNC void tcc_free(void *ptr) 214 200 { 215 #ifdef MEM_DEBUG 216 mem_cur_size -= malloc_usable_size(ptr); 217 #endif 218 free(ptr); 201 free(ptr); 219 202 } 220 203 … … 224 207 ptr = malloc(size); 225 208 if (!ptr && size) 226 tcc_error("memory full"); 227 #ifdef MEM_DEBUG 228 mem_cur_size += malloc_usable_size(ptr); 229 if (mem_cur_size > mem_max_size) 230 mem_max_size = mem_cur_size; 231 #endif 209 tcc_error("memory full (malloc)"); 232 210 return ptr; 233 211 } … … 244 222 { 245 223 void *ptr1; 246 #ifdef MEM_DEBUG247 mem_cur_size -= malloc_usable_size(ptr);248 #endif249 224 ptr1 = realloc(ptr, size); 250 225 if (!ptr1 && size) 251 tcc_error("memory full"); 252 #ifdef MEM_DEBUG 253 /* NOTE: count not correct if alloc error, but not critical */ 254 mem_cur_size += malloc_usable_size(ptr1); 255 if (mem_cur_size > mem_max_size) 256 mem_max_size = mem_cur_size; 257 #endif 226 tcc_error("memory full (realloc)"); 258 227 return ptr1; 259 228 } … … 267 236 } 268 237 269 PUB_FUNC void tcc_memstats(void) 270 { 271 #ifdef MEM_DEBUG 272 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size); 273 #endif 274 } 238 PUB_FUNC void tcc_memcheck(void) 239 { 240 } 241 242 #else 243 244 #define MEM_DEBUG_MAGIC1 0xFEEDDEB1 245 #define MEM_DEBUG_MAGIC2 0xFEEDDEB2 246 #define MEM_DEBUG_MAGIC3 0xFEEDDEB3 247 #define MEM_DEBUG_FILE_LEN 40 248 #define MEM_DEBUG_CHECK3(header) \ 249 ((mem_debug_header_t*)((char*)header + header->size))->magic3 250 #define MEM_USER_PTR(header) \ 251 ((char *)header + offsetof(mem_debug_header_t, magic3)) 252 #define MEM_HEADER_PTR(ptr) \ 253 (mem_debug_header_t *)((char*)ptr - offsetof(mem_debug_header_t, magic3)) 254 255 struct mem_debug_header { 256 unsigned magic1; 257 unsigned size; 258 struct mem_debug_header *prev; 259 struct mem_debug_header *next; 260 int line_num; 261 char file_name[MEM_DEBUG_FILE_LEN + 1]; 262 unsigned magic2; 263 ALIGNED(16) unsigned magic3; 264 }; 265 266 typedef struct mem_debug_header mem_debug_header_t; 267 268 static mem_debug_header_t *mem_debug_chain; 269 static unsigned mem_cur_size; 270 static unsigned mem_max_size; 271 272 static mem_debug_header_t *malloc_check(void *ptr, const char *msg) 273 { 274 mem_debug_header_t * header = MEM_HEADER_PTR(ptr); 275 if (header->magic1 != MEM_DEBUG_MAGIC1 || 276 header->magic2 != MEM_DEBUG_MAGIC2 || 277 MEM_DEBUG_CHECK3(header) != MEM_DEBUG_MAGIC3 || 278 header->size == (unsigned)-1) { 279 fprintf(stderr, "%s check failed\n", msg); 280 if (header->magic1 == MEM_DEBUG_MAGIC1) 281 fprintf(stderr, "%s:%u: block allocated here.\n", 282 header->file_name, header->line_num); 283 exit(1); 284 } 285 return header; 286 } 287 288 PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line) 289 { 290 int ofs; 291 mem_debug_header_t *header; 292 293 header = malloc(sizeof(mem_debug_header_t) + size); 294 if (!header) 295 tcc_error("memory full (malloc)"); 296 297 header->magic1 = MEM_DEBUG_MAGIC1; 298 header->magic2 = MEM_DEBUG_MAGIC2; 299 header->size = size; 300 MEM_DEBUG_CHECK3(header) = MEM_DEBUG_MAGIC3; 301 header->line_num = line; 302 ofs = strlen(file) - MEM_DEBUG_FILE_LEN; 303 strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN); 304 header->file_name[MEM_DEBUG_FILE_LEN] = 0; 305 306 header->next = mem_debug_chain; 307 header->prev = NULL; 308 if (header->next) 309 header->next->prev = header; 310 mem_debug_chain = header; 311 312 mem_cur_size += size; 313 if (mem_cur_size > mem_max_size) 314 mem_max_size = mem_cur_size; 315 316 return MEM_USER_PTR(header); 317 } 318 319 PUB_FUNC void tcc_free_debug(void *ptr) 320 { 321 mem_debug_header_t *header; 322 if (!ptr) 323 return; 324 header = malloc_check(ptr, "tcc_free"); 325 mem_cur_size -= header->size; 326 header->size = (unsigned)-1; 327 if (header->next) 328 header->next->prev = header->prev; 329 if (header->prev) 330 header->prev->next = header->next; 331 if (header == mem_debug_chain) 332 mem_debug_chain = header->next; 333 free(header); 334 } 335 336 PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line) 337 { 338 void *ptr; 339 ptr = tcc_malloc_debug(size,file,line); 340 memset(ptr, 0, size); 341 return ptr; 342 } 343 344 PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line) 345 { 346 mem_debug_header_t *header; 347 int mem_debug_chain_update = 0; 348 if (!ptr) 349 return tcc_malloc_debug(size, file, line); 350 header = malloc_check(ptr, "tcc_realloc"); 351 mem_cur_size -= header->size; 352 mem_debug_chain_update = (header == mem_debug_chain); 353 header = realloc(header, sizeof(mem_debug_header_t) + size); 354 if (!header) 355 tcc_error("memory full (realloc)"); 356 header->size = size; 357 MEM_DEBUG_CHECK3(header) = MEM_DEBUG_MAGIC3; 358 if (header->next) 359 header->next->prev = header; 360 if (header->prev) 361 header->prev->next = header; 362 if (mem_debug_chain_update) 363 mem_debug_chain = header; 364 mem_cur_size += size; 365 if (mem_cur_size > mem_max_size) 366 mem_max_size = mem_cur_size; 367 return MEM_USER_PTR(header); 368 } 369 370 PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line) 371 { 372 char *ptr; 373 ptr = tcc_malloc_debug(strlen(str) + 1, file, line); 374 strcpy(ptr, str); 375 return ptr; 376 } 377 378 PUB_FUNC void tcc_memcheck(void) 379 { 380 if (mem_cur_size) { 381 mem_debug_header_t *header = mem_debug_chain; 382 fprintf(stderr, "MEM_DEBUG: mem_leak= %d bytes, mem_max_size= %d bytes\n", 383 mem_cur_size, mem_max_size); 384 while (header) { 385 fprintf(stderr, "%s:%u: error: %u bytes leaked\n", 386 header->file_name, header->line_num, header->size); 387 header = header->next; 388 } 389 #if MEM_DEBUG-0 == 2 390 exit(2); 391 #endif 392 } 393 } 394 #endif /* MEM_DEBUG */ 275 395 276 396 #define free(p) use_tcc_free(p) … … 281 401 /* dynarrays */ 282 402 283 ST_FUNC void dynarray_add(void * **ptab, int *nb_ptr, void *data)403 ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data) 284 404 { 285 405 int nb, nb_alloc; 286 406 void **pp; 287 407 288 408 nb = *nb_ptr; 289 pp = * ptab;409 pp = *(void ***)ptab; 290 410 /* every power of two we double array size */ 291 411 if ((nb & (nb - 1)) == 0) { … … 295 415 nb_alloc = nb * 2; 296 416 pp = tcc_realloc(pp, nb_alloc * sizeof(void *)); 297 * ptab = pp;417 *(void***)ptab = pp; 298 418 } 299 419 pp[nb++] = data; … … 311 431 } 312 432 313 static void tcc_split_path(TCCState *s, void * **p_ary, int *p_nb_ary, const char *in)433 static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *in) 314 434 { 315 435 const char *p; … … 319 439 320 440 cstr_new(&str); 321 for (p = in; c = *p, c != '\0' && c != PATHSEP ; ++p) {441 for (p = in; c = *p, c != '\0' && c != PATHSEP[0]; ++p) { 322 442 if (c == '{' && p[1] && p[2] == '}') { 323 443 c = p[1], p += 2; 324 444 if (c == 'B') 325 cstr_cat(&str, s->tcc_lib_path );445 cstr_cat(&str, s->tcc_lib_path, -1); 326 446 } else { 327 447 cstr_ccat(&str, c); 328 448 } 329 449 } 330 cstr_ccat(&str, '\0'); 331 dynarray_add(p_ary, p_nb_ary, str.data); 450 if (str.size) { 451 cstr_ccat(&str, '\0'); 452 dynarray_add(p_ary, p_nb_ary, tcc_strdup(str.data)); 453 } 454 cstr_free(&str); 332 455 in = p+1; 333 456 } while (*p); 334 }335 336 /********************************************************/337 338 ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)339 {340 Section *sec;341 342 sec = tcc_mallocz(sizeof(Section) + strlen(name));343 strcpy(sec->name, name);344 sec->sh_type = sh_type;345 sec->sh_flags = sh_flags;346 switch(sh_type) {347 case SHT_HASH:348 case SHT_REL:349 case SHT_RELA:350 case SHT_DYNSYM:351 case SHT_SYMTAB:352 case SHT_DYNAMIC:353 sec->sh_addralign = 4;354 break;355 case SHT_STRTAB:356 sec->sh_addralign = 1;357 break;358 default:359 sec->sh_addralign = 32; /* default conservative alignment */360 break;361 }362 363 if (sh_flags & SHF_PRIVATE) {364 dynarray_add((void ***)&s1->priv_sections, &s1->nb_priv_sections, sec);365 } else {366 sec->sh_num = s1->nb_sections;367 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);368 }369 370 return sec;371 }372 373 static void free_section(Section *s)374 {375 tcc_free(s->data);376 }377 378 /* realloc section and set its content to zero */379 ST_FUNC void section_realloc(Section *sec, unsigned long new_size)380 {381 unsigned long size;382 unsigned char *data;383 384 size = sec->data_allocated;385 if (size == 0)386 size = 1;387 while (size < new_size)388 size = size * 2;389 data = tcc_realloc(sec->data, size);390 memset(data + sec->data_allocated, 0, size - sec->data_allocated);391 sec->data = data;392 sec->data_allocated = size;393 }394 395 /* reserve at least 'size' bytes in section 'sec' from396 sec->data_offset. */397 ST_FUNC void *section_ptr_add(Section *sec, unsigned long size)398 {399 unsigned long offset, offset1;400 401 offset = sec->data_offset;402 offset1 = offset + size;403 if (offset1 > sec->data_allocated)404 section_realloc(sec, offset1);405 sec->data_offset = offset1;406 return sec->data + offset;407 }408 409 /* reserve at least 'size' bytes from section start */410 ST_FUNC void section_reserve(Section *sec, unsigned long size)411 {412 if (size > sec->data_allocated)413 section_realloc(sec, size);414 if (size > sec->data_offset)415 sec->data_offset = size;416 }417 418 /* return a reference to a section, and create it if it does not419 exists */420 ST_FUNC Section *find_section(TCCState *s1, const char *name)421 {422 Section *sec;423 int i;424 for(i = 1; i < s1->nb_sections; i++) {425 sec = s1->sections[i];426 if (!strcmp(name, sec->name))427 return sec;428 }429 /* sections are created as PROGBITS */430 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);431 }432 433 /* update sym->c so that it points to an external symbol in section434 'section' with value 'value' */435 ST_FUNC void put_extern_sym2(Sym *sym, Section *section,436 addr_t value, unsigned long size,437 int can_add_underscore)438 {439 int sym_type, sym_bind, sh_num, info, other;440 ElfW(Sym) *esym;441 const char *name;442 char buf1[256];443 444 if (section == NULL)445 sh_num = SHN_UNDEF;446 else if (section == SECTION_ABS)447 sh_num = SHN_ABS;448 else449 sh_num = section->sh_num;450 451 if ((sym->type.t & VT_BTYPE) == VT_FUNC) {452 sym_type = STT_FUNC;453 } else if ((sym->type.t & VT_BTYPE) == VT_VOID) {454 sym_type = STT_NOTYPE;455 } else {456 sym_type = STT_OBJECT;457 }458 459 if (sym->type.t & VT_STATIC)460 sym_bind = STB_LOCAL;461 else {462 if (sym->type.t & VT_WEAK)463 sym_bind = STB_WEAK;464 else465 sym_bind = STB_GLOBAL;466 }467 468 if (!sym->c) {469 name = get_tok_str(sym->v, NULL);470 #ifdef CONFIG_TCC_BCHECK471 if (tcc_state->do_bounds_check) {472 char buf[32];473 474 /* XXX: avoid doing that for statics ? */475 /* if bound checking is activated, we change some function476 names by adding the "__bound" prefix */477 switch(sym->v) {478 #ifdef TCC_TARGET_PE479 /* XXX: we rely only on malloc hooks */480 case TOK_malloc:481 case TOK_free:482 case TOK_realloc:483 case TOK_memalign:484 case TOK_calloc:485 #endif486 case TOK_memcpy:487 case TOK_memmove:488 case TOK_memset:489 case TOK_strlen:490 case TOK_strcpy:491 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64492 case TOK_alloca:493 #endif494 strcpy(buf, "__bound_");495 strcat(buf, name);496 name = buf;497 break;498 }499 }500 #endif501 other = 0;502 503 #ifdef TCC_TARGET_PE504 if (sym->type.t & VT_EXPORT)505 other |= 1;506 if (sym_type == STT_FUNC && sym->type.ref) {507 int attr = sym->type.ref->r;508 if (FUNC_EXPORT(attr))509 other |= 1;510 if (FUNC_CALL(attr) == FUNC_STDCALL && can_add_underscore) {511 sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr) * PTR_SIZE);512 name = buf1;513 other |= 2;514 can_add_underscore = 0;515 }516 } else {517 if (find_elf_sym(tcc_state->dynsymtab_section, name))518 other |= 4;519 if (sym->type.t & VT_IMPORT)520 other |= 4;521 }522 #endif523 if (tcc_state->leading_underscore && can_add_underscore) {524 buf1[0] = '_';525 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);526 name = buf1;527 }528 if (sym->asm_label) {529 name = sym->asm_label;530 }531 info = ELFW(ST_INFO)(sym_bind, sym_type);532 sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);533 } else {534 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];535 esym->st_value = value;536 esym->st_size = size;537 esym->st_shndx = sh_num;538 }539 }540 541 ST_FUNC void put_extern_sym(Sym *sym, Section *section,542 addr_t value, unsigned long size)543 {544 put_extern_sym2(sym, section, value, size, 1);545 }546 547 /* add a new relocation entry to symbol 'sym' in section 's' */548 ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type)549 {550 int c = 0;551 if (sym) {552 if (0 == sym->c)553 put_extern_sym(sym, NULL, 0, 0);554 c = sym->c;555 }556 /* now we can add ELF relocation info */557 put_elf_reloc(symtab_section, s, offset, type, c);558 457 } 559 458 … … 579 478 char buf[2048]; 580 479 BufferedFile **pf, *f; 581 480 582 481 buf[0] = '\0'; 583 482 /* use upper file if inline ":asm:" or token ":paste:" */ 584 for (f = file; f && f->filename[0] == ':'; f = f->prev); 483 for (f = file; f && f->filename[0] == ':'; f = f->prev) 484 ; 585 485 if (f) { 586 486 for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++) 587 487 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n", 588 488 (*pf)->filename, (*pf)->line_num); 589 if ( f->line_num > 0) {489 if (s1->error_set_jmp_enabled) { 590 490 strcat_printf(buf, sizeof(buf), "%s:%d: ", 591 f->filename, f->line_num );491 f->filename, f->line_num - !!(tok_flags & TOK_FLAG_BOL)); 592 492 } else { 593 493 strcat_printf(buf, sizeof(buf), "%s: ", … … 605 505 if (!s1->error_func) { 606 506 /* default case: stderr */ 507 if (s1->output_type == TCC_OUTPUT_PREPROCESS && s1->ppfp == stdout) 508 /* print a newline during tcc -E */ 509 printf("\n"), fflush(stdout); 510 fflush(stdout); /* flush -v output */ 607 511 fprintf(stderr, "%s\n", buf); 512 fflush(stderr); /* print error/warning now (win32) */ 608 513 } else { 609 514 s1->error_func(s1->error_opaque, buf); … … 669 574 int buflen = initlen ? initlen : IO_BUF_SIZE; 670 575 671 bf = tcc_malloc (sizeof(BufferedFile) + buflen);576 bf = tcc_mallocz(sizeof(BufferedFile) + buflen); 672 577 bf->buf_ptr = bf->buffer; 673 578 bf->buf_end = bf->buffer + initlen; 674 579 bf->buf_end[0] = CH_EOB; /* put eob symbol */ 675 580 pstrcpy(bf->filename, sizeof(bf->filename), filename); 676 #ifdef _WIN32 677 normalize_slashes(bf->filename); 678 #endif 581 bf->true_filename = bf->filename; 679 582 bf->line_num = 1; 680 bf->ifndef_macro = 0;681 583 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr; 682 584 bf->fd = -1; 683 585 bf->prev = file; 684 586 file = bf; 587 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; 685 588 } 686 589 … … 692 595 total_lines += bf->line_num; 693 596 } 597 if (bf->true_filename != bf->filename) 598 tcc_free(bf->true_filename); 694 599 file = bf->prev; 695 600 tcc_free(bf); … … 700 605 int fd; 701 606 if (strcmp(filename, "-") == 0) 702 fd = 0, filename = " stdin";607 fd = 0, filename = "<stdin>"; 703 608 else 704 609 fd = open(filename, O_RDONLY | O_BINARY); … … 708 613 if (fd < 0) 709 614 return -1; 710 711 615 tcc_open_bf(s1, filename, 0); 616 #ifdef _WIN32 617 normalize_slashes(file->filename); 618 #endif 712 619 file->fd = fd; 713 620 return fd; 714 621 } 715 622 716 /* compile the Cfile opened in 'file'. Return non zero if errors. */623 /* compile the file opened in 'file'. Return non zero if errors. */ 717 624 static int tcc_compile(TCCState *s1) 718 625 { 719 626 Sym *define_start; 720 SValue *pvtop; 721 char buf[512]; 722 volatile int section_sym; 723 724 #ifdef INC_DEBUG 725 printf("%s: **** new file\n", file->filename); 726 #endif 727 preprocess_init(s1); 728 729 cur_text_section = NULL; 730 funcname = ""; 731 anon_sym = SYM_FIRST_ANOM; 732 733 /* file info: full path + filename */ 734 section_sym = 0; /* avoid warning */ 735 if (s1->do_debug) { 736 section_sym = put_elf_sym(symtab_section, 0, 0, 737 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0, 738 text_section->sh_num, NULL); 739 getcwd(buf, sizeof(buf)); 740 #ifdef _WIN32 741 normalize_slashes(buf); 742 #endif 743 pstrcat(buf, sizeof(buf), "/"); 744 put_stabs_r(buf, N_SO, 0, 0, 745 text_section->data_offset, text_section, section_sym); 746 put_stabs_r(file->filename, N_SO, 0, 0, 747 text_section->data_offset, text_section, section_sym); 748 } 749 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL 750 symbols can be safely used */ 751 put_elf_sym(symtab_section, 0, 0, 752 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, 753 SHN_ABS, file->filename); 754 755 /* define some often used types */ 756 int_type.t = VT_INT; 757 758 char_pointer_type.t = VT_BYTE; 759 mk_pointer(&char_pointer_type); 760 761 #if PTR_SIZE == 4 762 size_type.t = VT_INT; 763 #else 764 size_type.t = VT_LLONG; 765 #endif 766 767 func_old_type.t = VT_FUNC; 768 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD); 769 #ifdef TCC_TARGET_ARM 770 arm_init_types(); 771 #endif 772 773 #if 0 774 /* define 'void *alloca(unsigned int)' builtin function */ 775 { 776 Sym *s1; 777 778 p = anon_sym++; 779 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW); 780 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0); 781 s1->next = NULL; 782 sym->next = s1; 783 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0); 784 } 785 #endif 627 int filetype, is_asm; 786 628 787 629 define_start = define_stack; 788 nocode_wanted = 1; 630 filetype = s1->filetype; 631 is_asm = filetype == AFF_TYPE_ASM || filetype == AFF_TYPE_ASMPP; 632 tccelf_begin_file(s1); 789 633 790 634 if (setjmp(s1->error_jmp_buf) == 0) { … … 792 636 s1->error_set_jmp_enabled = 1; 793 637 794 ch = file->buf_ptr[0]; 795 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; 796 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM; 797 pvtop = vtop; 798 next(); 799 decl(VT_CONST); 800 if (tok != TOK_EOF) 801 expect("declaration"); 802 if (pvtop != vtop) 803 tcc_warning("internal compiler error: vstack leak? (%d)", vtop - pvtop); 804 805 /* end of translation unit info */ 806 if (s1->do_debug) { 807 put_stabs_r(NULL, N_SO, 0, 0, 808 text_section->data_offset, text_section, section_sym); 638 preprocess_start(s1, is_asm); 639 if (s1->output_type == TCC_OUTPUT_PREPROCESS) { 640 tcc_preprocess(s1); 641 } else if (is_asm) { 642 #ifdef CONFIG_TCC_ASM 643 tcc_assemble(s1, filetype == AFF_TYPE_ASMPP); 644 #else 645 tcc_error_noabort("asm not supported"); 646 #endif 647 } else { 648 tccgen_compile(s1); 809 649 } 810 650 } 811 812 651 s1->error_set_jmp_enabled = 0; 813 652 814 /* reset define stack, but leave -Dsymbols (may be incorrect if 815 they are undefined) */ 816 free_defines(define_start); 817 818 gen_inline_functions(); 819 820 sym_pop(&global_stack, NULL); 821 sym_pop(&local_stack, NULL); 822 653 preprocess_end(s1); 654 free_inline_functions(s1); 655 /* reset define stack, but keep -D and built-ins */ 656 free_defines(define_start); 657 sym_pop(&global_stack, NULL, 0); 658 sym_pop(&local_stack, NULL, 0); 659 tccelf_end_file(s1); 823 660 return s1->nb_errors != 0 ? -1 : 0; 824 661 } … … 827 664 { 828 665 int len, ret; 666 829 667 len = strlen(str); 830 831 668 tcc_open_bf(s, "<string>", len); 832 669 memcpy(file->buffer, str, len); … … 853 690 854 691 /* parse with define parser */ 855 ch = file->buf_ptr[0];856 692 next_nomacro(); 857 693 parse_define(); 858 859 694 tcc_close(); 860 695 } … … 875 710 static void tcc_cleanup(void) 876 711 { 877 int i, n;878 712 if (NULL == tcc_state) 879 713 return; 714 while (file) 715 tcc_close(); 716 tccpp_delete(tcc_state); 880 717 tcc_state = NULL; 881 882 /* free -D defines */883 free_defines(NULL);884 885 /* free tokens */886 n = tok_ident - TOK_IDENT;887 for(i = 0; i < n; i++)888 tcc_free(table_ident[i]);889 tcc_free(table_ident);890 891 718 /* free sym_pools */ 892 719 dynarray_reset(&sym_pools, &nb_sym_pools); 893 /* string buffer */894 cstr_free(&tokcstr);895 720 /* reset symbol stack */ 896 721 sym_free_first = NULL; 897 /* cleanup from error/setjmp */898 macro_ptr = NULL;899 722 } 900 723 … … 902 725 { 903 726 TCCState *s; 904 char buffer[100];905 int a,b,c;906 727 907 728 tcc_cleanup(); … … 911 732 return NULL; 912 733 tcc_state = s; 734 ++nb_states; 735 736 s->alacarte_link = 1; 737 s->nocommon = 1; 738 s->warn_implicit_function_declaration = 1; 739 s->ms_extensions = 1; 740 741 #ifdef CHAR_IS_UNSIGNED 742 s->char_is_unsigned = 1; 743 #endif 744 #ifdef TCC_TARGET_I386 745 s->seg_size = 32; 746 #endif 747 /* enable this if you want symbols with leading underscore on windows: */ 748 #if 0 /* def TCC_TARGET_PE */ 749 s->leading_underscore = 1; 750 #endif 913 751 #ifdef _WIN32 914 752 tcc_set_lib_path_w32(s); … … 916 754 tcc_set_lib_path(s, CONFIG_TCCDIR); 917 755 #endif 918 s->output_type = TCC_OUTPUT_MEMORY; 919 preprocess_new(); 920 s->include_stack_ptr = s->include_stack; 756 tccelf_new(s); 757 tccpp_new(s); 921 758 922 759 /* we add dummy defines for some special macros to speed up tests … … 926 763 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL); 927 764 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL); 928 929 /* define __TINYC__ 92X */ 930 sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c); 931 sprintf(buffer, "%d", a*10000 + b*100 + c); 932 tcc_define_symbol(s, "__TINYC__", buffer); 765 define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL); 766 { 767 /* define __TINYC__ 92X */ 768 char buffer[32]; int a,b,c; 769 sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c); 770 sprintf(buffer, "%d", a*10000 + b*100 + c); 771 tcc_define_symbol(s, "__TINYC__", buffer); 772 } 933 773 934 774 /* standard defines */ 935 775 tcc_define_symbol(s, "__STDC__", NULL); 936 776 tcc_define_symbol(s, "__STDC_VERSION__", "199901L"); 777 tcc_define_symbol(s, "__STDC_HOSTED__", NULL); 937 778 938 779 /* target defines */ … … 952 793 tcc_define_symbol(s, "arm", NULL); 953 794 tcc_define_symbol(s, "__APCS_32__", NULL); 795 tcc_define_symbol(s, "__ARMEL__", NULL); 796 #if defined(TCC_ARM_EABI) 797 tcc_define_symbol(s, "__ARM_EABI__", NULL); 798 #endif 799 #if defined(TCC_ARM_HARDFLOAT) 800 s->float_abi = ARM_HARD_FLOAT; 801 tcc_define_symbol(s, "__ARM_PCS_VFP", NULL); 802 #else 803 s->float_abi = ARM_SOFTFP_FLOAT; 804 #endif 805 #elif defined(TCC_TARGET_ARM64) 806 tcc_define_symbol(s, "__aarch64__", NULL); 807 #elif defined TCC_TARGET_C67 808 tcc_define_symbol(s, "__C67__", NULL); 954 809 #endif 955 810 … … 963 818 tcc_define_symbol(s, "__unix", NULL); 964 819 tcc_define_symbol(s, "unix", NULL); 965 # if defined(__linux )820 # if defined(__linux__) 966 821 tcc_define_symbol(s, "__linux__", NULL); 967 822 tcc_define_symbol(s, "__linux", NULL); 968 823 # endif 969 824 # if defined(__FreeBSD__) 970 # define str(s) #s 971 tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));972 # undef str 825 tcc_define_symbol(s, "__FreeBSD__", "__FreeBSD__"); 826 /* No 'Thread Storage Local' on FreeBSD with tcc */ 827 tcc_define_symbol(s, "__NO_TLS", NULL); 973 828 # endif 974 829 # if defined(__FreeBSD_kernel__) 975 830 tcc_define_symbol(s, "__FreeBSD_kernel__", NULL); 976 831 # endif 832 # if defined(__NetBSD__) 833 tcc_define_symbol(s, "__NetBSD__", "__NetBSD__"); 834 # endif 835 # if defined(__OpenBSD__) 836 tcc_define_symbol(s, "__OpenBSD__", "__OpenBSD__"); 837 # endif 977 838 #endif 978 839 979 840 /* TinyCC & gcc defines */ 980 #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64 841 #if PTR_SIZE == 4 842 /* 32bit systems. */ 843 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int"); 844 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int"); 845 tcc_define_symbol(s, "__ILP32__", NULL); 846 #elif LONG_SIZE == 4 847 /* 64bit Windows. */ 981 848 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long long"); 982 849 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long long"); 850 tcc_define_symbol(s, "__LLP64__", NULL); 983 851 #else 852 /* Other 64bit systems. */ 984 853 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long"); 985 854 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long"); 855 tcc_define_symbol(s, "__LP64__", NULL); 986 856 #endif 987 857 988 858 #ifdef TCC_TARGET_PE 989 859 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short"); 860 tcc_define_symbol(s, "__WINT_TYPE__", "unsigned short"); 990 861 #else 991 862 tcc_define_symbol(s, "__WCHAR_TYPE__", "int"); 992 #endif 993 994 #ifndef TCC_TARGET_PE 863 /* wint_t is unsigned int by default, but (signed) int on BSDs 864 and unsigned short on windows. Other OSes might have still 865 other conventions, sigh. */ 866 # if defined(__FreeBSD__) || defined (__FreeBSD_kernel__) \ 867 || defined(__NetBSD__) || defined(__OpenBSD__) 868 tcc_define_symbol(s, "__WINT_TYPE__", "int"); 869 # ifdef __FreeBSD__ 870 /* define __GNUC__ to have some useful stuff from sys/cdefs.h 871 that are unconditionally used in FreeBSDs other system headers :/ */ 872 tcc_define_symbol(s, "__GNUC__", "2"); 873 tcc_define_symbol(s, "__GNUC_MINOR__", "7"); 874 tcc_define_symbol(s, "__builtin_alloca", "alloca"); 875 # endif 876 # else 877 tcc_define_symbol(s, "__WINT_TYPE__", "unsigned int"); 995 878 /* glibc defines */ 996 tcc_define_symbol(s, "__REDIRECT(name, proto, alias)", "name proto __asm__ (#alias)"); 997 tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", "name proto __asm__ (#alias) __THROW"); 998 /* default library paths */ 999 tcc_add_library_path(s, CONFIG_TCC_LIBPATHS); 1000 /* paths for crt objects */ 1001 tcc_split_path(s, (void ***)&s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX); 1002 #endif 1003 1004 /* no section zero */ 1005 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL); 1006 1007 /* create standard sections */ 1008 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); 1009 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); 1010 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); 1011 1012 /* symbols are always generated for linking stage */ 1013 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0, 1014 ".strtab", 1015 ".hashtab", SHF_PRIVATE); 1016 strtab_section = symtab_section->link; 1017 s->symtab = symtab_section; 1018 1019 /* private symbol table for dynamic symbols */ 1020 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE, 1021 ".dynstrtab", 1022 ".dynhashtab", SHF_PRIVATE); 1023 s->alacarte_link = 1; 1024 s->nocommon = 1; 1025 s->section_align = ELF_PAGE_SIZE; 1026 1027 #ifdef CHAR_IS_UNSIGNED 1028 s->char_is_unsigned = 1; 1029 #endif 1030 /* enable this if you want symbols with leading underscore on windows: */ 1031 #if 0 //def TCC_TARGET_PE 1032 s->leading_underscore = 1; 1033 #endif 1034 #ifdef TCC_TARGET_I386 1035 s->seg_size = 32; 1036 #endif 879 tcc_define_symbol(s, "__REDIRECT(name, proto, alias)", 880 "name proto __asm__ (#alias)"); 881 tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", 882 "name proto __asm__ (#alias) __THROW"); 883 # endif 884 # if defined(TCC_MUSL) 885 tcc_define_symbol(s, "__DEFINED_va_list", ""); 886 tcc_define_symbol(s, "__DEFINED___isoc_va_list", ""); 887 tcc_define_symbol(s, "__isoc_va_list", "void *"); 888 # endif /* TCC_MUSL */ 889 /* Some GCC builtins that are simple to express as macros. */ 890 tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x"); 891 #endif /* ndef TCC_TARGET_PE */ 1037 892 return s; 1038 893 } … … 1040 895 LIBTCCAPI void tcc_delete(TCCState *s1) 1041 896 { 1042 int i;1043 1044 897 tcc_cleanup(); 1045 898 1046 /* free all sections */ 1047 for(i = 1; i < s1->nb_sections; i++) 1048 free_section(s1->sections[i]); 1049 dynarray_reset(&s1->sections, &s1->nb_sections); 1050 1051 for(i = 0; i < s1->nb_priv_sections; i++) 1052 free_section(s1->priv_sections[i]); 1053 dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections); 1054 1055 /* free any loaded DLLs */ 1056 for ( i = 0; i < s1->nb_loaded_dlls; i++) { 1057 DLLReference *ref = s1->loaded_dlls[i]; 1058 if ( ref->handle ) 1059 dlclose(ref->handle); 1060 } 1061 1062 /* free loaded dlls array */ 1063 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); 899 /* free sections */ 900 tccelf_delete(s1); 1064 901 1065 902 /* free library paths */ … … 1071 908 dynarray_reset(&s1->include_paths, &s1->nb_include_paths); 1072 909 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths); 910 dynarray_reset(&s1->cmd_include_files, &s1->nb_cmd_include_files); 1073 911 1074 912 tcc_free(s1->tcc_lib_path); … … 1081 919 dynarray_reset(&s1->files, &s1->nb_files); 1082 920 dynarray_reset(&s1->target_deps, &s1->nb_target_deps); 921 dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs); 922 dynarray_reset(&s1->argv, &s1->argc); 1083 923 1084 924 #ifdef TCC_IS_NATIVE 1085 # ifdef HAVE_SELINUX 1086 munmap (s1->write_mem, s1->mem_size); 1087 munmap (s1->runtime_mem, s1->mem_size); 1088 # else 1089 tcc_free(s1->runtime_mem); 925 /* free runtime memory */ 926 tcc_run_free(s1); 927 #endif 928 929 tcc_free(s1); 930 if (0 == --nb_states) 931 tcc_memcheck(); 932 } 933 934 LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) 935 { 936 s->output_type = output_type; 937 938 /* always elf for objects */ 939 if (output_type == TCC_OUTPUT_OBJ) 940 s->output_format = TCC_OUTPUT_FORMAT_ELF; 941 942 if (s->char_is_unsigned) 943 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL); 944 945 if (!s->nostdinc) { 946 /* default include paths */ 947 /* -isystem paths have already been handled */ 948 tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS); 949 } 950 951 #ifdef CONFIG_TCC_BCHECK 952 if (s->do_bounds_check) { 953 /* if bound checking, then add corresponding sections */ 954 tccelf_bounds_new(s); 955 /* define symbol */ 956 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL); 957 } 958 #endif 959 if (s->do_debug) { 960 /* add debug sections */ 961 tccelf_stab_new(s); 962 } 963 964 tcc_add_library_path(s, CONFIG_TCC_LIBPATHS); 965 966 #ifdef TCC_TARGET_PE 967 # ifdef _WIN32 968 if (!s->nostdlib && output_type != TCC_OUTPUT_OBJ) 969 tcc_add_systemdir(s); 1090 970 # endif 1091 #endif 1092 1093 tcc_free(s1); 971 #else 972 /* paths for crt objects */ 973 tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX); 974 /* add libc crt1/crti objects */ 975 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) && 976 !s->nostdlib) { 977 if (output_type != TCC_OUTPUT_DLL) 978 tcc_add_crt(s, "crt1.o"); 979 tcc_add_crt(s, "crti.o"); 980 } 981 #endif 982 return 0; 1094 983 } 1095 984 1096 985 LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname) 1097 986 { 1098 tcc_split_path(s, (void ***)&s->include_paths, &s->nb_include_paths, pathname);987 tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname); 1099 988 return 0; 1100 989 } … … 1102 991 LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname) 1103 992 { 1104 tcc_split_path(s, (void ***)&s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);993 tcc_split_path(s, &s->sysinclude_paths, &s->nb_sysinclude_paths, pathname); 1105 994 return 0; 1106 995 } … … 1108 997 ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) 1109 998 { 1110 const char *ext; 1111 ElfW(Ehdr) ehdr; 1112 int fd, ret, size; 1113 1114 /* find source file type with extension */ 1115 ext = tcc_fileextension(filename); 1116 if (ext[0]) 1117 ext++; 1118 1119 #ifdef CONFIG_TCC_ASM 1120 /* if .S file, define __ASSEMBLER__ like gcc does */ 1121 if (!strcmp(ext, "S")) 1122 tcc_define_symbol(s1, "__ASSEMBLER__", NULL); 1123 #endif 999 int ret; 1124 1000 1125 1001 /* open the file */ … … 1132 1008 1133 1009 /* update target deps */ 1134 dynarray_add( (void ***)&s1->target_deps, &s1->nb_target_deps,1010 dynarray_add(&s1->target_deps, &s1->nb_target_deps, 1135 1011 tcc_strdup(filename)); 1136 1012 1137 if (flags & AFF_PREPROCESS) { 1138 ret = tcc_preprocess(s1); 1139 goto the_end; 1140 } 1141 1142 if (!ext[0] || !PATHCMP(ext, "c")) { 1143 /* C file assumed */ 1144 ret = tcc_compile(s1); 1145 goto the_end; 1146 } 1147 1148 #ifdef CONFIG_TCC_ASM 1149 if (!strcmp(ext, "S")) { 1150 /* preprocessed assembler */ 1151 ret = tcc_assemble(s1, 1); 1152 goto the_end; 1153 } 1154 1155 if (!strcmp(ext, "s")) { 1156 /* non preprocessed assembler */ 1157 ret = tcc_assemble(s1, 0); 1158 goto the_end; 1159 } 1160 #endif 1161 1162 fd = file->fd; 1163 /* assume executable format: auto guess file type */ 1164 size = read(fd, &ehdr, sizeof(ehdr)); 1165 lseek(fd, 0, SEEK_SET); 1166 if (size <= 0) { 1167 tcc_error_noabort("could not read header"); 1168 goto the_end; 1169 } 1170 1171 if (size == sizeof(ehdr) && 1172 ehdr.e_ident[0] == ELFMAG0 && 1173 ehdr.e_ident[1] == ELFMAG1 && 1174 ehdr.e_ident[2] == ELFMAG2 && 1175 ehdr.e_ident[3] == ELFMAG3) { 1176 1177 /* do not display line number if error */ 1178 file->line_num = 0; 1179 if (ehdr.e_type == ET_REL) { 1013 if (flags & AFF_TYPE_BIN) { 1014 ElfW(Ehdr) ehdr; 1015 int fd, obj_type; 1016 1017 fd = file->fd; 1018 obj_type = tcc_object_type(fd, &ehdr); 1019 lseek(fd, 0, SEEK_SET); 1020 1021 #ifdef TCC_TARGET_MACHO 1022 if (0 == obj_type && 0 == strcmp(tcc_fileextension(filename), ".dylib")) 1023 obj_type = AFF_BINTYPE_DYN; 1024 #endif 1025 1026 switch (obj_type) { 1027 case AFF_BINTYPE_REL: 1180 1028 ret = tcc_load_object_file(s1, fd, 0); 1181 goto the_end; 1182 1183 } 1029 break; 1184 1030 #ifndef TCC_TARGET_PE 1185 if (ehdr.e_type == ET_DYN) {1031 case AFF_BINTYPE_DYN: 1186 1032 if (s1->output_type == TCC_OUTPUT_MEMORY) { 1033 ret = 0; 1187 1034 #ifdef TCC_IS_NATIVE 1188 void *h; 1189 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY); 1190 if (h) 1191 #endif 1192 ret = 0; 1035 if (NULL == dlopen(filename, RTLD_GLOBAL | RTLD_LAZY)) 1036 ret = -1; 1037 #endif 1193 1038 } else { 1194 ret = tcc_load_dll(s1, fd, filename, 1039 ret = tcc_load_dll(s1, fd, filename, 1195 1040 (flags & AFF_REFERENCED_DLL) != 0); 1196 1041 } 1197 goto the_end; 1042 break; 1043 #endif 1044 case AFF_BINTYPE_AR: 1045 ret = tcc_load_archive(s1, fd); 1046 break; 1047 #ifdef TCC_TARGET_COFF 1048 case AFF_BINTYPE_C67: 1049 ret = tcc_load_coff(s1, fd); 1050 break; 1051 #endif 1052 default: 1053 #ifdef TCC_TARGET_PE 1054 ret = pe_load_file(s1, filename, fd); 1055 #else 1056 /* as GNU ld, consider it is an ld script if not recognized */ 1057 ret = tcc_load_ldscript(s1); 1058 #endif 1059 if (ret < 0) 1060 tcc_error_noabort("unrecognized file type"); 1061 break; 1198 1062 } 1199 #endif 1200 tcc_error_noabort("unrecognized ELF file"); 1201 goto the_end; 1202 } 1203 1204 if (memcmp((char *)&ehdr, ARMAG, 8) == 0) { 1205 file->line_num = 0; /* do not display line number if error */ 1206 ret = tcc_load_archive(s1, fd); 1207 goto the_end; 1208 } 1209 1210 #ifdef TCC_TARGET_COFF 1211 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) { 1212 ret = tcc_load_coff(s1, fd); 1213 goto the_end; 1214 } 1215 #endif 1216 1217 #ifdef TCC_TARGET_PE 1218 ret = pe_load_file(s1, filename, fd); 1219 #else 1220 /* as GNU ld, consider it is an ld script if not recognized */ 1221 ret = tcc_load_ldscript(s1); 1222 #endif 1223 if (ret < 0) 1224 tcc_error_noabort("unrecognized file type"); 1225 1226 the_end: 1063 } else { 1064 ret = tcc_compile(s1); 1065 } 1227 1066 tcc_close(); 1228 1067 return ret; … … 1231 1070 LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename) 1232 1071 { 1233 if (s->output_type == TCC_OUTPUT_PREPROCESS) 1234 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR | AFF_PREPROCESS); 1235 else 1236 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR); 1072 int filetype = s->filetype; 1073 int flags = AFF_PRINT_ERROR; 1074 if (filetype == 0) { 1075 /* use a file extension to detect a filetype */ 1076 const char *ext = tcc_fileextension(filename); 1077 if (ext[0]) { 1078 ext++; 1079 if (!strcmp(ext, "S")) 1080 filetype = AFF_TYPE_ASMPP; 1081 else if (!strcmp(ext, "s")) 1082 filetype = AFF_TYPE_ASM; 1083 else if (!PATHCMP(ext, "c") || !PATHCMP(ext, "i")) 1084 filetype = AFF_TYPE_C; 1085 else 1086 flags |= AFF_TYPE_BIN; 1087 } else { 1088 filetype = AFF_TYPE_C; 1089 } 1090 s->filetype = filetype; 1091 } 1092 return tcc_add_file_internal(s, filename, flags); 1237 1093 } 1238 1094 1239 1095 LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname) 1240 1096 { 1241 tcc_split_path(s, (void ***)&s->library_paths, &s->nb_library_paths, pathname);1097 tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname); 1242 1098 return 0; 1243 1099 } … … 1251 1107 for(i = 0; i < nb_paths; i++) { 1252 1108 snprintf(buf, sizeof(buf), fmt, paths[i], filename); 1253 if (tcc_add_file_internal(s, buf, flags ) == 0)1109 if (tcc_add_file_internal(s, buf, flags | AFF_TYPE_BIN) == 0) 1254 1110 return 0; 1255 1111 } … … 1276 1132 LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname) 1277 1133 { 1278 #if defTCC_TARGET_PE1134 #if defined TCC_TARGET_PE 1279 1135 const char *libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL }; 1280 1136 const char **pp = s->static_link ? libs + 4 : libs; 1137 #elif defined TCC_TARGET_MACHO 1138 const char *libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL }; 1139 const char **pp = s->static_link ? libs + 1 : libs; 1281 1140 #else 1282 1141 const char *libs[] = { "%s/lib%s.so", "%s/lib%s.a", NULL }; … … 1292 1151 } 1293 1152 1153 PUB_FUNC int tcc_add_library_err(TCCState *s, const char *libname) 1154 { 1155 int ret = tcc_add_library(s, libname); 1156 if (ret < 0) 1157 tcc_error_noabort("library '%s' not found", libname); 1158 return ret; 1159 } 1160 1161 /* handle #pragma comment(lib,) */ 1162 ST_FUNC void tcc_add_pragma_libs(TCCState *s1) 1163 { 1164 int i; 1165 for (i = 0; i < s1->nb_pragma_libs; i++) 1166 tcc_add_library_err(s1, s1->pragma_libs[i]); 1167 } 1168 1294 1169 LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val) 1295 1170 { … … 1299 1174 pe_putimport(s, 0, name, (uintptr_t)val); 1300 1175 #else 1301 /* XXX: Same problem on linux but currently "solved" elsewhere 1302 via the rather dirty 'runtime_plt_and_got' hack. */ 1303 add_elf_sym(symtab_section, (uintptr_t)val, 0, 1176 set_elf_sym(symtab_section, (uintptr_t)val, 0, 1304 1177 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1305 1178 SHN_ABS, name); 1306 #endif1307 return 0;1308 }1309 1310 LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)1311 {1312 s->output_type = output_type;1313 1314 if (!s->nostdinc) {1315 /* default include paths */1316 /* -isystem paths have already been handled */1317 tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS);1318 }1319 1320 /* if bound checking, then add corresponding sections */1321 #ifdef CONFIG_TCC_BCHECK1322 if (s->do_bounds_check) {1323 /* define symbol */1324 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);1325 /* create bounds sections */1326 bounds_section = new_section(s, ".bounds",1327 SHT_PROGBITS, SHF_ALLOC);1328 lbounds_section = new_section(s, ".lbounds",1329 SHT_PROGBITS, SHF_ALLOC);1330 }1331 #endif1332 1333 if (s->char_is_unsigned) {1334 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);1335 }1336 1337 /* add debug sections */1338 if (s->do_debug) {1339 /* stab symbols */1340 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);1341 stab_section->sh_entsize = sizeof(Stab_Sym);1342 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);1343 put_elf_str(stabstr_section, "");1344 stab_section->link = stabstr_section;1345 /* put first entry */1346 put_stabs("", 0, 0, 0, 0);1347 }1348 1349 #ifdef TCC_TARGET_PE1350 tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);1351 # ifdef _WIN321352 tcc_add_systemdir(s);1353 # endif1354 #else1355 /* add libc crt1/crti objects */1356 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&1357 !s->nostdlib) {1358 if (output_type != TCC_OUTPUT_DLL)1359 tcc_add_crt(s, "crt1.o");1360 tcc_add_crt(s, "crti.o");1361 }1362 1179 #endif 1363 1180 return 0; … … 1379 1196 } FlagDef; 1380 1197 1381 static const FlagDef warning_defs[] = {1382 { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, 1383 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },1384 { offsetof(TCCState, warn_error), 0, "error" },1385 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,1386 "implicit-function-declaration" },1387 };1388 1389 ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, int nb_flags, 1390 const char *name, int value)1391 { 1392 int i;1198 static int no_flag(const char **pp) 1199 { 1200 const char *p = *pp; 1201 if (*p != 'n' || *++p != 'o' || *++p != '-') 1202 return 0; 1203 *pp = p + 1; 1204 return 1; 1205 } 1206 1207 ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, const char *name) 1208 { 1209 int value, ret; 1393 1210 const FlagDef *p; 1394 1211 const char *r; 1395 1212 1213 value = 1; 1396 1214 r = name; 1397 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') { 1398 r += 3; 1399 value = !value; 1400 } 1401 for(i = 0, p = flags; i < nb_flags; i++, p++) { 1402 if (!strcmp(r, p->name)) 1403 goto found; 1404 } 1405 return -1; 1406 found: 1407 if (p->flags & FD_INVERT) 1408 value = !value; 1409 *(int *)((uint8_t *)s + p->offset) = value; 1410 return 0; 1411 } 1412 1413 /* set/reset a warning */ 1414 static int tcc_set_warning(TCCState *s, const char *warning_name, int value) 1415 { 1416 int i; 1417 const FlagDef *p; 1418 1419 if (!strcmp(warning_name, "all")) { 1420 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) { 1421 if (p->flags & WD_ALL) 1422 *(int *)((uint8_t *)s + p->offset) = 1; 1215 if (no_flag(&r)) 1216 value = 0; 1217 1218 for (ret = -1, p = flags; p->name; ++p) { 1219 if (ret) { 1220 if (strcmp(r, p->name)) 1221 continue; 1222 } else { 1223 if (0 == (p->flags & WD_ALL)) 1224 continue; 1423 1225 } 1424 return 0; 1425 } else { 1426 return set_flag(s, warning_defs, countof(warning_defs), 1427 warning_name, value); 1428 } 1429 } 1430 1431 static const FlagDef flag_defs[] = { 1432 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" }, 1433 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" }, 1434 { offsetof(TCCState, nocommon), FD_INVERT, "common" }, 1435 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" }, 1436 }; 1437 1438 /* set/reset a flag */ 1439 static int tcc_set_flag(TCCState *s, const char *flag_name, int value) 1440 { 1441 return set_flag(s, flag_defs, countof(flag_defs), 1442 flag_name, value); 1443 } 1444 1226 if (p->offset) { 1227 *(int*)((char *)s + p->offset) = 1228 p->flags & FD_INVERT ? !value : value; 1229 if (ret) 1230 return 0; 1231 } else { 1232 ret = 0; 1233 } 1234 } 1235 return ret; 1236 } 1445 1237 1446 1238 static int strstart(const char *val, const char **str) … … 1470 1262 { 1471 1263 const char *p, *q; 1264 int ret; 1472 1265 1473 1266 /* there should be 1 or 2 dashes */ … … 1477 1270 str++; 1478 1271 1479 /* then str & val should match (potential y up to '=') */1272 /* then str & val should match (potentially up to '=') */ 1480 1273 p = str; 1481 1274 q = val; 1275 1276 ret = 1; 1277 if (q[0] == '?') { 1278 ++q; 1279 if (no_flag(&p)) 1280 ret = -1; 1281 } 1482 1282 1483 1283 while (*q != '\0' && *q != '=') { … … 1490 1290 /* '=' near eos means ',' or '=' is ok */ 1491 1291 if (*q == '=') { 1292 if (*p == 0) 1293 *ptr = p; 1492 1294 if (*p != ',' && *p != '=') 1493 1295 return 0; 1494 1296 p++; 1495 q++; 1496 } 1497 1498 if (ptr) 1499 *ptr = p; 1500 return 1; 1297 } else if (*p) { 1298 return 0; 1299 } 1300 *ptr = p; 1301 return ret; 1501 1302 } 1502 1303 … … 1509 1310 } 1510 1311 1511 static char *copy_linker_arg(const char *p) 1512 { 1513 const char *q = p; 1312 static void copy_linker_arg(char **pp, const char *s, int sep) 1313 { 1314 const char *q = s; 1315 char *p = *pp; 1316 int l = 0; 1317 if (p && sep) 1318 p[l = strlen(p)] = sep, ++l; 1514 1319 skip_linker_arg(&q); 1515 return pstrncpy(tcc_malloc(q - p + 1), p, q - p);1320 pstrncpy(l + (*pp = tcc_realloc(p, q - s + l + 1)), s, q - s); 1516 1321 } 1517 1322 … … 1519 1324 static int tcc_set_linker(TCCState *s, const char *option) 1520 1325 { 1521 while ( option &&*option) {1522 1523 const char *p = option;1326 while (*option) { 1327 1328 const char *p = NULL; 1524 1329 char *end = NULL; 1525 1330 int ignoring = 0; 1331 int ret; 1526 1332 1527 1333 if (link_option(option, "Bsymbolic", &p)) { … … 1530 1336 s->nostdlib = 1; 1531 1337 } else if (link_option(option, "fini=", &p)) { 1532 s->fini_symbol = copy_linker_arg(p);1338 copy_linker_arg(&s->fini_symbol, p, 0); 1533 1339 ignoring = 1; 1534 1340 } else if (link_option(option, "image-base=", &p) … … 1537 1343 s->has_text_addr = 1; 1538 1344 } else if (link_option(option, "init=", &p)) { 1539 s->init_symbol = copy_linker_arg(p);1345 copy_linker_arg(&s->init_symbol, p, 0); 1540 1346 ignoring = 1; 1541 1347 } else if (link_option(option, "oformat=", &p)) { 1542 1348 #if defined(TCC_TARGET_PE) 1543 1349 if (strstart("pe-", &p)) { 1544 #elif defined(TCC_TARGET_X86_64)1350 #elif PTR_SIZE == 8 1545 1351 if (strstart("elf64-", &p)) { 1546 1352 #else … … 1557 1363 goto err; 1558 1364 1365 } else if (link_option(option, "as-needed", &p)) { 1366 ignoring = 1; 1367 } else if (link_option(option, "O", &p)) { 1368 ignoring = 1; 1369 } else if (link_option(option, "export-all-symbols", &p)) { 1370 s->rdynamic = 1; 1559 1371 } else if (link_option(option, "rpath=", &p)) { 1560 s->rpath = copy_linker_arg(p); 1372 copy_linker_arg(&s->rpath, p, ':'); 1373 } else if (link_option(option, "enable-new-dtags", &p)) { 1374 s->enable_new_dtags = 1; 1561 1375 } else if (link_option(option, "section-alignment=", &p)) { 1562 1376 s->section_align = strtoul(p, &end, 16); 1563 1377 } else if (link_option(option, "soname=", &p)) { 1564 s->soname = copy_linker_arg(p);1378 copy_linker_arg(&s->soname, p, 0); 1565 1379 #ifdef TCC_TARGET_PE 1380 } else if (link_option(option, "large-address-aware", &p)) { 1381 s->pe_characteristics |= 0x20; 1566 1382 } else if (link_option(option, "file-alignment=", &p)) { 1567 1383 s->pe_file_align = strtoul(p, &end, 16); … … 1574 1390 } else if (!strcmp(p, "console")) { 1575 1391 s->pe_subsystem = 3; 1576 } else if (!strcmp(p, "gui") ) {1392 } else if (!strcmp(p, "gui") || !strcmp(p, "windows")) { 1577 1393 s->pe_subsystem = 2; 1578 1394 } else if (!strcmp(p, "posix")) { … … 1593 1409 goto err; 1594 1410 #endif 1595 } else 1596 goto err; 1597 1598 if (ignoring && s->warn_unsupported) err: { 1599 char buf[100], *e; 1600 pstrcpy(buf, sizeof buf, e = copy_linker_arg(option)), tcc_free(e); 1601 if (ignoring) 1602 tcc_warning("unsupported linker option '%s'", buf); 1603 else 1604 tcc_error("unsupported linker option '%s'", buf); 1411 } else if (ret = link_option(option, "?whole-archive", &p), ret) { 1412 s->alacarte_link = ret < 0; 1413 } else if (p) { 1414 return 0; 1415 } else { 1416 err: 1417 tcc_error("unsupported linker option '%s'", option); 1605 1418 } 1419 1420 if (ignoring && s->warn_unsupported) 1421 tcc_warning("unsupported linker option '%s'", option); 1422 1606 1423 option = skip_linker_arg(&p); 1607 1424 } 1608 return 0;1425 return 1; 1609 1426 } 1610 1427 … … 1617 1434 enum { 1618 1435 TCC_OPTION_HELP, 1436 TCC_OPTION_HELP2, 1437 TCC_OPTION_v, 1619 1438 TCC_OPTION_I, 1620 1439 TCC_OPTION_D, 1621 1440 TCC_OPTION_U, 1441 TCC_OPTION_P, 1622 1442 TCC_OPTION_L, 1623 1443 TCC_OPTION_B, … … 1628 1448 TCC_OPTION_g, 1629 1449 TCC_OPTION_c, 1450 TCC_OPTION_dumpversion, 1451 TCC_OPTION_d, 1630 1452 TCC_OPTION_static, 1453 TCC_OPTION_std, 1631 1454 TCC_OPTION_shared, 1632 1455 TCC_OPTION_soname, … … 1634 1457 TCC_OPTION_r, 1635 1458 TCC_OPTION_s, 1459 TCC_OPTION_traditional, 1636 1460 TCC_OPTION_Wl, 1461 TCC_OPTION_Wp, 1637 1462 TCC_OPTION_W, 1638 1463 TCC_OPTION_O, 1464 TCC_OPTION_mfloat_abi, 1639 1465 TCC_OPTION_m, 1640 1466 TCC_OPTION_f, 1641 1467 TCC_OPTION_isystem, 1468 TCC_OPTION_iwithprefix, 1469 TCC_OPTION_include, 1642 1470 TCC_OPTION_nostdinc, 1643 1471 TCC_OPTION_nostdlib, 1644 1472 TCC_OPTION_print_search_dirs, 1645 1473 TCC_OPTION_rdynamic, 1474 TCC_OPTION_param, 1646 1475 TCC_OPTION_pedantic, 1647 1476 TCC_OPTION_pthread, 1648 1477 TCC_OPTION_run, 1649 TCC_OPTION_v,1650 1478 TCC_OPTION_w, 1651 1479 TCC_OPTION_pipe, … … 1654 1482 TCC_OPTION_MF, 1655 1483 TCC_OPTION_x, 1656 TCC_OPTION_dumpversion, 1484 TCC_OPTION_ar, 1485 TCC_OPTION_impdef 1657 1486 }; 1658 1487 … … 1664 1493 { "-help", TCC_OPTION_HELP, 0 }, 1665 1494 { "?", TCC_OPTION_HELP, 0 }, 1495 { "hh", TCC_OPTION_HELP2, 0 }, 1496 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1666 1497 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG }, 1667 1498 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG }, 1668 1499 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG }, 1500 { "P", TCC_OPTION_P, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1669 1501 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG }, 1670 1502 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG }, … … 1679 1511 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1680 1512 { "c", TCC_OPTION_c, 0 }, 1513 { "dumpversion", TCC_OPTION_dumpversion, 0}, 1514 { "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1681 1515 { "static", TCC_OPTION_static, 0 }, 1516 { "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1682 1517 { "shared", TCC_OPTION_shared, 0 }, 1683 1518 { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG }, 1684 1519 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG }, 1520 { "-param", TCC_OPTION_param, TCC_OPTION_HAS_ARG }, 1685 1521 { "pedantic", TCC_OPTION_pedantic, 0}, 1686 1522 { "pthread", TCC_OPTION_pthread, 0}, … … 1689 1525 { "r", TCC_OPTION_r, 0 }, 1690 1526 { "s", TCC_OPTION_s, 0 }, 1527 { "traditional", TCC_OPTION_traditional, 0 }, 1691 1528 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1529 { "Wp,", TCC_OPTION_Wp, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1692 1530 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1693 1531 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1694 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG }, 1532 #ifdef TCC_TARGET_ARM 1533 { "mfloat-abi", TCC_OPTION_mfloat_abi, TCC_OPTION_HAS_ARG }, 1534 #endif 1535 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1695 1536 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1696 1537 { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG }, 1538 { "include", TCC_OPTION_include, TCC_OPTION_HAS_ARG }, 1697 1539 { "nostdinc", TCC_OPTION_nostdinc, 0 }, 1698 1540 { "nostdlib", TCC_OPTION_nostdlib, 0 }, 1699 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, 1700 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 1541 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, 1701 1542 { "w", TCC_OPTION_w, 0 }, 1702 1543 { "pipe", TCC_OPTION_pipe, 0}, … … 1705 1546 { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG }, 1706 1547 { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG }, 1707 { "dumpversion", TCC_OPTION_dumpversion, 0}, 1548 { "ar", TCC_OPTION_ar, 0}, 1549 #ifdef TCC_TARGET_PE 1550 { "impdef", TCC_OPTION_impdef, 0}, 1551 #endif 1708 1552 { NULL, 0, 0 }, 1553 }; 1554 1555 static const FlagDef options_W[] = { 1556 { 0, 0, "all" }, 1557 { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, 1558 { offsetof(TCCState, warn_write_strings), 0, "write-strings" }, 1559 { offsetof(TCCState, warn_error), 0, "error" }, 1560 { offsetof(TCCState, warn_gcc_compat), 0, "gcc-compat" }, 1561 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, 1562 "implicit-function-declaration" }, 1563 { 0, 0, NULL } 1564 }; 1565 1566 static const FlagDef options_f[] = { 1567 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" }, 1568 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" }, 1569 { offsetof(TCCState, nocommon), FD_INVERT, "common" }, 1570 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" }, 1571 { offsetof(TCCState, ms_extensions), 0, "ms-extensions" }, 1572 { offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" }, 1573 { 0, 0, NULL } 1574 }; 1575 1576 static const FlagDef options_m[] = { 1577 { offsetof(TCCState, ms_bitfields), 0, "ms-bitfields" }, 1578 #ifdef TCC_TARGET_X86_64 1579 { offsetof(TCCState, nosse), FD_INVERT, "sse" }, 1580 #endif 1581 { 0, 0, NULL } 1709 1582 }; 1710 1583 … … 1719 1592 } 1720 1593 1721 PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) 1594 static void args_parser_add_file(TCCState *s, const char* filename, int filetype) 1595 { 1596 struct filespec *f = tcc_malloc(sizeof *f + strlen(filename)); 1597 f->type = filetype; 1598 f->alacarte = s->alacarte_link; 1599 strcpy(f->name, filename); 1600 dynarray_add(&s->files, &s->nb_files, f); 1601 } 1602 1603 static int args_parser_make_argv(const char *r, int *argc, char ***argv) 1604 { 1605 int ret = 0, q, c; 1606 CString str; 1607 for(;;) { 1608 while (c = (unsigned char)*r, c && c <= ' ') 1609 ++r; 1610 if (c == 0) 1611 break; 1612 q = 0; 1613 cstr_new(&str); 1614 while (c = (unsigned char)*r, c) { 1615 ++r; 1616 if (c == '\\' && (*r == '"' || *r == '\\')) { 1617 c = *r++; 1618 } else if (c == '"') { 1619 q = !q; 1620 continue; 1621 } else if (q == 0 && c <= ' ') { 1622 break; 1623 } 1624 cstr_ccat(&str, c); 1625 } 1626 cstr_ccat(&str, 0); 1627 //printf("<%s>\n", str.data), fflush(stdout); 1628 dynarray_add(argv, argc, tcc_strdup(str.data)); 1629 cstr_free(&str); 1630 ++ret; 1631 } 1632 return ret; 1633 } 1634 1635 /* read list file */ 1636 static void args_parser_listfile(TCCState *s, 1637 const char *filename, int optind, int *pargc, char ***pargv) 1638 { 1639 int fd, i; 1640 size_t len; 1641 char *p; 1642 int argc = 0; 1643 char **argv = NULL; 1644 1645 fd = open(filename, O_RDONLY | O_BINARY); 1646 if (fd < 0) 1647 tcc_error("listfile '%s' not found", filename); 1648 1649 len = lseek(fd, 0, SEEK_END); 1650 p = tcc_malloc(len + 1), p[len] = 0; 1651 lseek(fd, 0, SEEK_SET), read(fd, p, len), close(fd); 1652 1653 for (i = 0; i < *pargc; ++i) 1654 if (i == optind) 1655 args_parser_make_argv(p, &argc, &argv); 1656 else 1657 dynarray_add(&argv, &argc, tcc_strdup((*pargv)[i])); 1658 1659 tcc_free(p); 1660 dynarray_reset(&s->argv, &s->argc); 1661 *pargc = s->argc = argc, *pargv = s->argv = argv; 1662 } 1663 1664 PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind) 1722 1665 { 1723 1666 const TCCOption *popt; 1724 1667 const char *optarg, *r; 1725 int run = 0; 1726 int pthread = 0; 1727 int optind = 0; 1728 1729 /* collect -Wl options for input such as "-Wl,-rpath -Wl,<path>" */ 1730 CString linker_arg; 1668 const char *run = NULL; 1669 int last_o = -1; 1670 int x; 1671 CString linker_arg; /* collect -Wl options */ 1672 int tool = 0, arg_start = 0, noaction = optind; 1673 char **argv = *pargv; 1674 int argc = *pargc; 1675 1731 1676 cstr_new(&linker_arg); 1732 1677 1733 1678 while (optind < argc) { 1734 1735 r = argv[optind++]; 1679 r = argv[optind]; 1680 if (r[0] == '@' && r[1] != '\0') { 1681 args_parser_listfile(s, r + 1, optind, &argc, &argv); 1682 continue; 1683 } 1684 optind++; 1685 if (tool) { 1686 if (r[0] == '-' && r[1] == 'v' && r[2] == 0) 1687 ++s->verbose; 1688 continue; 1689 } 1690 reparse: 1736 1691 if (r[0] != '-' || r[1] == '\0') { 1737 /* add a new file*/1738 dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));1692 if (r[0] != '@') /* allow "tcc file(s) -run @ args ..." */ 1693 args_parser_add_file(s, r, s->filetype); 1739 1694 if (run) { 1740 optind--;1741 /* argv[0] will be this file */1695 tcc_set_options(s, run); 1696 arg_start = optind - 1; 1742 1697 break; 1743 1698 } … … 1757 1712 if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP)) { 1758 1713 if (optind >= argc) 1714 arg_err: 1759 1715 tcc_error("argument to '%s' is missing", r); 1760 1716 optarg = argv[optind++]; … … 1767 1723 switch(popt->index) { 1768 1724 case TCC_OPTION_HELP: 1769 return 0; 1725 return OPT_HELP; 1726 case TCC_OPTION_HELP2: 1727 return OPT_HELP2; 1770 1728 case TCC_OPTION_I: 1771 if (tcc_add_include_path(s, optarg) < 0) 1772 tcc_error("too many include paths"); 1729 tcc_add_include_path(s, optarg); 1773 1730 break; 1774 1731 case TCC_OPTION_D: … … 1786 1743 break; 1787 1744 case TCC_OPTION_l: 1788 dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r));1745 args_parser_add_file(s, optarg, AFF_TYPE_LIB); 1789 1746 s->nb_libraries++; 1790 1747 break; 1791 1748 case TCC_OPTION_pthread: 1792 1749 parse_option_D(s, "_REENTRANT"); 1793 pthread = 1;1750 s->option_pthread = 1; 1794 1751 break; 1795 1752 case TCC_OPTION_bench: … … 1811 1768 break; 1812 1769 case TCC_OPTION_c: 1813 s->output_type = TCC_OUTPUT_OBJ; 1770 x = TCC_OUTPUT_OBJ; 1771 set_output_type: 1772 if (s->output_type) 1773 tcc_warning("-%s: overriding compiler action already specified", popt->name); 1774 s->output_type = x; 1775 break; 1776 case TCC_OPTION_d: 1777 if (*optarg == 'D') 1778 s->dflag = 3; 1779 else if (*optarg == 'M') 1780 s->dflag = 7; 1781 else if (*optarg == 't') 1782 s->dflag = 16; 1783 else if (isnum(*optarg)) 1784 g_debug = atoi(optarg); 1785 else 1786 goto unsupported_option; 1814 1787 break; 1815 1788 case TCC_OPTION_static: 1816 1789 s->static_link = 1; 1817 1790 break; 1791 case TCC_OPTION_std: 1792 /* silently ignore, a current purpose: 1793 allow to use a tcc as a reference compiler for "make test" */ 1794 break; 1818 1795 case TCC_OPTION_shared: 1819 s->output_type= TCC_OUTPUT_DLL;1820 break;1796 x = TCC_OUTPUT_DLL; 1797 goto set_output_type; 1821 1798 case TCC_OPTION_soname: 1822 1799 s->soname = tcc_strdup(optarg); 1823 1800 break; 1824 case TCC_OPTION_m:1825 s->option_m = tcc_strdup(optarg);1826 break;1827 1801 case TCC_OPTION_o: 1802 if (s->outfile) { 1803 tcc_warning("multiple -o option"); 1804 tcc_free(s->outfile); 1805 } 1828 1806 s->outfile = tcc_strdup(optarg); 1829 1807 break; … … 1831 1809 /* generate a .o merging several output files */ 1832 1810 s->option_r = 1; 1833 s->output_type= TCC_OUTPUT_OBJ;1834 break;1811 x = TCC_OUTPUT_OBJ; 1812 goto set_output_type; 1835 1813 case TCC_OPTION_isystem: 1836 1814 tcc_add_sysinclude_path(s, optarg); 1837 1815 break; 1816 case TCC_OPTION_include: 1817 dynarray_add(&s->cmd_include_files, 1818 &s->nb_cmd_include_files, tcc_strdup(optarg)); 1819 break; 1838 1820 case TCC_OPTION_nostdinc: 1839 1821 s->nostdinc = 1; … … 1842 1824 s->nostdlib = 1; 1843 1825 break; 1844 case TCC_OPTION_print_search_dirs:1845 s->print_search_dirs = 1;1846 break;1847 1826 case TCC_OPTION_run: 1848 s->output_type = TCC_OUTPUT_MEMORY; 1849 tcc_set_options(s, optarg); 1850 run = 1; 1851 break; 1827 #ifndef TCC_IS_NATIVE 1828 tcc_error("-run is not available in a cross compiler"); 1829 #endif 1830 run = optarg; 1831 x = TCC_OUTPUT_MEMORY; 1832 goto set_output_type; 1852 1833 case TCC_OPTION_v: 1853 1834 do ++s->verbose; while (*optarg++ == 'v'); 1835 ++noaction; 1854 1836 break; 1855 1837 case TCC_OPTION_f: 1856 if ( tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)1838 if (set_flag(s, options_f, optarg) < 0) 1857 1839 goto unsupported_option; 1858 1840 break; 1841 #ifdef TCC_TARGET_ARM 1842 case TCC_OPTION_mfloat_abi: 1843 /* tcc doesn't support soft float yet */ 1844 if (!strcmp(optarg, "softfp")) { 1845 s->float_abi = ARM_SOFTFP_FLOAT; 1846 tcc_undefine_symbol(s, "__ARM_PCS_VFP"); 1847 } else if (!strcmp(optarg, "hard")) 1848 s->float_abi = ARM_HARD_FLOAT; 1849 else 1850 tcc_error("unsupported float abi '%s'", optarg); 1851 break; 1852 #endif 1853 case TCC_OPTION_m: 1854 if (set_flag(s, options_m, optarg) < 0) { 1855 if (x = atoi(optarg), x != 32 && x != 64) 1856 goto unsupported_option; 1857 if (PTR_SIZE != x/8) 1858 return x; 1859 ++noaction; 1860 } 1861 break; 1859 1862 case TCC_OPTION_W: 1860 if (tcc_set_warning(s, optarg, 1) < 0 && 1861 s->warn_unsupported) 1863 if (set_flag(s, options_W, optarg) < 0) 1862 1864 goto unsupported_option; 1863 1865 break; … … 1871 1873 if (linker_arg.size) 1872 1874 --linker_arg.size, cstr_ccat(&linker_arg, ','); 1873 cstr_cat(&linker_arg, optarg); 1874 cstr_ccat(&linker_arg, '\0'); 1875 break; 1875 cstr_cat(&linker_arg, optarg, 0); 1876 if (tcc_set_linker(s, linker_arg.data)) 1877 cstr_free(&linker_arg); 1878 break; 1879 case TCC_OPTION_Wp: 1880 r = optarg; 1881 goto reparse; 1876 1882 case TCC_OPTION_E: 1877 s->output_type = TCC_OUTPUT_PREPROCESS; 1883 x = TCC_OUTPUT_PREPROCESS; 1884 goto set_output_type; 1885 case TCC_OPTION_P: 1886 s->Pflag = atoi(optarg) + 1; 1878 1887 break; 1879 1888 case TCC_OPTION_MD: … … 1886 1895 printf ("%s\n", TCC_VERSION); 1887 1896 exit(0); 1897 break; 1898 case TCC_OPTION_x: 1899 if (*optarg == 'c') 1900 s->filetype = AFF_TYPE_C; 1901 else if (*optarg == 'a') 1902 s->filetype = AFF_TYPE_ASMPP; 1903 else if (*optarg == 'n') 1904 s->filetype = AFF_TYPE_NONE; 1905 else 1906 tcc_warning("unsupported language '%s'", optarg); 1907 break; 1888 1908 case TCC_OPTION_O: 1909 last_o = atoi(optarg); 1910 break; 1911 case TCC_OPTION_print_search_dirs: 1912 x = OPT_PRINT_DIRS; 1913 goto extra_action; 1914 case TCC_OPTION_impdef: 1915 x = OPT_IMPDEF; 1916 goto extra_action; 1917 case TCC_OPTION_ar: 1918 x = OPT_AR; 1919 extra_action: 1920 arg_start = optind - 1; 1921 if (arg_start != noaction) 1922 tcc_error("cannot parse %s here", r); 1923 tool = x; 1924 break; 1925 case TCC_OPTION_traditional: 1889 1926 case TCC_OPTION_pedantic: 1890 1927 case TCC_OPTION_pipe: 1891 1928 case TCC_OPTION_s: 1892 case TCC_OPTION_x:1893 1929 /* ignored */ 1894 1930 break; 1895 1931 default: 1896 if (s->warn_unsupported) { 1897 unsupported_option:1932 unsupported_option: 1933 if (s->warn_unsupported) 1898 1934 tcc_warning("unsupported option '%s'", r); 1899 }1900 1935 break; 1901 1936 } 1902 1937 } 1903 1904 if (pthread && s->output_type != TCC_OUTPUT_OBJ) 1905 tcc_set_options(s, "-lpthread"); 1906 1907 tcc_set_linker(s, (const char *)linker_arg.data); 1908 cstr_free(&linker_arg); 1909 1910 return optind; 1911 } 1912 1913 LIBTCCAPI int tcc_set_options(TCCState *s, const char *str) 1914 { 1915 const char *s1; 1916 char **argv, *arg; 1917 int argc, len; 1918 int ret; 1919 1920 argc = 0, argv = NULL; 1921 for(;;) { 1922 while (is_space(*str)) 1923 str++; 1924 if (*str == '\0') 1925 break; 1926 s1 = str; 1927 while (*str != '\0' && !is_space(*str)) 1928 str++; 1929 len = str - s1; 1930 arg = tcc_malloc(len + 1); 1931 pstrncpy(arg, s1, len); 1932 dynarray_add((void ***)&argv, &argc, arg); 1933 } 1934 ret = tcc_parse_args(s, argc, argv); 1938 if (last_o > 0) 1939 tcc_define_symbol(s, "__OPTIMIZE__", NULL); 1940 if (linker_arg.size) { 1941 r = linker_arg.data; 1942 goto arg_err; 1943 } 1944 *pargc = argc - arg_start; 1945 *pargv = argv + arg_start; 1946 if (tool) 1947 return tool; 1948 if (optind != noaction) 1949 return 0; 1950 if (s->verbose == 2) 1951 return OPT_PRINT_DIRS; 1952 if (s->verbose) 1953 return OPT_V; 1954 return OPT_HELP; 1955 } 1956 1957 LIBTCCAPI void tcc_set_options(TCCState *s, const char *r) 1958 { 1959 char **argv = NULL; 1960 int argc = 0; 1961 args_parser_make_argv(r, &argc, &argv); 1962 tcc_parse_args(s, &argc, &argv, 0); 1935 1963 dynarray_reset(&argv, &argc); 1936 return ret; 1937 } 1938 1939 PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time) 1940 { 1941 double tt; 1942 tt = (double)total_time / 1000000.0; 1943 if (tt < 0.001) 1944 tt = 0.001; 1964 } 1965 1966 PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time) 1967 { 1968 if (total_time < 1) 1969 total_time = 1; 1945 1970 if (total_bytes < 1) 1946 1971 total_bytes = 1; 1947 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n", 1972 fprintf(stderr, "* %d idents, %d lines, %d bytes\n" 1973 "* %0.3f s, %u lines/s, %0.1f MB/s\n", 1948 1974 tok_ident - TOK_IDENT, total_lines, total_bytes, 1949 tt, (int)(total_lines / tt), 1950 total_bytes / tt / 1000000.0); 1951 } 1975 (double)total_time/1000, 1976 (unsigned)total_lines*1000/total_time, 1977 (double)total_bytes/1000/total_time); 1978 #ifdef MEM_DEBUG 1979 fprintf(stderr, "* %d bytes memory used\n", mem_max_size); 1980 #endif 1981 } -
EcnlProtoTool/trunk/tcc-0.9.27/libtcc.h
r321 r331 28 28 29 29 /* set options as from command line (multiple supported) */ 30 LIBTCCAPI inttcc_set_options(TCCState *s, const char *str);30 LIBTCCAPI void tcc_set_options(TCCState *s, const char *str); 31 31 32 32 /*****************************/ … … 59 59 /* set output type. MUST BE CALLED before any compilation */ 60 60 LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type); 61 #define TCC_OUTPUT_MEMORY 0/* output will be run in memory (default) */62 #define TCC_OUTPUT_EXE 1/* executable file */63 #define TCC_OUTPUT_DLL 2/* dynamic library */64 #define TCC_OUTPUT_OBJ 3/* object file */65 #define TCC_OUTPUT_PREPROCESS 4/* only preprocess (used internally) */61 #define TCC_OUTPUT_MEMORY 1 /* output will be run in memory (default) */ 62 #define TCC_OUTPUT_EXE 2 /* executable file */ 63 #define TCC_OUTPUT_DLL 3 /* dynamic library */ 64 #define TCC_OUTPUT_OBJ 4 /* object file */ 65 #define TCC_OUTPUT_PREPROCESS 5 /* only preprocess (used internally) */ 66 66 67 67 /* equivalent to -Lpath option */ -
EcnlProtoTool/trunk/tcc-0.9.27/stab.def
- Property svn:keywords deleted
-
EcnlProtoTool/trunk/tcc-0.9.27/tcc-doc.html
- Property svn:keywords deleted
r279 r331 1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html401/loose.dtd"> 2 <html> 3 <!-- Created on February 15, 2013 by texi2html 1.82 4 texi2html was written by: 5 Lionel Cons <Lionel.Cons@cern.ch> (original author) 6 Karl Berry <karl@freefriends.org> 7 Olaf Bachmann <obachman@mathematik.uni-kl.de> 8 and many others. 9 Maintained by: Many creative people. 10 Send bugs and suggestions to <texi2html-bug@nongnu.org> 1 <HTML> 2 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 3 <!-- Created on December, 17 2017 by texi2html 1.64 --> 4 <!-- 5 Written by: Lionel Cons <Lionel.Cons@cern.ch> (original author) 6 Karl Berry <karl@freefriends.org> 7 Olaf Bachmann <obachman@mathematik.uni-kl.de> 8 and many others. 9 Maintained by: Olaf Bachmann <obachman@mathematik.uni-kl.de> 10 Send bugs and suggestions to <texi2html@mathematik.uni-kl.de> 11 11 12 --> 12 <head> 13 <title>Tiny C Compiler Reference Documentation</title> 14 15 <meta name="description" content="Tiny C Compiler Reference Documentation"> 16 <meta name="keywords" content="Tiny C Compiler Reference Documentation"> 17 <meta name="resource-type" content="document"> 18 <meta name="distribution" content="global"> 19 <meta name="Generator" content="texi2html 1.82"> 20 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 21 <style type="text/css"> 22 <!-- 23 a.summary-letter {text-decoration: none} 24 blockquote.smallquotation {font-size: smaller} 25 pre.display {font-family: serif} 26 pre.format {font-family: serif} 27 pre.menu-comment {font-family: serif} 28 pre.menu-preformatted {font-family: serif} 29 pre.smalldisplay {font-family: serif; font-size: smaller} 30 pre.smallexample {font-size: smaller} 31 pre.smallformat {font-family: serif; font-size: smaller} 32 pre.smalllisp {font-size: smaller} 33 span.roman {font-family:serif; font-weight:normal;} 34 span.sansserif {font-family:sans-serif; font-weight:normal;} 35 ul.toc {list-style: none} 36 --> 37 </style> 38 39 40 </head> 41 42 <body lang="en" bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000"> 43 44 <a name="Top"></a> 45 <table cellpadding="1" cellspacing="1" border="0"> 46 <tr><td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 47 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 48 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 49 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 50 </tr></table> 51 <a name="Tiny-C-Compiler-Reference-Documentation"></a> 52 <h1 class="settitle">Tiny C Compiler Reference Documentation</h1> 53 54 <p>This manual documents version 0.9.26 of the Tiny C Compiler. 55 </p> 56 <table class="menu" border="0" cellspacing="0"> 57 <tr><td align="left" valign="top"><a href="#Introduction">1. Introduction</a></td><td> </td><td align="left" valign="top"> Introduction to tcc. 58 </td></tr> 59 <tr><td align="left" valign="top"><a href="#Invoke">2. Command line invocation</a></td><td> </td><td align="left" valign="top"> Invocation of tcc (command line, options). 60 </td></tr> 61 <tr><td align="left" valign="top"><a href="#Clang">3. C language support</a></td><td> </td><td align="left" valign="top"> ANSI C and extensions. 62 </td></tr> 63 <tr><td align="left" valign="top"><a href="#asm">4. TinyCC Assembler</a></td><td> </td><td align="left" valign="top"> Assembler syntax. 64 </td></tr> 65 <tr><td align="left" valign="top"><a href="#linker">5. TinyCC Linker</a></td><td> </td><td align="left" valign="top"> Output file generation and supported targets. 66 </td></tr> 67 <tr><td align="left" valign="top"><a href="#Bounds">6. TinyCC Memory and Bound checks</a></td><td> </td><td align="left" valign="top"> Automatic bounds-checking of C code. 68 </td></tr> 69 <tr><td align="left" valign="top"><a href="#Libtcc">7. The <code>libtcc</code> library</a></td><td> </td><td align="left" valign="top"> The libtcc library. 70 </td></tr> 71 <tr><td align="left" valign="top"><a href="#devel">8. Developer’s guide</a></td><td> </td><td align="left" valign="top"> Guide for Developers. 72 </td></tr> 73 </table> 74 75 76 <hr size="1"> 77 <a name="Introduction"></a> 78 <table cellpadding="1" cellspacing="1" border="0"> 79 <tr><td valign="middle" align="left">[<a href="#Top" title="Previous section in reading order"> < </a>]</td> 80 <td valign="middle" align="left">[<a href="#Invoke" title="Next section in reading order"> > </a>]</td> 81 <td valign="middle" align="left"> </td> 82 <td valign="middle" align="left">[<a href="#Top" title="Beginning of this chapter or previous chapter"> << </a>]</td> 83 <td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td> 84 <td valign="middle" align="left">[<a href="#Invoke" title="Next chapter"> >> </a>]</td> 85 <td valign="middle" align="left"> </td> 86 <td valign="middle" align="left"> </td> 87 <td valign="middle" align="left"> </td> 88 <td valign="middle" align="left"> </td> 89 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 90 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 91 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 92 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 93 </tr></table> 94 <a name="Introduction-1"></a> 95 <h1 class="chapter">1. Introduction</h1> 96 97 <p>TinyCC (aka TCC) is a small but hyper fast C compiler. Unlike other C 13 <HEAD> 14 <TITLE>Tiny C Compiler Reference Documentation: </TITLE> 15 16 <META NAME="description" CONTENT="Tiny C Compiler Reference Documentation: "> 17 <META NAME="keywords" CONTENT="Tiny C Compiler Reference Documentation: "> 18 <META NAME="resource-type" CONTENT="document"> 19 <META NAME="distribution" CONTENT="global"> 20 <META NAME="Generator" CONTENT="texi2html 1.64"> 21 22 </HEAD> 23 24 <BODY LANG="" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080" ALINK="#FF0000"> 25 26 <A NAME="SEC_Top"></A> 27 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 28 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 29 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 30 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 31 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 32 </TR></TABLE> 33 <H1>Tiny C Compiler Reference Documentation</H1></P><P> 34 35 This manual documents version 0.9.27 36 of the Tiny C Compiler. 37 </P><P> 38 39 <BLOCKQUOTE><TABLE BORDER=0 CELLSPACING=0> 40 <TR><TD ALIGN="left" VALIGN="TOP"><A HREF="tcc-doc.html#SEC1">1. Introduction</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">Introduction to tcc.</TD></TR> 41 <TR><TD ALIGN="left" VALIGN="TOP"><A HREF="tcc-doc.html#SEC2">2. Command line invocation</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">Invocation of tcc (command line, options).</TD></TR> 42 <TR><TD ALIGN="left" VALIGN="TOP"><A HREF="tcc-doc.html#SEC5">3. C language support</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">ANSI C and extensions.</TD></TR> 43 <TR><TD ALIGN="left" VALIGN="TOP"><A HREF="tcc-doc.html#SEC10">4. TinyCC Assembler</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">Assembler syntax.</TD></TR> 44 <TR><TD ALIGN="left" VALIGN="TOP"><A HREF="tcc-doc.html#SEC16">5. TinyCC Linker</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">Output file generation and supported targets.</TD></TR> 45 <TR><TD ALIGN="left" VALIGN="TOP"><A HREF="tcc-doc.html#SEC21">6. TinyCC Memory and Bound checks</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">Automatic bounds-checking of C code.</TD></TR> 46 <TR><TD ALIGN="left" VALIGN="TOP"><A HREF="tcc-doc.html#SEC22">7. The <CODE>libtcc</CODE> library</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">The libtcc library.</TD></TR> 47 <TR><TD ALIGN="left" VALIGN="TOP"><A HREF="tcc-doc.html#SEC23">8. Developer's guide</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">Guide for Developers.</TD></TR> 48 </TABLE></BLOCKQUOTE> 49 <P> 50 51 <HR SIZE=1> 52 <A NAME="SEC1"></A> 53 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 54 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top"> < </A>]</TD> 55 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC2"> > </A>]</TD> 56 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD> 57 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top"> Up </A>]</TD> 58 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC2"> >> </A>]</TD> 59 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 60 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 61 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 62 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 63 </TR></TABLE> 64 <A NAME="Introduction"></A> 65 <H1> 1. Introduction </H1> 66 <!--docid::SEC1::--> 67 <P> 68 69 TinyCC (aka TCC) is a small but hyper fast C compiler. Unlike other C 98 70 compilers, it is meant to be self-relying: you do not need an 99 71 external assembler or linker because TCC does that for you. 100 </p> 101 <p>TCC compiles so <em>fast</em> that even for big projects <code>Makefile</code>s may 72 </P><P> 73 74 TCC compiles so <EM>fast</EM> that even for big projects <CODE>Makefile</CODE>s may 102 75 not be necessary. 103 </p> 104 <p>TCC not only supports ANSI C, but also most of the new ISO C99 76 </P><P> 77 78 TCC not only supports ANSI C, but also most of the new ISO C99 105 79 standard and many GNUC extensions including inline assembly. 106 </p> 107 <p>TCC can also be used to make <em>C scripts</em>, i.e. pieces of C source 80 </P><P> 81 82 TCC can also be used to make <EM>C scripts</EM>, i.e. pieces of C source 108 83 that you run as a Perl or Python script. Compilation is so fast that 109 84 your script will be as fast as if it was an executable. 110 </p> 111 <p>TCC can also automatically generate memory and bound checks 112 (see section <a href="#Bounds">TinyCC Memory and Bound checks</a>) while allowing all C pointers operations. TCC can do 85 </P><P> 86 87 TCC can also automatically generate memory and bound checks 88 (see section <A HREF="tcc-doc.html#SEC21">6. TinyCC Memory and Bound checks</A>) while allowing all C pointers operations. TCC can do 113 89 these checks even if non patched libraries are used. 114 </p> 115 <p>With <code>libtcc</code>, you can use TCC as a backend for dynamic code 116 generation (see section <a href="#Libtcc">The <code>libtcc</code> library</a>). 117 </p> 118 <p>TCC mainly supports the i386 target on Linux and Windows. There are alpha 119 ports for the ARM (<code>arm-tcc</code>) and the TMS320C67xx targets 120 (<code>c67-tcc</code>). More information about the ARM port is available at 121 <a href="http://lists.gnu.org/archive/html/tinycc-devel/2003-10/msg00044.html">http://lists.gnu.org/archive/html/tinycc-devel/2003-10/msg00044.html</a>. 122 </p> 123 <p>For usage on Windows, see also <a href="tcc-win32.txt">tcc-win32.txt</a>. 124 </p> 125 <hr size="6"> 126 <a name="Invoke"></a> 127 <table cellpadding="1" cellspacing="1" border="0"> 128 <tr><td valign="middle" align="left">[<a href="#Introduction" title="Previous section in reading order"> < </a>]</td> 129 <td valign="middle" align="left">[<a href="#Quick-start" title="Next section in reading order"> > </a>]</td> 130 <td valign="middle" align="left"> </td> 131 <td valign="middle" align="left">[<a href="#Introduction" title="Beginning of this chapter or previous chapter"> << </a>]</td> 132 <td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td> 133 <td valign="middle" align="left">[<a href="#Clang" title="Next chapter"> >> </a>]</td> 134 <td valign="middle" align="left"> </td> 135 <td valign="middle" align="left"> </td> 136 <td valign="middle" align="left"> </td> 137 <td valign="middle" align="left"> </td> 138 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 139 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 140 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 141 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 142 </tr></table> 143 <a name="Command-line-invocation"></a> 144 <h1 class="chapter">2. Command line invocation</h1> 145 146 <hr size="6"> 147 <a name="Quick-start"></a> 148 <table cellpadding="1" cellspacing="1" border="0"> 149 <tr><td valign="middle" align="left">[<a href="#Invoke" title="Previous section in reading order"> < </a>]</td> 150 <td valign="middle" align="left">[<a href="#Option-summary" title="Next section in reading order"> > </a>]</td> 151 <td valign="middle" align="left"> </td> 152 <td valign="middle" align="left">[<a href="#Invoke" title="Beginning of this chapter or previous chapter"> << </a>]</td> 153 <td valign="middle" align="left">[<a href="#Invoke" title="Up section"> Up </a>]</td> 154 <td valign="middle" align="left">[<a href="#Clang" title="Next chapter"> >> </a>]</td> 155 <td valign="middle" align="left"> </td> 156 <td valign="middle" align="left"> </td> 157 <td valign="middle" align="left"> </td> 158 <td valign="middle" align="left"> </td> 159 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 160 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 161 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 162 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 163 </tr></table> 164 <h2 class="section">2.1 Quick start</h2> 165 166 <table><tr><td> </td><td><pre class="example">usage: tcc [options] [<var>infile1</var> <var>infile2</var>…] [‘<samp>-run</samp>’ <var>infile</var> <var>args</var>…] 167 </pre></td></tr></table> 168 169 <p>TCC options are a very much like gcc options. The main difference is that TCC 90 </P><P> 91 92 With <CODE>libtcc</CODE>, you can use TCC as a backend for dynamic code 93 generation (see section <A HREF="tcc-doc.html#SEC22">7. The <CODE>libtcc</CODE> library</A>). 94 </P><P> 95 96 TCC mainly supports the i386 target on Linux and Windows. There are alpha 97 ports for the ARM (<CODE>arm-tcc</CODE>) and the TMS320C67xx targets 98 (<CODE>c67-tcc</CODE>). More information about the ARM port is available at 99 <A HREF="http://lists.gnu.org/archive/html/tinycc-devel/2003-10/msg00044.html">http://lists.gnu.org/archive/html/tinycc-devel/2003-10/msg00044.html</A>. 100 </P><P> 101 102 For usage on Windows, see also <A HREF="tcc-win32.txt">tcc-win32.txt</A>. 103 </P><P> 104 105 <A NAME="Invoke"></A> 106 <HR SIZE="6"> 107 <A NAME="SEC2"></A> 108 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 109 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC1"> < </A>]</TD> 110 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC3"> > </A>]</TD> 111 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC5"> << </A>]</TD> 112 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top"> Up </A>]</TD> 113 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC5"> >> </A>]</TD> 114 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 115 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 116 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 117 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 118 </TR></TABLE> 119 <H1> 2. Command line invocation </H1> 120 <!--docid::SEC2::--> 121 <P> 122 123 <HR SIZE="6"> 124 <A NAME="SEC3"></A> 125 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 126 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC2"> < </A>]</TD> 127 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC4"> > </A>]</TD> 128 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC2"> << </A>]</TD> 129 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC2"> Up </A>]</TD> 130 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC5"> >> </A>]</TD> 131 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 132 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 133 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 134 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 135 </TR></TABLE> 136 <H2> 2.1 Quick start </H2> 137 <!--docid::SEC3::--> 138 <P> 139 140 <TABLE><tr><td> </td><td class=example><pre>usage: tcc [options] [<VAR>infile1</VAR> <VAR>infile2</VAR><small>...</small>] [<SAMP>`-run'</SAMP> <VAR>infile</VAR> <VAR>args</VAR><small>...</small>] 141 </pre></td></tr></table></P><P> 142 143 TCC options are a very much like gcc options. The main difference is that TCC 170 144 can also execute directly the resulting program and give it runtime 171 145 arguments. 172 </p> 173 <p>Here are some examples to understand the logic: 174 </p> 175 <dl compact="compact"> 176 <dt> <code>‘<samp>tcc -run a.c</samp>’</code></dt> 177 <dd><p>Compile ‘<tt>a.c</tt>’ and execute it directly 178 </p> 179 </dd> 180 <dt> <code>‘<samp>tcc -run a.c arg1</samp>’</code></dt> 181 <dd><p>Compile a.c and execute it directly. arg1 is given as first argument to 182 the <code>main()</code> of a.c. 183 </p> 184 </dd> 185 <dt> <code>‘<samp>tcc a.c -run b.c arg1</samp>’</code></dt> 186 <dd><p>Compile ‘<tt>a.c</tt>’ and ‘<tt>b.c</tt>’, link them together and execute them. arg1 is given 187 as first argument to the <code>main()</code> of the resulting program. 188 </p> 189 </dd> 190 <dt> <code>‘<samp>tcc -o myprog a.c b.c</samp>’</code></dt> 191 <dd><p>Compile ‘<tt>a.c</tt>’ and ‘<tt>b.c</tt>’, link them and generate the executable ‘<tt>myprog</tt>’. 192 </p> 193 </dd> 194 <dt> <code>‘<samp>tcc -o myprog a.o b.o</samp>’</code></dt> 195 <dd><p>link ‘<tt>a.o</tt>’ and ‘<tt>b.o</tt>’ together and generate the executable ‘<tt>myprog</tt>’. 196 </p> 197 </dd> 198 <dt> <code>‘<samp>tcc -c a.c</samp>’</code></dt> 199 <dd><p>Compile ‘<tt>a.c</tt>’ and generate object file ‘<tt>a.o</tt>’. 200 </p> 201 </dd> 202 <dt> <code>‘<samp>tcc -c asmfile.S</samp>’</code></dt> 203 <dd><p>Preprocess with C preprocess and assemble ‘<tt>asmfile.S</tt>’ and generate 204 object file ‘<tt>asmfile.o</tt>’. 205 </p> 206 </dd> 207 <dt> <code>‘<samp>tcc -c asmfile.s</samp>’</code></dt> 208 <dd><p>Assemble (but not preprocess) ‘<tt>asmfile.s</tt>’ and generate object file 209 ‘<tt>asmfile.o</tt>’. 210 </p> 211 </dd> 212 <dt> <code>‘<samp>tcc -r -o ab.o a.c b.c</samp>’</code></dt> 213 <dd><p>Compile ‘<tt>a.c</tt>’ and ‘<tt>b.c</tt>’, link them together and generate the object file ‘<tt>ab.o</tt>’. 214 </p> 215 </dd> 216 </dl> 217 218 <p>Scripting: 219 </p> 220 <p>TCC can be invoked from <em>scripts</em>, just as shell scripts. You just 221 need to add <code>#!/usr/local/bin/tcc -run</code> at the start of your C source: 222 </p> 223 <table><tr><td> </td><td><pre class="example">#!/usr/local/bin/tcc -run 224 #include <stdio.h> 146 </P><P> 147 148 Here are some examples to understand the logic: 149 </P><P> 150 151 <DL COMPACT> 152 <DT><CODE><SAMP>`tcc -run a.c'</SAMP></CODE> 153 <DD>Compile <TT>`a.c'</TT> and execute it directly 154 <P> 155 156 <DT><CODE><SAMP>`tcc -run a.c arg1'</SAMP></CODE> 157 <DD>Compile a.c and execute it directly. arg1 is given as first argument to 158 the <CODE>main()</CODE> of a.c. 159 <P> 160 161 <DT><CODE><SAMP>`tcc a.c -run b.c arg1'</SAMP></CODE> 162 <DD>Compile <TT>`a.c'</TT> and <TT>`b.c'</TT>, link them together and execute them. arg1 is given 163 as first argument to the <CODE>main()</CODE> of the resulting program. 164 <P> 165 166 <DT><CODE><SAMP>`tcc -o myprog a.c b.c'</SAMP></CODE> 167 <DD>Compile <TT>`a.c'</TT> and <TT>`b.c'</TT>, link them and generate the executable <TT>`myprog'</TT>. 168 <P> 169 170 <DT><CODE><SAMP>`tcc -o myprog a.o b.o'</SAMP></CODE> 171 <DD>link <TT>`a.o'</TT> and <TT>`b.o'</TT> together and generate the executable <TT>`myprog'</TT>. 172 <P> 173 174 <DT><CODE><SAMP>`tcc -c a.c'</SAMP></CODE> 175 <DD>Compile <TT>`a.c'</TT> and generate object file <TT>`a.o'</TT>. 176 <P> 177 178 <DT><CODE><SAMP>`tcc -c asmfile.S'</SAMP></CODE> 179 <DD>Preprocess with C preprocess and assemble <TT>`asmfile.S'</TT> and generate 180 object file <TT>`asmfile.o'</TT>. 181 <P> 182 183 <DT><CODE><SAMP>`tcc -c asmfile.s'</SAMP></CODE> 184 <DD>Assemble (but not preprocess) <TT>`asmfile.s'</TT> and generate object file 185 <TT>`asmfile.o'</TT>. 186 <P> 187 188 <DT><CODE><SAMP>`tcc -r -o ab.o a.c b.c'</SAMP></CODE> 189 <DD>Compile <TT>`a.c'</TT> and <TT>`b.c'</TT>, link them together and generate the object file <TT>`ab.o'</TT>. 190 <P> 191 192 </DL> 193 <P> 194 195 Scripting: 196 </P><P> 197 198 TCC can be invoked from <EM>scripts</EM>, just as shell scripts. You just 199 need to add <CODE>#!/usr/local/bin/tcc -run</CODE> at the start of your C source: 200 </P><P> 201 202 <TABLE><tr><td> </td><td class=example><pre>#!/usr/local/bin/tcc -run 203 #include <stdio.h> 225 204 226 205 int main() 227 206 { 228 printf( "Hello World\n");207 printf("Hello World\n"); 229 208 return 0; 230 209 } 231 </pre></td></tr></table> 232 233 <p>TCC can read C source code from <em>standard input</em> when ‘<samp>-</samp>’ is used in 234 place of ‘<samp>infile</samp>’. Example: 235 </p> 236 <table><tr><td> </td><td><pre class="example">echo 'main(){puts("hello");}' | tcc -run - 237 </pre></td></tr></table> 238 239 <hr size="6"> 240 <a name="Option-summary"></a> 241 <table cellpadding="1" cellspacing="1" border="0"> 242 <tr><td valign="middle" align="left">[<a href="#Quick-start" title="Previous section in reading order"> < </a>]</td> 243 <td valign="middle" align="left">[<a href="#Clang" title="Next section in reading order"> > </a>]</td> 244 <td valign="middle" align="left"> </td> 245 <td valign="middle" align="left">[<a href="#Invoke" title="Beginning of this chapter or previous chapter"> << </a>]</td> 246 <td valign="middle" align="left">[<a href="#Invoke" title="Up section"> Up </a>]</td> 247 <td valign="middle" align="left">[<a href="#Clang" title="Next chapter"> >> </a>]</td> 248 <td valign="middle" align="left"> </td> 249 <td valign="middle" align="left"> </td> 250 <td valign="middle" align="left"> </td> 251 <td valign="middle" align="left"> </td> 252 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 253 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 254 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 255 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 256 </tr></table> 257 <h2 class="section">2.2 Option summary</h2> 258 259 <p>General Options: 260 </p> 261 <dl compact="compact"> 262 <dt> ‘<samp>-c</samp>’</dt> 263 <dd><p>Generate an object file. 264 </p> 265 </dd> 266 <dt> ‘<samp>-o outfile</samp>’</dt> 267 <dd><p>Put object file, executable, or dll into output file ‘<tt>outfile</tt>’. 268 </p> 269 </dd> 270 <dt> ‘<samp>-run source [args...]</samp>’</dt> 271 <dd><p>Compile file <var>source</var> and run it with the command line arguments 272 <var>args</var>. In order to be able to give more than one argument to a 273 script, several TCC options can be given <em>after</em> the 274 ‘<samp>-run</samp>’ option, separated by spaces: 275 </p><table><tr><td> </td><td><pre class="example">tcc "-run -L/usr/X11R6/lib -lX11" ex4.c 276 </pre></td></tr></table> 277 <p>In a script, it gives the following header: 278 </p><table><tr><td> </td><td><pre class="example">#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11 279 </pre></td></tr></table> 280 281 </dd> 282 <dt> ‘<samp>-dumpversion</samp>’</dt> 283 <dd><p>Print only the compiler version and nothing else. 284 </p> 285 </dd> 286 <dt> ‘<samp>-v</samp>’</dt> 287 <dd><p>Display TCC version. 288 </p> 289 </dd> 290 <dt> ‘<samp>-vv</samp>’</dt> 291 <dd><p>Show included files. As sole argument, print search dirs (as below). 292 </p> 293 </dd> 294 <dt> ‘<samp>-bench</samp>’</dt> 295 <dd><p>Display compilation statistics. 296 </p> 297 </dd> 298 <dt> ‘<samp>-print-search-dirs</samp>’</dt> 299 <dd><p>Print the configured installation directory and a list of library 210 </pre></td></tr></table></P><P> 211 212 TCC can read C source code from <EM>standard input</EM> when <SAMP>`-'</SAMP> is used in 213 place of <SAMP>`infile'</SAMP>. Example: 214 </P><P> 215 216 <TABLE><tr><td> </td><td class=example><pre>echo 'main(){puts("hello");}' | tcc -run - 217 </pre></td></tr></table></P><P> 218 219 <HR SIZE="6"> 220 <A NAME="SEC4"></A> 221 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 222 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC3"> < </A>]</TD> 223 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC5"> > </A>]</TD> 224 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC2"> << </A>]</TD> 225 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC2"> Up </A>]</TD> 226 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC5"> >> </A>]</TD> 227 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 228 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 229 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 230 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 231 </TR></TABLE> 232 <H2> 2.2 Option summary </H2> 233 <!--docid::SEC4::--> 234 <P> 235 236 General Options: 237 </P><P> 238 239 <DL COMPACT> 240 <DT><SAMP>`-c'</SAMP> 241 <DD>Generate an object file. 242 <P> 243 244 <DT><SAMP>`-o outfile'</SAMP> 245 <DD>Put object file, executable, or dll into output file <TT>`outfile'</TT>. 246 <P> 247 248 <DT><SAMP>`-run source [args...]'</SAMP> 249 <DD>Compile file <VAR>source</VAR> and run it with the command line arguments 250 <VAR>args</VAR>. In order to be able to give more than one argument to a 251 script, several TCC options can be given <EM>after</EM> the 252 <SAMP>`-run'</SAMP> option, separated by spaces: 253 <TABLE><tr><td> </td><td class=example><pre>tcc "-run -L/usr/X11R6/lib -lX11" ex4.c 254 </pre></td></tr></table>In a script, it gives the following header: 255 <TABLE><tr><td> </td><td class=example><pre>#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11 256 </pre></td></tr></table><P> 257 258 <DT><SAMP>`-v'</SAMP> 259 <DD>Display TCC version. 260 <P> 261 262 <DT><SAMP>`-vv'</SAMP> 263 <DD>Show included files. As sole argument, print search dirs. -vvv shows tries too. 264 <P> 265 266 <DT><SAMP>`-bench'</SAMP> 267 <DD>Display compilation statistics. 268 <P> 269 270 </DL> 271 <P> 272 273 Preprocessor options: 274 </P><P> 275 276 <DL COMPACT> 277 <DT><SAMP>`-Idir'</SAMP> 278 <DD>Specify an additional include path. Include paths are searched in the 279 order they are specified. 280 <P> 281 282 System include paths are always searched after. The default system 283 include paths are: <TT>`/usr/local/include'</TT>, <TT>`/usr/include'</TT> 284 and <TT>`PREFIX/lib/tcc/include'</TT>. (<TT>`PREFIX'</TT> is usually 285 <TT>`/usr'</TT> or <TT>`/usr/local'</TT>). 286 </P><P> 287 288 <DT><SAMP>`-Dsym[=val]'</SAMP> 289 <DD>Define preprocessor symbol <SAMP>`sym'</SAMP> to 290 val. If val is not present, its value is <SAMP>`1'</SAMP>. Function-like macros can 291 also be defined: <SAMP>`-DF(a)=a+1'</SAMP> 292 <P> 293 294 <DT><SAMP>`-Usym'</SAMP> 295 <DD>Undefine preprocessor symbol <SAMP>`sym'</SAMP>. 296 <P> 297 298 <DT><SAMP>`-E'</SAMP> 299 <DD>Preprocess only, to stdout or file (with -o). 300 <P> 301 302 </DL> 303 <P> 304 305 Compilation flags: 306 </P><P> 307 308 Note: each of the following options has a negative form beginning with 309 <SAMP>`-fno-'</SAMP>. 310 </P><P> 311 312 <DL COMPACT> 313 <DT><SAMP>`-funsigned-char'</SAMP> 314 <DD>Let the <CODE>char</CODE> type be unsigned. 315 <P> 316 317 <DT><SAMP>`-fsigned-char'</SAMP> 318 <DD>Let the <CODE>char</CODE> type be signed. 319 <P> 320 321 <DT><SAMP>`-fno-common'</SAMP> 322 <DD>Do not generate common symbols for uninitialized data. 323 <P> 324 325 <DT><SAMP>`-fleading-underscore'</SAMP> 326 <DD>Add a leading underscore at the beginning of each C symbol. 327 <P> 328 329 <DT><SAMP>`-fms-extensions'</SAMP> 330 <DD>Allow a MS C compiler extensions to the language. Currently this 331 assumes a nested named structure declaration without an identifier 332 behaves like an unnamed one. 333 <P> 334 335 <DT><SAMP>`-fdollars-in-identifiers'</SAMP> 336 <DD>Allow dollar signs in identifiers 337 <P> 338 339 </DL> 340 <P> 341 342 Warning options: 343 </P><P> 344 345 <DL COMPACT> 346 <DT><SAMP>`-w'</SAMP> 347 <DD>Disable all warnings. 348 <P> 349 350 </DL> 351 <P> 352 353 Note: each of the following warning options has a negative form beginning with 354 <SAMP>`-Wno-'</SAMP>. 355 </P><P> 356 357 <DL COMPACT> 358 <DT><SAMP>`-Wimplicit-function-declaration'</SAMP> 359 <DD>Warn about implicit function declaration. 360 <P> 361 362 <DT><SAMP>`-Wunsupported'</SAMP> 363 <DD>Warn about unsupported GCC features that are ignored by TCC. 364 <P> 365 366 <DT><SAMP>`-Wwrite-strings'</SAMP> 367 <DD>Make string constants be of type <CODE>const char *</CODE> instead of <CODE>char 368 *</CODE>. 369 <P> 370 371 <DT><SAMP>`-Werror'</SAMP> 372 <DD>Abort compilation if warnings are issued. 373 <P> 374 375 <DT><SAMP>`-Wall'</SAMP> 376 <DD>Activate all warnings, except <SAMP>`-Werror'</SAMP>, <SAMP>`-Wunusupported'</SAMP> and 377 <SAMP>`-Wwrite-strings'</SAMP>. 378 <P> 379 380 </DL> 381 <P> 382 383 Linker options: 384 </P><P> 385 386 <DL COMPACT> 387 <DT><SAMP>`-Ldir'</SAMP> 388 <DD>Specify an additional static library path for the <SAMP>`-l'</SAMP> option. The 389 default library paths are <TT>`/usr/local/lib'</TT>, <TT>`/usr/lib'</TT> and <TT>`/lib'</TT>. 390 <P> 391 392 <DT><SAMP>`-lxxx'</SAMP> 393 <DD>Link your program with dynamic library libxxx.so or static library 394 libxxx.a. The library is searched in the paths specified by the 395 <SAMP>`-L'</SAMP> option and <CODE>LIBRARY_PATH</CODE> variable. 396 <P> 397 398 <DT><SAMP>`-Bdir'</SAMP> 399 <DD>Set the path where the tcc internal libraries (and include files) can be 400 found (default is <TT>`PREFIX/lib/tcc'</TT>). 401 <P> 402 403 <DT><SAMP>`-shared'</SAMP> 404 <DD>Generate a shared library instead of an executable. 405 <P> 406 407 <DT><SAMP>`-soname name'</SAMP> 408 <DD>set name for shared library to be used at runtime 409 <P> 410 411 <DT><SAMP>`-static'</SAMP> 412 <DD>Generate a statically linked executable (default is a shared linked 413 executable). 414 <P> 415 416 <DT><SAMP>`-rdynamic'</SAMP> 417 <DD>Export global symbols to the dynamic linker. It is useful when a library 418 opened with <CODE>dlopen()</CODE> needs to access executable symbols. 419 <P> 420 421 <DT><SAMP>`-r'</SAMP> 422 <DD>Generate an object file combining all input files. 423 <P> 424 425 <DT><SAMP>`-Wl,-rpath=path'</SAMP> 426 <DD>Put custom search path for dynamic libraries into executable. 427 <P> 428 429 <DT><SAMP>`-Wl,--enable-new-dtags'</SAMP> 430 <DD>When putting a custom search path for dynamic libraries into the executable, 431 create the new ELF dynamic tag DT_RUNPATH instead of the old legacy DT_RPATH. 432 <P> 433 434 <DT><SAMP>`-Wl,--oformat=fmt'</SAMP> 435 <DD>Use <VAR>fmt</VAR> as output format. The supported output formats are: 436 <DL COMPACT> 437 <DT><CODE>elf32-i386</CODE> 438 <DD>ELF output format (default) 439 <DT><CODE>binary</CODE> 440 <DD>Binary image (only for executable output) 441 <DT><CODE>coff</CODE> 442 <DD>COFF output format (only for executable output for TMS320C67xx target) 443 </DL> 444 <P> 445 446 <DT><SAMP>`-Wl,-subsystem=console/gui/wince/...'</SAMP> 447 <DD>Set type for PE (Windows) executables. 448 <P> 449 450 <DT><SAMP>`-Wl,-[Ttext=# | section-alignment=# | file-alignment=# | image-base=# | stack=#]'</SAMP> 451 <DD>Modify executable layout. 452 <P> 453 454 <DT><SAMP>`-Wl,-Bsymbolic'</SAMP> 455 <DD>Set DT_SYMBOLIC tag. 456 <P> 457 458 <DT><SAMP>`-Wl,-(no-)whole-archive'</SAMP> 459 <DD>Turn on/off linking of all objects in archives. 460 <P> 461 462 </DL> 463 <P> 464 465 Debugger options: 466 </P><P> 467 468 <DL COMPACT> 469 <DT><SAMP>`-g'</SAMP> 470 <DD>Generate run time debug information so that you get clear run time 471 error messages: <CODE> test.c:68: in function 'test5()': dereferencing 472 invalid pointer</CODE> instead of the laconic <CODE>Segmentation 473 fault</CODE>. 474 <P> 475 476 <DT><SAMP>`-b'</SAMP> 477 <DD>Generate additional support code to check 478 memory allocations and array/pointer bounds. <SAMP>`-g'</SAMP> is implied. Note 479 that the generated code is slower and bigger in this case. 480 <P> 481 482 Note: <SAMP>`-b'</SAMP> is only available on i386 when using libtcc for the moment. 483 </P><P> 484 485 <DT><SAMP>`-bt N'</SAMP> 486 <DD>Display N callers in stack traces. This is useful with <SAMP>`-g'</SAMP> or 487 <SAMP>`-b'</SAMP>. 488 <P> 489 490 </DL> 491 <P> 492 493 Misc options: 494 </P><P> 495 496 <DL COMPACT> 497 <DT><SAMP>`-MD'</SAMP> 498 <DD>Generate makefile fragment with dependencies. 499 <P> 500 501 <DT><SAMP>`-MF depfile'</SAMP> 502 <DD>Use <TT>`depfile'</TT> as output for -MD. 503 <P> 504 505 <DT><SAMP>`-print-search-dirs'</SAMP> 506 <DD>Print the configured installation directory and a list of library 300 507 and include directories tcc will search. 301 </p> 302 </dd> 303 </dl> 304 305 <p>Preprocessor options: 306 </p> 307 <dl compact="compact"> 308 <dt> ‘<samp>-Idir</samp>’</dt> 309 <dd><p>Specify an additional include path. Include paths are searched in the 310 order they are specified. 311 </p> 312 <p>System include paths are always searched after. The default system 313 include paths are: ‘<tt>/usr/local/include</tt>’, ‘<tt>/usr/include</tt>’ 314 and ‘<tt>PREFIX/lib/tcc/include</tt>’. (‘<tt>PREFIX</tt>’ is usually 315 ‘<tt>/usr</tt>’ or ‘<tt>/usr/local</tt>’). 316 </p> 317 </dd> 318 <dt> ‘<samp>-Dsym[=val]</samp>’</dt> 319 <dd><p>Define preprocessor symbol ‘<samp>sym</samp>’ to 320 val. If val is not present, its value is ‘<samp>1</samp>’. Function-like macros can 321 also be defined: ‘<samp>-DF(a)=a+1</samp>’ 322 </p> 323 </dd> 324 <dt> ‘<samp>-Usym</samp>’</dt> 325 <dd><p>Undefine preprocessor symbol ‘<samp>sym</samp>’. 326 </p></dd> 327 </dl> 328 329 <p>Compilation flags: 330 </p> 331 <p>Note: each of the following warning options has a negative form beginning with 332 ‘<samp>-fno-</samp>’. 333 </p> 334 <dl compact="compact"> 335 <dt> ‘<samp>-funsigned-char</samp>’</dt> 336 <dd><p>Let the <code>char</code> type be unsigned. 337 </p> 338 </dd> 339 <dt> ‘<samp>-fsigned-char</samp>’</dt> 340 <dd><p>Let the <code>char</code> type be signed. 341 </p> 342 </dd> 343 <dt> ‘<samp>-fno-common</samp>’</dt> 344 <dd><p>Do not generate common symbols for uninitialized data. 345 </p> 346 </dd> 347 <dt> ‘<samp>-fleading-underscore</samp>’</dt> 348 <dd><p>Add a leading underscore at the beginning of each C symbol. 349 </p> 350 </dd> 351 </dl> 352 353 <p>Warning options: 354 </p> 355 <dl compact="compact"> 356 <dt> ‘<samp>-w</samp>’</dt> 357 <dd><p>Disable all warnings. 358 </p> 359 </dd> 360 </dl> 361 362 <p>Note: each of the following warning options has a negative form beginning with 363 ‘<samp>-Wno-</samp>’. 364 </p> 365 <dl compact="compact"> 366 <dt> ‘<samp>-Wimplicit-function-declaration</samp>’</dt> 367 <dd><p>Warn about implicit function declaration. 368 </p> 369 </dd> 370 <dt> ‘<samp>-Wunsupported</samp>’</dt> 371 <dd><p>Warn about unsupported GCC features that are ignored by TCC. 372 </p> 373 </dd> 374 <dt> ‘<samp>-Wwrite-strings</samp>’</dt> 375 <dd><p>Make string constants be of type <code>const char *</code> instead of <code>char 376 *</code>. 377 </p> 378 </dd> 379 <dt> ‘<samp>-Werror</samp>’</dt> 380 <dd><p>Abort compilation if warnings are issued. 381 </p> 382 </dd> 383 <dt> ‘<samp>-Wall</samp>’ </dt> 384 <dd><p>Activate all warnings, except ‘<samp>-Werror</samp>’, ‘<samp>-Wunusupported</samp>’ and 385 ‘<samp>-Wwrite-strings</samp>’. 386 </p> 387 </dd> 388 </dl> 389 390 <p>Linker options: 391 </p> 392 <dl compact="compact"> 393 <dt> ‘<samp>-Ldir</samp>’</dt> 394 <dd><p>Specify an additional static library path for the ‘<samp>-l</samp>’ option. The 395 default library paths are ‘<tt>/usr/local/lib</tt>’, ‘<tt>/usr/lib</tt>’ and ‘<tt>/lib</tt>’. 396 </p> 397 </dd> 398 <dt> ‘<samp>-lxxx</samp>’</dt> 399 <dd><p>Link your program with dynamic library libxxx.so or static library 400 libxxx.a. The library is searched in the paths specified by the 401 ‘<samp>-L</samp>’ option. 402 </p> 403 </dd> 404 <dt> ‘<samp>-Bdir</samp>’</dt> 405 <dd><p>Set the path where the tcc internal libraries (and include files) can be 406 found (default is ‘<tt>PREFIX/lib/tcc</tt>’). 407 </p> 408 </dd> 409 <dt> ‘<samp>-shared</samp>’</dt> 410 <dd><p>Generate a shared library instead of an executable. 411 </p> 412 </dd> 413 <dt> ‘<samp>-soname name</samp>’</dt> 414 <dd><p>set name for shared library to be used at runtime 415 </p> 416 </dd> 417 <dt> ‘<samp>-static</samp>’</dt> 418 <dd><p>Generate a statically linked executable (default is a shared linked 419 executable). 420 </p> 421 </dd> 422 <dt> ‘<samp>-rdynamic</samp>’</dt> 423 <dd><p>Export global symbols to the dynamic linker. It is useful when a library 424 opened with <code>dlopen()</code> needs to access executable symbols. 425 </p> 426 </dd> 427 <dt> ‘<samp>-r</samp>’</dt> 428 <dd><p>Generate an object file combining all input files. 429 </p> 430 </dd> 431 <dt> ‘<samp>-Wl,-rpath=path</samp>’</dt> 432 <dd><p>Put custom seatch path for dynamic libraries into executable. 433 </p> 434 </dd> 435 <dt> ‘<samp>-Wl,--oformat=fmt</samp>’</dt> 436 <dd><p>Use <var>fmt</var> as output format. The supported output formats are: 437 </p><dl compact="compact"> 438 <dt> <code>elf32-i386</code></dt> 439 <dd><p>ELF output format (default) 440 </p></dd> 441 <dt> <code>binary</code></dt> 442 <dd><p>Binary image (only for executable output) 443 </p></dd> 444 <dt> <code>coff</code></dt> 445 <dd><p>COFF output format (only for executable output for TMS320C67xx target) 446 </p></dd> 447 </dl> 448 449 </dd> 450 <dt> ‘<samp>-Wl,-subsystem=console/gui/wince/...</samp>’</dt> 451 <dd><p>Set type for PE (Windows) executables. 452 </p> 453 </dd> 454 <dt> ‘<samp>-Wl,-[Ttext=# | section-alignment=# | file-alignment=# | image-base=# | stack=#]</samp>’</dt> 455 <dd><p>Modify executable layout. 456 </p> 457 </dd> 458 <dt> ‘<samp>-Wl,-Bsymbolic</samp>’</dt> 459 <dd><p>Set DT_SYMBOLIC tag. 460 </p> 461 </dd> 462 </dl> 463 464 <p>Debugger options: 465 </p> 466 <dl compact="compact"> 467 <dt> ‘<samp>-g</samp>’</dt> 468 <dd><p>Generate run time debug information so that you get clear run time 469 error messages: <code> test.c:68: in function 'test5()': dereferencing 470 invalid pointer</code> instead of the laconic <code>Segmentation 471 fault</code>. 472 </p> 473 </dd> 474 <dt> ‘<samp>-b</samp>’</dt> 475 <dd><p>Generate additional support code to check 476 memory allocations and array/pointer bounds. ‘<samp>-g</samp>’ is implied. Note 477 that the generated code is slower and bigger in this case. 478 </p> 479 <p>Note: ‘<samp>-b</samp>’ is only available on i386 for the moment. 480 </p> 481 </dd> 482 <dt> ‘<samp>-bt N</samp>’</dt> 483 <dd><p>Display N callers in stack traces. This is useful with ‘<samp>-g</samp>’ or 484 ‘<samp>-b</samp>’. 485 </p> 486 </dd> 487 </dl> 488 489 <p>Misc options: 490 </p> 491 <dl compact="compact"> 492 <dt> ‘<samp>-MD</samp>’</dt> 493 <dd><p>Generate makefile fragment with dependencies. 494 </p> 495 </dd> 496 <dt> ‘<samp>-MF depfile</samp>’</dt> 497 <dd><p>Use ‘<tt>depfile</tt>’ as output for -MD. 498 </p> 499 </dd> 500 </dl> 501 502 <p>Note: GCC options ‘<samp>-Ox</samp>’, ‘<samp>-fx</samp>’ and ‘<samp>-mx</samp>’ are 508 <P> 509 510 <DT><SAMP>`-dumpversion'</SAMP> 511 <DD>Print version. 512 <P> 513 514 </DL> 515 <P> 516 517 Target specific options: 518 </P><P> 519 520 <DL COMPACT> 521 <DT><SAMP>`-mms-bitfields'</SAMP> 522 <DD>Use an algorithm for bitfield alignment consistent with MSVC. Default is 523 gcc's algorithm. 524 <P> 525 526 <DT><SAMP>`-mfloat-abi (ARM only)'</SAMP> 527 <DD>Select the float ABI. Possible values: <CODE>softfp</CODE> and <CODE>hard</CODE> 528 <P> 529 530 <DT><SAMP>`-mno-sse'</SAMP> 531 <DD>Do not use sse registers on x86_64 532 <P> 533 534 <DT><SAMP>`-m32, -m64'</SAMP> 535 <DD>Pass command line to the i386/x86_64 cross compiler. 536 <P> 537 538 </DL> 539 <P> 540 541 Note: GCC options <SAMP>`-Ox'</SAMP>, <SAMP>`-fx'</SAMP> and <SAMP>`-mx'</SAMP> are 503 542 ignored. 504 </p> 505 506 <hr size="6"> 507 <a name="Clang"></a> 508 <table cellpadding="1" cellspacing="1" border="0"> 509 <tr><td valign="middle" align="left">[<a href="#Option-summary" title="Previous section in reading order"> < </a>]</td> 510 <td valign="middle" align="left">[<a href="#ANSI-C" title="Next section in reading order"> > </a>]</td> 511 <td valign="middle" align="left"> </td> 512 <td valign="middle" align="left">[<a href="#Invoke" title="Beginning of this chapter or previous chapter"> << </a>]</td> 513 <td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td> 514 <td valign="middle" align="left">[<a href="#asm" title="Next chapter"> >> </a>]</td> 515 <td valign="middle" align="left"> </td> 516 <td valign="middle" align="left"> </td> 517 <td valign="middle" align="left"> </td> 518 <td valign="middle" align="left"> </td> 519 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 520 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 521 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 522 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 523 </tr></table> 524 <a name="C-language-support"></a> 525 <h1 class="chapter">3. C language support</h1> 526 527 <hr size="6"> 528 <a name="ANSI-C"></a> 529 <table cellpadding="1" cellspacing="1" border="0"> 530 <tr><td valign="middle" align="left">[<a href="#Clang" title="Previous section in reading order"> < </a>]</td> 531 <td valign="middle" align="left">[<a href="#ISOC99-extensions" title="Next section in reading order"> > </a>]</td> 532 <td valign="middle" align="left"> </td> 533 <td valign="middle" align="left">[<a href="#Clang" title="Beginning of this chapter or previous chapter"> << </a>]</td> 534 <td valign="middle" align="left">[<a href="#Clang" title="Up section"> Up </a>]</td> 535 <td valign="middle" align="left">[<a href="#asm" title="Next chapter"> >> </a>]</td> 536 <td valign="middle" align="left"> </td> 537 <td valign="middle" align="left"> </td> 538 <td valign="middle" align="left"> </td> 539 <td valign="middle" align="left"> </td> 540 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 541 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 542 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 543 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 544 </tr></table> 545 <h2 class="section">3.1 ANSI C</h2> 546 547 <p>TCC implements all the ANSI C standard, including structure bit fields 548 and floating point numbers (<code>long double</code>, <code>double</code>, and 549 <code>float</code> fully supported). 550 </p> 551 <hr size="6"> 552 <a name="ISOC99-extensions"></a> 553 <table cellpadding="1" cellspacing="1" border="0"> 554 <tr><td valign="middle" align="left">[<a href="#ANSI-C" title="Previous section in reading order"> < </a>]</td> 555 <td valign="middle" align="left">[<a href="#GNU-C-extensions" title="Next section in reading order"> > </a>]</td> 556 <td valign="middle" align="left"> </td> 557 <td valign="middle" align="left">[<a href="#Clang" title="Beginning of this chapter or previous chapter"> << </a>]</td> 558 <td valign="middle" align="left">[<a href="#Clang" title="Up section"> Up </a>]</td> 559 <td valign="middle" align="left">[<a href="#asm" title="Next chapter"> >> </a>]</td> 560 <td valign="middle" align="left"> </td> 561 <td valign="middle" align="left"> </td> 562 <td valign="middle" align="left"> </td> 563 <td valign="middle" align="left"> </td> 564 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 565 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 566 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 567 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 568 </tr></table> 569 <h2 class="section">3.2 ISOC99 extensions</h2> 570 571 <p>TCC implements many features of the new C standard: ISO C99. Currently 572 missing items are: complex and imaginary numbers and variable length 573 arrays. 574 </p> 575 <p>Currently implemented ISOC99 features: 576 </p> 577 <ul> 578 <li> 64 bit <code>long long</code> types are fully supported. 579 580 </li><li> The boolean type <code>_Bool</code> is supported. 581 582 </li><li> <code>__func__</code> is a string variable containing the current 543 </P><P> 544 545 Environment variables that affect how tcc operates. 546 </P><P> 547 548 <DL COMPACT> 549 550 <DT><SAMP>`CPATH'</SAMP> 551 <DD><DT><SAMP>`C_INCLUDE_PATH'</SAMP> 552 <DD>A colon-separated list of directories searched for include files, 553 directories given with <SAMP>`-I'</SAMP> are searched first. 554 <P> 555 556 <DT><SAMP>`LIBRARY_PATH'</SAMP> 557 <DD>A colon-separated list of directories searched for libraries for the 558 <SAMP>`-l'</SAMP> option, directories given with <SAMP>`-L'</SAMP> are searched first. 559 <P> 560 561 </DL> 562 <P> 563 564 <A NAME="Clang"></A> 565 <HR SIZE="6"> 566 <A NAME="SEC5"></A> 567 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 568 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC4"> < </A>]</TD> 569 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC6"> > </A>]</TD> 570 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> << </A>]</TD> 571 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top"> Up </A>]</TD> 572 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> >> </A>]</TD> 573 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 574 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 575 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 576 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 577 </TR></TABLE> 578 <H1> 3. C language support </H1> 579 <!--docid::SEC5::--> 580 <P> 581 582 <HR SIZE="6"> 583 <A NAME="SEC6"></A> 584 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 585 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC5"> < </A>]</TD> 586 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC7"> > </A>]</TD> 587 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC5"> << </A>]</TD> 588 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC5"> Up </A>]</TD> 589 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> >> </A>]</TD> 590 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 591 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 592 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 593 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 594 </TR></TABLE> 595 <H2> 3.1 ANSI C </H2> 596 <!--docid::SEC6::--> 597 <P> 598 599 TCC implements all the ANSI C standard, including structure bit fields 600 and floating point numbers (<CODE>long double</CODE>, <CODE>double</CODE>, and 601 <CODE>float</CODE> fully supported). 602 </P><P> 603 604 <HR SIZE="6"> 605 <A NAME="SEC7"></A> 606 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 607 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC6"> < </A>]</TD> 608 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC8"> > </A>]</TD> 609 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC8"> << </A>]</TD> 610 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC5"> Up </A>]</TD> 611 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> >> </A>]</TD> 612 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 613 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 614 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 615 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 616 </TR></TABLE> 617 <H2> 3.2 ISOC99 extensions </H2> 618 <!--docid::SEC7::--> 619 <P> 620 621 TCC implements many features of the new C standard: ISO C99. Currently 622 missing items are: complex and imaginary numbers. 623 </P><P> 624 625 Currently implemented ISOC99 features: 626 </P><P> 627 628 <UL> 629 630 <LI>variable length arrays. 631 <P> 632 633 <LI>64 bit <CODE>long long</CODE> types are fully supported. 634 <P> 635 636 <LI>The boolean type <CODE>_Bool</CODE> is supported. 637 <P> 638 639 <LI><CODE>__func__</CODE> is a string variable containing the current 583 640 function name. 584 585 </li><li> Variadic macros: <code>__VA_ARGS__</code> can be used for 641 <P> 642 643 <LI>Variadic macros: <CODE>__VA_ARGS__</CODE> can be used for 586 644 function-like macros: 587 <table><tr><td> </td><td><pre class="example"> #define dprintf(level, __VA_ARGS__) printf(__VA_ARGS__) 588 </pre></td></tr></table> 589 590 <p><code>dprintf</code> can then be used with a variable number of parameters. 591 </p> 592 </li><li> Declarations can appear anywhere in a block (as in C++). 593 594 </li><li> Array and struct/union elements can be initialized in any order by 645 <TABLE><tr><td> </td><td class=example><pre> #define dprintf(level, __VA_ARGS__) printf(__VA_ARGS__) 646 </pre></td></tr></table><P> 647 648 <CODE>dprintf</CODE> can then be used with a variable number of parameters. 649 </P><P> 650 651 <LI>Declarations can appear anywhere in a block (as in C++). 652 <P> 653 654 <LI>Array and struct/union elements can be initialized in any order by 595 655 using designators: 596 < table><tr><td> </td><td><pre class="example"> struct { int x, y; } st[10] = { [0].x = 1, [0].y = 2 };656 <TABLE><tr><td> </td><td class=example><pre> struct { int x, y; } st[10] = { [0].x = 1, [0].y = 2 }; 597 657 598 658 int tab[10] = { 1, 2, [5] = 5, [9] = 9}; 599 </pre></td></tr></table> 600 601 </li><li> Compound initializers are supported: 602 <table><tr><td> </td><td><pre class="example"> int *p = (int []){ 1, 2, 3 }; 603 </pre></td></tr></table> 604 <p>to initialize a pointer pointing to an initialized array. The same 659 </pre></td></tr></table> 660 <LI>Compound initializers are supported: 661 <TABLE><tr><td> </td><td class=example><pre> int *p = (int []){ 1, 2, 3 }; 662 </pre></td></tr></table>to initialize a pointer pointing to an initialized array. The same 605 663 works for structures and strings. 606 </p> 607 </li><li> Hexadecimal floating point constants are supported: 608 <table><tr><td> </td><td><pre class="example"> double d = 0x1234p10; 609 </pre></td></tr></table> 610 611 <p>is the same as writing 612 </p><table><tr><td> </td><td><pre class="example"> double d = 4771840.0; 613 </pre></td></tr></table> 614 615 </li><li> <code>inline</code> keyword is ignored. 616 617 </li><li> <code>restrict</code> keyword is ignored. 618 </li></ul> 619 620 <hr size="6"> 621 <a name="GNU-C-extensions"></a> 622 <table cellpadding="1" cellspacing="1" border="0"> 623 <tr><td valign="middle" align="left">[<a href="#ISOC99-extensions" title="Previous section in reading order"> < </a>]</td> 624 <td valign="middle" align="left">[<a href="#TinyCC-extensions" title="Next section in reading order"> > </a>]</td> 625 <td valign="middle" align="left"> </td> 626 <td valign="middle" align="left">[<a href="#Clang" title="Beginning of this chapter or previous chapter"> << </a>]</td> 627 <td valign="middle" align="left">[<a href="#Clang" title="Up section"> Up </a>]</td> 628 <td valign="middle" align="left">[<a href="#asm" title="Next chapter"> >> </a>]</td> 629 <td valign="middle" align="left"> </td> 630 <td valign="middle" align="left"> </td> 631 <td valign="middle" align="left"> </td> 632 <td valign="middle" align="left"> </td> 633 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 634 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 635 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 636 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 637 </tr></table> 638 <h2 class="section">3.3 GNU C extensions</h2> 639 640 <p>TCC implements some GNU C extensions: 641 </p> 642 <ul> 643 <li> array designators can be used without ’=’: 644 <table><tr><td> </td><td><pre class="example"> int a[10] = { [0] 1, [5] 2, 3, 4 }; 645 </pre></td></tr></table> 646 647 </li><li> Structure field designators can be a label: 648 <table><tr><td> </td><td><pre class="example"> struct { int x, y; } st = { x: 1, y: 1}; 649 </pre></td></tr></table> 650 <p>instead of 651 </p><table><tr><td> </td><td><pre class="example"> struct { int x, y; } st = { .x = 1, .y = 1}; 652 </pre></td></tr></table> 653 654 </li><li> <code>\e</code> is ASCII character 27. 655 656 </li><li> case ranges : ranges can be used in <code>case</code>s: 657 <table><tr><td> </td><td><pre class="example"> switch(a) { 658 case 1 … 9: 659 printf("range 1 to 9\n"); 664 <P> 665 666 <LI>Hexadecimal floating point constants are supported: 667 <TABLE><tr><td> </td><td class=example><pre> double d = 0x1234p10; 668 </pre></td></tr></table><P> 669 670 is the same as writing 671 <TABLE><tr><td> </td><td class=example><pre> double d = 4771840.0; 672 </pre></td></tr></table></P><P> 673 674 <LI><CODE>inline</CODE> keyword is ignored. 675 <P> 676 677 <LI><CODE>restrict</CODE> keyword is ignored. 678 </UL> 679 <P> 680 681 <HR SIZE="6"> 682 <A NAME="SEC8"></A> 683 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 684 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC7"> < </A>]</TD> 685 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC9"> > </A>]</TD> 686 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC9"> << </A>]</TD> 687 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC5"> Up </A>]</TD> 688 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> >> </A>]</TD> 689 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 690 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 691 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 692 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 693 </TR></TABLE> 694 <H2> 3.3 GNU C extensions </H2> 695 <!--docid::SEC8::--> 696 <P> 697 698 TCC implements some GNU C extensions: 699 </P><P> 700 701 <UL> 702 703 <LI>array designators can be used without '=': 704 <TABLE><tr><td> </td><td class=example><pre> int a[10] = { [0] 1, [5] 2, 3, 4 }; 705 </pre></td></tr></table><P> 706 707 <LI>Structure field designators can be a label: 708 <TABLE><tr><td> </td><td class=example><pre> struct { int x, y; } st = { x: 1, y: 1}; 709 </pre></td></tr></table>instead of 710 <TABLE><tr><td> </td><td class=example><pre> struct { int x, y; } st = { .x = 1, .y = 1}; 711 </pre></td></tr></table><P> 712 713 <LI><CODE>\e</CODE> is ASCII character 27. 714 <P> 715 716 <LI>case ranges : ranges can be used in <CODE>case</CODE>s: 717 <TABLE><tr><td> </td><td class=example><pre> switch(a) { 718 case 1 <small>...</small> 9: 719 printf("range 1 to 9\n"); 660 720 break; 661 721 default: 662 printf( "unexpected\n");722 printf("unexpected\n"); 663 723 break; 664 724 } 665 </pre></td></tr></table> 666 667 <a name="index-aligned-attribute"></a> 668 <a name="index-packed-attribute"></a> 669 <a name="index-section-attribute"></a> 670 <a name="index-unused-attribute"></a> 671 <a name="index-cdecl-attribute"></a> 672 <a name="index-stdcall-attribute"></a> 673 <a name="index-regparm-attribute"></a> 674 <a name="index-dllexport-attribute"></a> 675 676 </li><li> The keyword <code>__attribute__</code> is handled to specify variable or 725 </pre></td></tr></table><P> 726 727 <A NAME="IDX1"></A> 728 <A NAME="IDX2"></A> 729 <A NAME="IDX3"></A> 730 <A NAME="IDX4"></A> 731 <A NAME="IDX5"></A> 732 <A NAME="IDX6"></A> 733 <A NAME="IDX7"></A> 734 <A NAME="IDX8"></A> 735 </P><P> 736 737 <LI>The keyword <CODE>__attribute__</CODE> is handled to specify variable or 677 738 function attributes. The following attributes are supported: 678 <ul> 679 <li> <code>aligned(n)</code>: align a variable or a structure field to n bytes 739 <UL> 740 741 <LI><CODE>aligned(n)</CODE>: align a variable or a structure field to n bytes 680 742 (must be a power of two). 681 682 </li><li> <code>packed</code>: force alignment of a variable or a structure field to 743 <P> 744 745 <LI><CODE>packed</CODE>: force alignment of a variable or a structure field to 683 746 1. 684 685 </li><li> <code>section(name)</code>: generate function or data in assembly section 747 <P> 748 749 <LI><CODE>section(name)</CODE>: generate function or data in assembly section 686 750 name (name is a string containing the section name) instead of the default 687 751 section. 688 689 </li><li> <code>unused</code>: specify that the variable or the function is unused. 690 691 </li><li> <code>cdecl</code>: use standard C calling convention (default). 692 693 </li><li> <code>stdcall</code>: use Pascal-like calling convention. 694 695 </li><li> <code>regparm(n)</code>: use fast i386 calling convention. <var>n</var> must be 696 between 1 and 3. The first <var>n</var> function parameters are respectively put in 697 registers <code>%eax</code>, <code>%edx</code> and <code>%ecx</code>. 698 699 </li><li> <code>dllexport</code>: export function from dll/executable (win32 only) 700 701 </li></ul> 702 703 <p>Here are some examples: 704 </p><table><tr><td> </td><td><pre class="example"> int a __attribute__ ((aligned(8), section(".mysection"))); 705 </pre></td></tr></table> 706 707 <p>align variable <code>a</code> to 8 bytes and put it in section <code>.mysection</code>. 708 </p> 709 <table><tr><td> </td><td><pre class="example"> int my_add(int a, int b) __attribute__ ((section(".mycodesection"))) 752 <P> 753 754 <LI><CODE>unused</CODE>: specify that the variable or the function is unused. 755 <P> 756 757 <LI><CODE>cdecl</CODE>: use standard C calling convention (default). 758 <P> 759 760 <LI><CODE>stdcall</CODE>: use Pascal-like calling convention. 761 <P> 762 763 <LI><CODE>regparm(n)</CODE>: use fast i386 calling convention. <VAR>n</VAR> must be 764 between 1 and 3. The first <VAR>n</VAR> function parameters are respectively put in 765 registers <CODE>%eax</CODE>, <CODE>%edx</CODE> and <CODE>%ecx</CODE>. 766 <P> 767 768 <LI><CODE>dllexport</CODE>: export function from dll/executable (win32 only) 769 <P> 770 771 </UL> 772 <P> 773 774 Here are some examples: 775 <TABLE><tr><td> </td><td class=example><pre> int a __attribute__ ((aligned(8), section(".mysection"))); 776 </pre></td></tr></table></P><P> 777 778 align variable <CODE>a</CODE> to 8 bytes and put it in section <CODE>.mysection</CODE>. 779 </P><P> 780 781 <TABLE><tr><td> </td><td class=example><pre> int my_add(int a, int b) __attribute__ ((section(".mycodesection"))) 710 782 { 711 783 return a + b; 712 784 } 713 </pre></td></tr></table> 714 715 <p>generate function <code>my_add</code> in section <code>.mycodesection</code>. 716 </p> 717 </li><li> GNU style variadic macros: 718 <table><tr><td> </td><td><pre class="example"> #define dprintf(fmt, args…) printf(fmt, ## args) 719 720 dprintf("no arg\n"); 721 dprintf("one arg %d\n", 1); 722 </pre></td></tr></table> 723 724 </li><li> <code>__FUNCTION__</code> is interpreted as C99 <code>__func__</code> 785 </pre></td></tr></table></P><P> 786 787 generate function <CODE>my_add</CODE> in section <CODE>.mycodesection</CODE>. 788 </P><P> 789 790 <LI>GNU style variadic macros: 791 <TABLE><tr><td> </td><td class=example><pre> #define dprintf(fmt, args<small>...</small>) printf(fmt, ## args) 792 793 dprintf("no arg\n"); 794 dprintf("one arg %d\n", 1); 795 </pre></td></tr></table><P> 796 797 <LI><CODE>__FUNCTION__</CODE> is interpreted as C99 <CODE>__func__</CODE> 725 798 (so it has not exactly the same semantics as string literal GNUC 726 799 where it is a string literal). 727 728 </li><li> The <code>__alignof__</code> keyword can be used as <code>sizeof</code> 800 <P> 801 802 <LI>The <CODE>__alignof__</CODE> keyword can be used as <CODE>sizeof</CODE> 729 803 to get the alignment of a type or an expression. 730 731 </li><li> The <code>typeof(x)</code> returns the type of <code>x</code>. 732 <code>x</code> is an expression or a type. 733 734 </li><li> Computed gotos: <code>&&label</code> returns a pointer of type 735 <code>void *</code> on the goto label <code>label</code>. <code>goto *expr</code> can be 736 used to jump on the pointer resulting from <code>expr</code>. 737 738 </li><li> Inline assembly with asm instruction: 739 <a name="index-inline-assembly"></a> 740 <a name="index-assembly_002c-inline"></a> 741 <a name="index-_005f_005fasm_005f_005f"></a> 742 <table><tr><td> </td><td><pre class="example">static inline void * my_memcpy(void * to, const void * from, size_t n) 804 <P> 805 806 <LI>The <CODE>typeof(x)</CODE> returns the type of <CODE>x</CODE>. 807 <CODE>x</CODE> is an expression or a type. 808 <P> 809 810 <LI>Computed gotos: <CODE>&&label</CODE> returns a pointer of type 811 <CODE>void *</CODE> on the goto label <CODE>label</CODE>. <CODE>goto *expr</CODE> can be 812 used to jump on the pointer resulting from <CODE>expr</CODE>. 813 <P> 814 815 <LI>Inline assembly with asm instruction: 816 <A NAME="IDX9"></A> 817 <A NAME="IDX10"></A> 818 <A NAME="IDX11"></A> 819 <TABLE><tr><td> </td><td class=example><pre>static inline void * my_memcpy(void * to, const void * from, size_t n) 743 820 { 744 821 int d0, d1, d2; 745 822 __asm__ __volatile__( 746 "rep ; movsl\n\t"747 "testb $2,%b4\n\t"748 "je 1f\n\t"749 "movsw\n"750 "1:\ttestb $1,%b4\n\t"751 "je 2f\n\t"752 "movsb\n"753 "2:"754 : "=&c" (d0), "=&D" (d1), "=&S"(d2)755 : "0" (n/4), "q" (n),"1" ((long) to),"2"((long) from)756 : "memory");823 "rep ; movsl\n\t" 824 "testb $2,%b4\n\t" 825 "je 1f\n\t" 826 "movsw\n" 827 "1:\ttestb $1,%b4\n\t" 828 "je 2f\n\t" 829 "movsb\n" 830 "2:" 831 : "=&c" (d0), "=&D" (d1), "=&S" (d2) 832 :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) 833 : "memory"); 757 834 return (to); 758 835 } 759 </pre></td></tr></table> 760 761 < a name="index-gas"></a>762 <p>TCC includes its own x86 inline assembler with a <code>gas</code>-like (GNU836 </pre></td></tr></table><P> 837 838 <A NAME="IDX12"></A> 839 TCC includes its own x86 inline assembler with a <CODE>gas</CODE>-like (GNU 763 840 assembler) syntax. No intermediate files are generated. GCC 3.x named 764 841 operands are supported. 765 </p> 766 </li><li> <code>__builtin_types_compatible_p()</code> and <code>__builtin_constant_p()</code> 842 </P><P> 843 844 <LI><CODE>__builtin_types_compatible_p()</CODE> and <CODE>__builtin_constant_p()</CODE> 767 845 are supported. 768 769 </li><li> <code>#pragma pack</code> is supported for win32 compatibility. 770 771 </li></ul> 772 773 <hr size="6"> 774 <a name="TinyCC-extensions"></a> 775 <table cellpadding="1" cellspacing="1" border="0"> 776 <tr><td valign="middle" align="left">[<a href="#GNU-C-extensions" title="Previous section in reading order"> < </a>]</td> 777 <td valign="middle" align="left">[<a href="#asm" title="Next section in reading order"> > </a>]</td> 778 <td valign="middle" align="left"> </td> 779 <td valign="middle" align="left">[<a href="#Clang" title="Beginning of this chapter or previous chapter"> << </a>]</td> 780 <td valign="middle" align="left">[<a href="#Clang" title="Up section"> Up </a>]</td> 781 <td valign="middle" align="left">[<a href="#asm" title="Next chapter"> >> </a>]</td> 782 <td valign="middle" align="left"> </td> 783 <td valign="middle" align="left"> </td> 784 <td valign="middle" align="left"> </td> 785 <td valign="middle" align="left"> </td> 786 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 787 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 788 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 789 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 790 </tr></table> 791 <h2 class="section">3.4 TinyCC extensions</h2> 792 793 <ul> 794 <li> <code>__TINYC__</code> is a predefined macro to <code>1</code> to 795 indicate that you use TCC. 796 797 </li><li> <code>#!</code> at the start of a line is ignored to allow scripting. 798 799 </li><li> Binary digits can be entered (<code>0b101</code> instead of 800 <code>5</code>). 801 802 </li><li> <code>__BOUNDS_CHECKING_ON</code> is defined if bound checking is activated. 803 804 </li></ul> 805 806 <hr size="6"> 807 <a name="asm"></a> 808 <table cellpadding="1" cellspacing="1" border="0"> 809 <tr><td valign="middle" align="left">[<a href="#TinyCC-extensions" title="Previous section in reading order"> < </a>]</td> 810 <td valign="middle" align="left">[<a href="#Syntax" title="Next section in reading order"> > </a>]</td> 811 <td valign="middle" align="left"> </td> 812 <td valign="middle" align="left">[<a href="#Clang" title="Beginning of this chapter or previous chapter"> << </a>]</td> 813 <td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td> 814 <td valign="middle" align="left">[<a href="#linker" title="Next chapter"> >> </a>]</td> 815 <td valign="middle" align="left"> </td> 816 <td valign="middle" align="left"> </td> 817 <td valign="middle" align="left"> </td> 818 <td valign="middle" align="left"> </td> 819 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 820 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 821 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 822 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 823 </tr></table> 824 <a name="TinyCC-Assembler"></a> 825 <h1 class="chapter">4. TinyCC Assembler</h1> 826 827 <p>Since version 0.9.16, TinyCC integrates its own assembler. TinyCC 846 <P> 847 848 <LI><CODE>#pragma pack</CODE> is supported for win32 compatibility. 849 <P> 850 851 </UL> 852 <P> 853 854 <HR SIZE="6"> 855 <A NAME="SEC9"></A> 856 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 857 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC8"> < </A>]</TD> 858 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> > </A>]</TD> 859 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC5"> << </A>]</TD> 860 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC5"> Up </A>]</TD> 861 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> >> </A>]</TD> 862 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 863 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 864 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 865 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 866 </TR></TABLE> 867 <H2> 3.4 TinyCC extensions </H2> 868 <!--docid::SEC9::--> 869 <P> 870 871 <UL> 872 873 <LI><CODE>__TINYC__</CODE> is a predefined macro to indicate that you use TCC. 874 <P> 875 876 <LI><CODE>#!</CODE> at the start of a line is ignored to allow scripting. 877 <P> 878 879 <LI>Binary digits can be entered (<CODE>0b101</CODE> instead of 880 <CODE>5</CODE>). 881 <P> 882 883 <LI><CODE>__BOUNDS_CHECKING_ON</CODE> is defined if bound checking is activated. 884 <P> 885 886 </UL> 887 <P> 888 889 <A NAME="asm"></A> 890 <HR SIZE="6"> 891 <A NAME="SEC10"></A> 892 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 893 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC9"> < </A>]</TD> 894 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC11"> > </A>]</TD> 895 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> << </A>]</TD> 896 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top"> Up </A>]</TD> 897 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> >> </A>]</TD> 898 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 899 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 900 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 901 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 902 </TR></TABLE> 903 <H1> 4. TinyCC Assembler </H1> 904 <!--docid::SEC10::--> 905 <P> 906 907 Since version 0.9.16, TinyCC integrates its own assembler. TinyCC 828 908 assembler supports a gas-like syntax (GNU assembler). You can 829 de sactivate assembler support if you want a smaller TinyCC executable909 deactivate assembler support if you want a smaller TinyCC executable 830 910 (the C compiler does not rely on the assembler). 831 </p> 832 <p>TinyCC Assembler is used to handle files with ‘<tt>.S</tt>’ (C 833 preprocessed assembler) and ‘<tt>.s</tt>’ extensions. It is also used to 834 handle the GNU inline assembler with the <code>asm</code> keyword. 835 </p> 836 <hr size="6"> 837 <a name="Syntax"></a> 838 <table cellpadding="1" cellspacing="1" border="0"> 839 <tr><td valign="middle" align="left">[<a href="#asm" title="Previous section in reading order"> < </a>]</td> 840 <td valign="middle" align="left">[<a href="#Expressions" title="Next section in reading order"> > </a>]</td> 841 <td valign="middle" align="left"> </td> 842 <td valign="middle" align="left">[<a href="#asm" title="Beginning of this chapter or previous chapter"> << </a>]</td> 843 <td valign="middle" align="left">[<a href="#asm" title="Up section"> Up </a>]</td> 844 <td valign="middle" align="left">[<a href="#linker" title="Next chapter"> >> </a>]</td> 845 <td valign="middle" align="left"> </td> 846 <td valign="middle" align="left"> </td> 847 <td valign="middle" align="left"> </td> 848 <td valign="middle" align="left"> </td> 849 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 850 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 851 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 852 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 853 </tr></table> 854 <h2 class="section">4.1 Syntax</h2> 855 856 <p>TinyCC Assembler supports most of the gas syntax. The tokens are the 911 </P><P> 912 913 TinyCC Assembler is used to handle files with <TT>`.S'</TT> (C 914 preprocessed assembler) and <TT>`.s'</TT> extensions. It is also used to 915 handle the GNU inline assembler with the <CODE>asm</CODE> keyword. 916 </P><P> 917 918 <HR SIZE="6"> 919 <A NAME="SEC11"></A> 920 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 921 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> < </A>]</TD> 922 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC12"> > </A>]</TD> 923 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> << </A>]</TD> 924 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> Up </A>]</TD> 925 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> >> </A>]</TD> 926 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 927 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 928 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 929 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 930 </TR></TABLE> 931 <H2> 4.1 Syntax </H2> 932 <!--docid::SEC11::--> 933 <P> 934 935 TinyCC Assembler supports most of the gas syntax. The tokens are the 857 936 same as C. 858 </p> 859 <ul> 860 <li> C and C++ comments are supported. 861 862 </li><li> Identifiers are the same as C, so you cannot use ’.’ or ’$’. 863 864 </li><li> Only 32 bit integer numbers are supported. 865 866 </li></ul> 867 868 <hr size="6"> 869 <a name="Expressions"></a> 870 <table cellpadding="1" cellspacing="1" border="0"> 871 <tr><td valign="middle" align="left">[<a href="#Syntax" title="Previous section in reading order"> < </a>]</td> 872 <td valign="middle" align="left">[<a href="#Labels" title="Next section in reading order"> > </a>]</td> 873 <td valign="middle" align="left"> </td> 874 <td valign="middle" align="left">[<a href="#asm" title="Beginning of this chapter or previous chapter"> << </a>]</td> 875 <td valign="middle" align="left">[<a href="#asm" title="Up section"> Up </a>]</td> 876 <td valign="middle" align="left">[<a href="#linker" title="Next chapter"> >> </a>]</td> 877 <td valign="middle" align="left"> </td> 878 <td valign="middle" align="left"> </td> 879 <td valign="middle" align="left"> </td> 880 <td valign="middle" align="left"> </td> 881 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 882 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 883 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 884 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 885 </tr></table> 886 <h2 class="section">4.2 Expressions</h2> 887 888 <ul> 889 <li> Integers in decimal, octal and hexa are supported. 890 891 </li><li> Unary operators: +, -, ~. 892 893 </li><li> Binary operators in decreasing priority order: 894 895 <ol> 896 <li> *, /, % 897 </li><li> &, |, ^ 898 </li><li> +, - 899 </li></ol> 900 901 </li><li> A value is either an absolute number or a label plus an offset. 902 All operators accept absolute values except ’+’ and ’-’. ’+’ or ’-’ can be 903 used to add an offset to a label. ’-’ supports two labels only if they 937 </P><P> 938 939 <UL> 940 941 <LI>C and C++ comments are supported. 942 <P> 943 944 <LI>Identifiers are the same as C, so you cannot use '.' or '$'. 945 <P> 946 947 <LI>Only 32 bit integer numbers are supported. 948 <P> 949 950 </UL> 951 <P> 952 953 <HR SIZE="6"> 954 <A NAME="SEC12"></A> 955 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 956 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC11"> < </A>]</TD> 957 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC13"> > </A>]</TD> 958 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC13"> << </A>]</TD> 959 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> Up </A>]</TD> 960 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> >> </A>]</TD> 961 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 962 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 963 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 964 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 965 </TR></TABLE> 966 <H2> 4.2 Expressions </H2> 967 <!--docid::SEC12::--> 968 <P> 969 970 <UL> 971 972 <LI>Integers in decimal, octal and hexa are supported. 973 <P> 974 975 <LI>Unary operators: +, -, ~. 976 <P> 977 978 <LI>Binary operators in decreasing priority order: 979 <P> 980 981 <OL> 982 <LI>*, /, % 983 <LI>&, |, ^ 984 <LI>+, - 985 </OL> 986 <P> 987 988 <LI>A value is either an absolute number or a label plus an offset. 989 All operators accept absolute values except '+' and '-'. '+' or '-' can be 990 used to add an offset to a label. '-' supports two labels only if they 904 991 are the same or if they are both defined and in the same section. 905 906 </li></ul> 907 908 <hr size="6"> 909 <a name="Labels"></a> 910 <table cellpadding="1" cellspacing="1" border="0"> 911 <tr><td valign="middle" align="left">[<a href="#Expressions" title="Previous section in reading order"> < </a>]</td> 912 <td valign="middle" align="left">[<a href="#Directives" title="Next section in reading order"> > </a>]</td> 913 <td valign="middle" align="left"> </td> 914 <td valign="middle" align="left">[<a href="#asm" title="Beginning of this chapter or previous chapter"> << </a>]</td> 915 <td valign="middle" align="left">[<a href="#asm" title="Up section"> Up </a>]</td> 916 <td valign="middle" align="left">[<a href="#linker" title="Next chapter"> >> </a>]</td> 917 <td valign="middle" align="left"> </td> 918 <td valign="middle" align="left"> </td> 919 <td valign="middle" align="left"> </td> 920 <td valign="middle" align="left"> </td> 921 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 922 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 923 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 924 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 925 </tr></table> 926 <h2 class="section">4.3 Labels</h2> 927 928 <ul> 929 <li> All labels are considered as local, except undefined ones. 930 931 </li><li> Numeric labels can be used as local <code>gas</code>-like labels. 932 They can be defined several times in the same source. Use ’b’ 933 (backward) or ’f’ (forward) as suffix to reference them: 934 935 <table><tr><td> </td><td><pre class="example"> 1: 992 <P> 993 994 </UL> 995 <P> 996 997 <HR SIZE="6"> 998 <A NAME="SEC13"></A> 999 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1000 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC12"> < </A>]</TD> 1001 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC14"> > </A>]</TD> 1002 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC14"> << </A>]</TD> 1003 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> Up </A>]</TD> 1004 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> >> </A>]</TD> 1005 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1006 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1007 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1008 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1009 </TR></TABLE> 1010 <H2> 4.3 Labels </H2> 1011 <!--docid::SEC13::--> 1012 <P> 1013 1014 <UL> 1015 1016 <LI>All labels are considered as local, except undefined ones. 1017 <P> 1018 1019 <LI>Numeric labels can be used as local <CODE>gas</CODE>-like labels. 1020 They can be defined several times in the same source. Use 'b' 1021 (backward) or 'f' (forward) as suffix to reference them: 1022 <P> 1023 1024 <TABLE><tr><td> </td><td class=example><pre> 1: 936 1025 jmp 1b /* jump to '1' label before */ 937 1026 jmp 1f /* jump to '1' label after */ 938 1027 1: 939 </pre></td></tr></table> 940 941 </li></ul> 942 943 <hr size="6"> 944 <a name="Directives"></a> 945 <table cellpadding="1" cellspacing="1" border="0"> 946 <tr><td valign="middle" align="left">[<a href="#Labels" title="Previous section in reading order"> < </a>]</td> 947 <td valign="middle" align="left">[<a href="#X86-Assembler" title="Next section in reading order"> > </a>]</td> 948 <td valign="middle" align="left"> </td> 949 <td valign="middle" align="left">[<a href="#asm" title="Beginning of this chapter or previous chapter"> << </a>]</td> 950 <td valign="middle" align="left">[<a href="#asm" title="Up section"> Up </a>]</td> 951 <td valign="middle" align="left">[<a href="#linker" title="Next chapter"> >> </a>]</td> 952 <td valign="middle" align="left"> </td> 953 <td valign="middle" align="left"> </td> 954 <td valign="middle" align="left"> </td> 955 <td valign="middle" align="left"> </td> 956 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 957 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 958 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 959 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 960 </tr></table> 961 <h2 class="section">4.4 Directives</h2> 962 <a name="index-assembler-directives"></a> 963 <a name="index-directives_002c-assembler"></a> 964 <a name="index-align-directive"></a> 965 <a name="index-skip-directive"></a> 966 <a name="index-space-directive"></a> 967 <a name="index-byte-directive"></a> 968 <a name="index-word-directive"></a> 969 <a name="index-short-directive"></a> 970 <a name="index-int-directive"></a> 971 <a name="index-long-directive"></a> 972 <a name="index-quad-directive"></a> 973 <a name="index-globl-directive"></a> 974 <a name="index-global-directive"></a> 975 <a name="index-section-directive"></a> 976 <a name="index-text-directive"></a> 977 <a name="index-data-directive"></a> 978 <a name="index-bss-directive"></a> 979 <a name="index-fill-directive"></a> 980 <a name="index-org-directive"></a> 981 <a name="index-previous-directive"></a> 982 <a name="index-string-directive"></a> 983 <a name="index-asciz-directive"></a> 984 <a name="index-ascii-directive"></a> 985 986 <p>All directives are preceeded by a ’.’. The following directives are 1028 </pre></td></tr></table></P><P> 1029 1030 </UL> 1031 <P> 1032 1033 <HR SIZE="6"> 1034 <A NAME="SEC14"></A> 1035 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1036 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC13"> < </A>]</TD> 1037 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC15"> > </A>]</TD> 1038 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC15"> << </A>]</TD> 1039 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> Up </A>]</TD> 1040 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> >> </A>]</TD> 1041 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1042 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1043 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1044 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1045 </TR></TABLE> 1046 <H2> 4.4 Directives </H2> 1047 <!--docid::SEC14::--> 1048 <P> 1049 1050 All directives are preceded by a '.'. The following directives are 987 1051 supported: 988 </p> 989 <ul> 990 <li> .align n[,value] 991 </li><li> .skip n[,value] 992 </li><li> .space n[,value] 993 </li><li> .byte value1[,...] 994 </li><li> .word value1[,...] 995 </li><li> .short value1[,...] 996 </li><li> .int value1[,...] 997 </li><li> .long value1[,...] 998 </li><li> .quad immediate_value1[,...] 999 </li><li> .globl symbol 1000 </li><li> .global symbol 1001 </li><li> .section section 1002 </li><li> .text 1003 </li><li> .data 1004 </li><li> .bss 1005 </li><li> .fill repeat[,size[,value]] 1006 </li><li> .org n 1007 </li><li> .previous 1008 </li><li> .string string[,...] 1009 </li><li> .asciz string[,...] 1010 </li><li> .ascii string[,...] 1011 </li></ul> 1012 1013 <hr size="6"> 1014 <a name="X86-Assembler"></a> 1015 <table cellpadding="1" cellspacing="1" border="0"> 1016 <tr><td valign="middle" align="left">[<a href="#Directives" title="Previous section in reading order"> < </a>]</td> 1017 <td valign="middle" align="left">[<a href="#linker" title="Next section in reading order"> > </a>]</td> 1018 <td valign="middle" align="left"> </td> 1019 <td valign="middle" align="left">[<a href="#asm" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1020 <td valign="middle" align="left">[<a href="#asm" title="Up section"> Up </a>]</td> 1021 <td valign="middle" align="left">[<a href="#linker" title="Next chapter"> >> </a>]</td> 1022 <td valign="middle" align="left"> </td> 1023 <td valign="middle" align="left"> </td> 1024 <td valign="middle" align="left"> </td> 1025 <td valign="middle" align="left"> </td> 1026 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1027 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1028 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1029 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1030 </tr></table> 1031 <h2 class="section">4.5 X86 Assembler</h2> 1032 <a name="index-assembler"></a> 1033 1034 <p>All X86 opcodes are supported. Only ATT syntax is supported (source 1052 </P><P> 1053 1054 <UL> 1055 <LI>.align n[,value] 1056 <LI>.skip n[,value] 1057 <LI>.space n[,value] 1058 <LI>.byte value1[,...] 1059 <LI>.word value1[,...] 1060 <LI>.short value1[,...] 1061 <LI>.int value1[,...] 1062 <LI>.long value1[,...] 1063 <LI>.quad immediate_value1[,...] 1064 <LI>.globl symbol 1065 <LI>.global symbol 1066 <LI>.section section 1067 <LI>.text 1068 <LI>.data 1069 <LI>.bss 1070 <LI>.fill repeat[,size[,value]] 1071 <LI>.org n 1072 <LI>.previous 1073 <LI>.string string[,...] 1074 <LI>.asciz string[,...] 1075 <LI>.ascii string[,...] 1076 </UL> 1077 <P> 1078 1079 <HR SIZE="6"> 1080 <A NAME="SEC15"></A> 1081 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1082 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC14"> < </A>]</TD> 1083 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> > </A>]</TD> 1084 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> << </A>]</TD> 1085 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC10"> Up </A>]</TD> 1086 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> >> </A>]</TD> 1087 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1088 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1089 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1090 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1091 </TR></TABLE> 1092 <H2> 4.5 X86 Assembler </H2> 1093 <!--docid::SEC15::--> 1094 <P> 1095 1096 All X86 opcodes are supported. Only ATT syntax is supported (source 1035 1097 then destination operand order). If no size suffix is given, TinyCC 1036 1098 tries to guess it from the operand sizes. 1037 </p> 1038 <p>Currently, MMX opcodes are supported but not SSE ones. 1039 </p> 1040 <hr size="6"> 1041 <a name="linker"></a> 1042 <table cellpadding="1" cellspacing="1" border="0"> 1043 <tr><td valign="middle" align="left">[<a href="#X86-Assembler" title="Previous section in reading order"> < </a>]</td> 1044 <td valign="middle" align="left">[<a href="#ELF-file-generation" title="Next section in reading order"> > </a>]</td> 1045 <td valign="middle" align="left"> </td> 1046 <td valign="middle" align="left">[<a href="#asm" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1047 <td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td> 1048 <td valign="middle" align="left">[<a href="#Bounds" title="Next chapter"> >> </a>]</td> 1049 <td valign="middle" align="left"> </td> 1050 <td valign="middle" align="left"> </td> 1051 <td valign="middle" align="left"> </td> 1052 <td valign="middle" align="left"> </td> 1053 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1054 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1055 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1056 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1057 </tr></table> 1058 <a name="TinyCC-Linker"></a> 1059 <h1 class="chapter">5. TinyCC Linker</h1> 1060 <a name="index-linker"></a> 1061 1062 <hr size="6"> 1063 <a name="ELF-file-generation"></a> 1064 <table cellpadding="1" cellspacing="1" border="0"> 1065 <tr><td valign="middle" align="left">[<a href="#linker" title="Previous section in reading order"> < </a>]</td> 1066 <td valign="middle" align="left">[<a href="#ELF-file-loader" title="Next section in reading order"> > </a>]</td> 1067 <td valign="middle" align="left"> </td> 1068 <td valign="middle" align="left">[<a href="#linker" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1069 <td valign="middle" align="left">[<a href="#linker" title="Up section"> Up </a>]</td> 1070 <td valign="middle" align="left">[<a href="#Bounds" title="Next chapter"> >> </a>]</td> 1071 <td valign="middle" align="left"> </td> 1072 <td valign="middle" align="left"> </td> 1073 <td valign="middle" align="left"> </td> 1074 <td valign="middle" align="left"> </td> 1075 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1076 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1077 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1078 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1079 </tr></table> 1080 <h2 class="section">5.1 ELF file generation</h2> 1081 <a name="index-ELF"></a> 1082 1083 <p>TCC can directly output relocatable ELF files (object files), 1099 </P><P> 1100 1101 Currently, MMX opcodes are supported but not SSE ones. 1102 </P><P> 1103 1104 <A NAME="linker"></A> 1105 <HR SIZE="6"> 1106 <A NAME="SEC16"></A> 1107 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1108 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC15"> < </A>]</TD> 1109 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC17"> > </A>]</TD> 1110 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC21"> << </A>]</TD> 1111 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top"> Up </A>]</TD> 1112 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC21"> >> </A>]</TD> 1113 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1114 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1115 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1116 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1117 </TR></TABLE> 1118 <H1> 5. TinyCC Linker </H1> 1119 <!--docid::SEC16::--> 1120 <P> 1121 1122 <HR SIZE="6"> 1123 <A NAME="SEC17"></A> 1124 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1125 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> < </A>]</TD> 1126 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC18"> > </A>]</TD> 1127 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> << </A>]</TD> 1128 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> Up </A>]</TD> 1129 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC21"> >> </A>]</TD> 1130 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1131 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1132 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1133 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1134 </TR></TABLE> 1135 <H2> 5.1 ELF file generation </H2> 1136 <!--docid::SEC17::--> 1137 <P> 1138 1139 TCC can directly output relocatable ELF files (object files), 1084 1140 executable ELF files and dynamic ELF libraries without relying on an 1085 1141 external linker. 1086 </p> 1087 <p>Dynamic ELF libraries can be output but the C compiler does not generate 1142 </P><P> 1143 1144 Dynamic ELF libraries can be output but the C compiler does not generate 1088 1145 position independent code (PIC). It means that the dynamic library 1089 1146 code generated by TCC cannot be factorized among processes yet. 1090 </p> 1091 <p>TCC linker eliminates unreferenced object code in libraries. A single pass is 1147 </P><P> 1148 1149 TCC linker eliminates unreferenced object code in libraries. A single pass is 1092 1150 done on the object and library list, so the order in which object files and 1093 1151 libraries are specified is important (same constraint as GNU ld). No grouping 1094 options (‘<samp>--start-group</samp>’ and ‘<samp>--end-group</samp>’) are supported. 1095 </p> 1096 <hr size="6"> 1097 <a name="ELF-file-loader"></a> 1098 <table cellpadding="1" cellspacing="1" border="0"> 1099 <tr><td valign="middle" align="left">[<a href="#ELF-file-generation" title="Previous section in reading order"> < </a>]</td> 1100 <td valign="middle" align="left">[<a href="#PE_002di386-file-generation" title="Next section in reading order"> > </a>]</td> 1101 <td valign="middle" align="left"> </td> 1102 <td valign="middle" align="left">[<a href="#linker" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1103 <td valign="middle" align="left">[<a href="#linker" title="Up section"> Up </a>]</td> 1104 <td valign="middle" align="left">[<a href="#Bounds" title="Next chapter"> >> </a>]</td> 1105 <td valign="middle" align="left"> </td> 1106 <td valign="middle" align="left"> </td> 1107 <td valign="middle" align="left"> </td> 1108 <td valign="middle" align="left"> </td> 1109 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1110 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1111 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1112 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1113 </tr></table> 1114 <h2 class="section">5.2 ELF file loader</h2> 1115 1116 <p>TCC can load ELF object files, archives (.a files) and dynamic 1152 options (<SAMP>`--start-group'</SAMP> and <SAMP>`--end-group'</SAMP>) are supported. 1153 </P><P> 1154 1155 <HR SIZE="6"> 1156 <A NAME="SEC18"></A> 1157 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1158 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC17"> < </A>]</TD> 1159 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC19"> > </A>]</TD> 1160 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC19"> << </A>]</TD> 1161 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> Up </A>]</TD> 1162 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC21"> >> </A>]</TD> 1163 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1164 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1165 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1166 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1167 </TR></TABLE> 1168 <H2> 5.2 ELF file loader </H2> 1169 <!--docid::SEC18::--> 1170 <P> 1171 1172 TCC can load ELF object files, archives (.a files) and dynamic 1117 1173 libraries (.so). 1118 </p> 1119 <hr size="6"> 1120 <a name="PE_002di386-file-generation"></a> 1121 <table cellpadding="1" cellspacing="1" border="0"> 1122 <tr><td valign="middle" align="left">[<a href="#ELF-file-loader" title="Previous section in reading order"> < </a>]</td> 1123 <td valign="middle" align="left">[<a href="#GNU-Linker-Scripts" title="Next section in reading order"> > </a>]</td> 1124 <td valign="middle" align="left"> </td> 1125 <td valign="middle" align="left">[<a href="#linker" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1126 <td valign="middle" align="left">[<a href="#linker" title="Up section"> Up </a>]</td> 1127 <td valign="middle" align="left">[<a href="#Bounds" title="Next chapter"> >> </a>]</td> 1128 <td valign="middle" align="left"> </td> 1129 <td valign="middle" align="left"> </td> 1130 <td valign="middle" align="left"> </td> 1131 <td valign="middle" align="left"> </td> 1132 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1133 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1134 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1135 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1136 </tr></table> 1137 <h2 class="section">5.3 PE-i386 file generation</h2> 1138 <a name="index-PE_002di386"></a> 1139 1140 <p>TCC for Windows supports the native Win32 executable file format (PE-i386). It 1174 </P><P> 1175 1176 <HR SIZE="6"> 1177 <A NAME="SEC19"></A> 1178 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1179 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC18"> < </A>]</TD> 1180 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC20"> > </A>]</TD> 1181 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC20"> << </A>]</TD> 1182 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> Up </A>]</TD> 1183 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC21"> >> </A>]</TD> 1184 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1185 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1186 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1187 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1188 </TR></TABLE> 1189 <H2> 5.3 PE-i386 file generation </H2> 1190 <!--docid::SEC19::--> 1191 <P> 1192 1193 TCC for Windows supports the native Win32 executable file format (PE-i386). It 1141 1194 generates EXE files (console and gui) and DLL files. 1142 </p> 1143 <p>For usage on Windows, see also tcc-win32.txt. 1144 </p> 1145 <hr size="6"> 1146 <a name="GNU-Linker-Scripts"></a> 1147 <table cellpadding="1" cellspacing="1" border="0"> 1148 <tr><td valign="middle" align="left">[<a href="#PE_002di386-file-generation" title="Previous section in reading order"> < </a>]</td> 1149 <td valign="middle" align="left">[<a href="#Bounds" title="Next section in reading order"> > </a>]</td> 1150 <td valign="middle" align="left"> </td> 1151 <td valign="middle" align="left">[<a href="#linker" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1152 <td valign="middle" align="left">[<a href="#linker" title="Up section"> Up </a>]</td> 1153 <td valign="middle" align="left">[<a href="#Bounds" title="Next chapter"> >> </a>]</td> 1154 <td valign="middle" align="left"> </td> 1155 <td valign="middle" align="left"> </td> 1156 <td valign="middle" align="left"> </td> 1157 <td valign="middle" align="left"> </td> 1158 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1159 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1160 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1161 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1162 </tr></table> 1163 <h2 class="section">5.4 GNU Linker Scripts</h2> 1164 <a name="index-scripts_002c-linker"></a> 1165 <a name="index-linker-scripts"></a> 1166 <a name="index-GROUP_002c-linker-command"></a> 1167 <a name="index-FILE_002c-linker-command"></a> 1168 <a name="index-OUTPUT_005fFORMAT_002c-linker-command"></a> 1169 <a name="index-TARGET_002c-linker-command"></a> 1170 1171 <p>Because on many Linux systems some dynamic libraries (such as 1172 ‘<tt>/usr/lib/libc.so</tt>’) are in fact GNU ld link scripts (horrible!), 1195 </P><P> 1196 1197 For usage on Windows, see also tcc-win32.txt. 1198 </P><P> 1199 1200 <HR SIZE="6"> 1201 <A NAME="SEC20"></A> 1202 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1203 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC19"> < </A>]</TD> 1204 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC21"> > </A>]</TD> 1205 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> << </A>]</TD> 1206 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC16"> Up </A>]</TD> 1207 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC21"> >> </A>]</TD> 1208 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1209 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1210 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1211 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1212 </TR></TABLE> 1213 <H2> 5.4 GNU Linker Scripts </H2> 1214 <!--docid::SEC20::--> 1215 <P> 1216 1217 Because on many Linux systems some dynamic libraries (such as 1218 <TT>`/usr/lib/libc.so'</TT>) are in fact GNU ld link scripts (horrible!), 1173 1219 the TCC linker also supports a subset of GNU ld scripts. 1174 </p> 1175 <p>The <code>GROUP</code> and <code>FILE</code> commands are supported. <code>OUTPUT_FORMAT</code> 1176 and <code>TARGET</code> are ignored. 1177 </p> 1178 <p>Example from ‘<tt>/usr/lib/libc.so</tt>’: 1179 </p><table><tr><td> </td><td><pre class="example">/* GNU ld script 1220 </P><P> 1221 1222 The <CODE>GROUP</CODE> and <CODE>FILE</CODE> commands are supported. <CODE>OUTPUT_FORMAT</CODE> 1223 and <CODE>TARGET</CODE> are ignored. 1224 </P><P> 1225 1226 Example from <TT>`/usr/lib/libc.so'</TT>: 1227 <TABLE><tr><td> </td><td class=example><pre>/* GNU ld script 1180 1228 Use the shared library, but some functions are only in 1181 1229 the static library, so try that secondarily. */ 1182 1230 GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a ) 1183 </pre></td></tr></table> 1184 1185 <hr size="6"> 1186 <a name="Bounds"></a> 1187 <table cellpadding="1" cellspacing="1" border="0"> 1188 <tr><td valign="middle" align="left">[<a href="#GNU-Linker-Scripts" title="Previous section in reading order"> < </a>]</td> 1189 <td valign="middle" align="left">[<a href="#Libtcc" title="Next section in reading order"> > </a>]</td> 1190 <td valign="middle" align="left"> </td> 1191 <td valign="middle" align="left">[<a href="#linker" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1192 <td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td> 1193 <td valign="middle" align="left">[<a href="#Libtcc" title="Next chapter"> >> </a>]</td> 1194 <td valign="middle" align="left"> </td> 1195 <td valign="middle" align="left"> </td> 1196 <td valign="middle" align="left"> </td> 1197 <td valign="middle" align="left"> </td> 1198 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1199 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1200 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1201 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1202 </tr></table> 1203 <a name="TinyCC-Memory-and-Bound-checks"></a> 1204 <h1 class="chapter">6. TinyCC Memory and Bound checks</h1> 1205 <a name="index-bound-checks"></a> 1206 <a name="index-memory-checks"></a> 1207 1208 <p>This feature is activated with the ‘<samp>-b</samp>’ (see section <a href="#Invoke">Command line invocation</a>). 1209 </p> 1210 <p>Note that pointer size is <em>unchanged</em> and that code generated 1211 with bound checks is <em>fully compatible</em> with unchecked 1231 </pre></td></tr></table></P><P> 1232 1233 <A NAME="Bounds"></A> 1234 <HR SIZE="6"> 1235 <A NAME="SEC21"></A> 1236 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1237 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC20"> < </A>]</TD> 1238 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC22"> > </A>]</TD> 1239 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC22"> << </A>]</TD> 1240 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top"> Up </A>]</TD> 1241 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC22"> >> </A>]</TD> 1242 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1243 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1244 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1245 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1246 </TR></TABLE> 1247 <H1> 6. TinyCC Memory and Bound checks </H1> 1248 <!--docid::SEC21::--> 1249 <P> 1250 1251 This feature is activated with the <SAMP>`-b'</SAMP> (see section <A HREF="tcc-doc.html#SEC2">2. Command line invocation</A>). 1252 </P><P> 1253 1254 Note that pointer size is <EM>unchanged</EM> and that code generated 1255 with bound checks is <EM>fully compatible</EM> with unchecked 1212 1256 code. When a pointer comes from unchecked code, it is assumed to be 1213 1257 valid. Even very obscure C code with casts should work correctly. 1214 </p> 1215 <p>For more information about the ideas behind this method, see 1216 <a href="http://www.doc.ic.ac.uk/~phjk/BoundsChecking.html">http://www.doc.ic.ac.uk/~phjk/BoundsChecking.html</a>. 1217 </p> 1218 <p>Here are some examples of caught errors: 1219 </p> 1220 <dl compact="compact"> 1221 <dt> Invalid range with standard string function:</dt> 1222 <dd><table><tr><td> </td><td><pre class="example">{ 1258 </P><P> 1259 1260 For more information about the ideas behind this method, see 1261 <A HREF="http://www.doc.ic.ac.uk/~phjk/BoundsChecking.html">http://www.doc.ic.ac.uk/~phjk/BoundsChecking.html</A>. 1262 </P><P> 1263 1264 Here are some examples of caught errors: 1265 </P><P> 1266 1267 <DL COMPACT> 1268 1269 <DT>Invalid range with standard string function: 1270 <DD><TABLE><tr><td> </td><td class=example><pre>{ 1223 1271 char tab[10]; 1224 1272 memset(tab, 0, 11); 1225 1273 } 1226 </pre></td></tr></table> 1227 1228 </dd> 1229 <dt> Out of bounds-error in global or local arrays:</dt> 1230 <dd><table><tr><td> </td><td><pre class="example">{ 1274 </pre></td></tr></table><P> 1275 1276 <DT>Out of bounds-error in global or local arrays: 1277 <DD><TABLE><tr><td> </td><td class=example><pre>{ 1231 1278 int tab[10]; 1232 for(i=0;i& lt;11;i++) {1279 for(i=0;i<11;i++) { 1233 1280 sum += tab[i]; 1234 1281 } 1235 1282 } 1236 </pre></td></tr></table> 1237 1238 </dd> 1239 <dt> Out of bounds-error in malloc’ed data:</dt> 1240 <dd><table><tr><td> </td><td><pre class="example">{ 1283 </pre></td></tr></table><P> 1284 1285 <DT>Out of bounds-error in malloc'ed data: 1286 <DD><TABLE><tr><td> </td><td class=example><pre>{ 1241 1287 int *tab; 1242 1288 tab = malloc(20 * sizeof(int)); 1243 for(i=0;i& lt;21;i++) {1289 for(i=0;i<21;i++) { 1244 1290 sum += tab4[i]; 1245 1291 } 1246 1292 free(tab); 1247 1293 } 1248 </pre></td></tr></table> 1249 1250 </dd> 1251 <dt> Access of freed memory:</dt> 1252 <dd><table><tr><td> </td><td><pre class="example">{ 1294 </pre></td></tr></table><P> 1295 1296 <DT>Access of freed memory: 1297 <DD><TABLE><tr><td> </td><td class=example><pre>{ 1253 1298 int *tab; 1254 1299 tab = malloc(20 * sizeof(int)); 1255 1300 free(tab); 1256 for(i=0;i& lt;20;i++) {1301 for(i=0;i<20;i++) { 1257 1302 sum += tab4[i]; 1258 1303 } 1259 1304 } 1260 </pre></td></tr></table> 1261 1262 </dd> 1263 <dt> Double free:</dt> 1264 <dd><table><tr><td> </td><td><pre class="example">{ 1305 </pre></td></tr></table><P> 1306 1307 <DT>Double free: 1308 <DD><TABLE><tr><td> </td><td class=example><pre>{ 1265 1309 int *tab; 1266 1310 tab = malloc(20 * sizeof(int)); … … 1268 1312 free(tab); 1269 1313 } 1270 </pre></td></tr></table> 1271 1272 </dd> 1273 </dl> 1274 1275 <hr size="6"> 1276 <a name="Libtcc"></a> 1277 <table cellpadding="1" cellspacing="1" border="0"> 1278 <tr><td valign="middle" align="left">[<a href="#Bounds" title="Previous section in reading order"> < </a>]</td> 1279 <td valign="middle" align="left">[<a href="#devel" title="Next section in reading order"> > </a>]</td> 1280 <td valign="middle" align="left"> </td> 1281 <td valign="middle" align="left">[<a href="#Bounds" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1282 <td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td> 1283 <td valign="middle" align="left">[<a href="#devel" title="Next chapter"> >> </a>]</td> 1284 <td valign="middle" align="left"> </td> 1285 <td valign="middle" align="left"> </td> 1286 <td valign="middle" align="left"> </td> 1287 <td valign="middle" align="left"> </td> 1288 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1289 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1290 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1291 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1292 </tr></table> 1293 <a name="The-libtcc-library"></a> 1294 <h1 class="chapter">7. The <code>libtcc</code> library</h1> 1295 1296 <p>The <code>libtcc</code> library enables you to use TCC as a backend for 1314 </pre></td></tr></table><P> 1315 1316 </DL> 1317 <P> 1318 1319 <A NAME="Libtcc"></A> 1320 <HR SIZE="6"> 1321 <A NAME="SEC22"></A> 1322 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1323 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC21"> < </A>]</TD> 1324 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC23"> > </A>]</TD> 1325 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC23"> << </A>]</TD> 1326 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top"> Up </A>]</TD> 1327 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC23"> >> </A>]</TD> 1328 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1329 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1330 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1331 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1332 </TR></TABLE> 1333 <H1> 7. The <CODE>libtcc</CODE> library </H1> 1334 <!--docid::SEC22::--> 1335 <P> 1336 1337 The <CODE>libtcc</CODE> library enables you to use TCC as a backend for 1297 1338 dynamic code generation. 1298 </p> 1299 <p>Read the ‘<tt>libtcc.h</tt>’ to have an overview of the API. Read 1300 ‘<tt>libtcc_test.c</tt>’ to have a very simple example. 1301 </p> 1302 <p>The idea consists in giving a C string containing the program you want 1303 to compile directly to <code>libtcc</code>. Then you can access to any global 1339 </P><P> 1340 1341 Read the <TT>`libtcc.h'</TT> to have an overview of the API. Read 1342 <TT>`libtcc_test.c'</TT> to have a very simple example. 1343 </P><P> 1344 1345 The idea consists in giving a C string containing the program you want 1346 to compile directly to <CODE>libtcc</CODE>. Then you can access to any global 1304 1347 symbol (function or variable) defined. 1305 </p> 1306 <hr size="6"> 1307 <a name="devel"></a> 1308 <table cellpadding="1" cellspacing="1" border="0"> 1309 <tr><td valign="middle" align="left">[<a href="#Libtcc" title="Previous section in reading order"> < </a>]</td> 1310 <td valign="middle" align="left">[<a href="#File-reading" title="Next section in reading order"> > </a>]</td> 1311 <td valign="middle" align="left"> </td> 1312 <td valign="middle" align="left">[<a href="#Libtcc" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1313 <td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td> 1314 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> >> </a>]</td> 1315 <td valign="middle" align="left"> </td> 1316 <td valign="middle" align="left"> </td> 1317 <td valign="middle" align="left"> </td> 1318 <td valign="middle" align="left"> </td> 1319 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1320 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1321 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1322 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1323 </tr></table> 1324 <a name="Developer_0027s-guide"></a> 1325 <h1 class="chapter">8. Developer’s guide</h1> 1326 1327 <p>This chapter gives some hints to understand how TCC works. You can skip 1348 </P><P> 1349 1350 <A NAME="devel"></A> 1351 <HR SIZE="6"> 1352 <A NAME="SEC23"></A> 1353 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1354 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC22"> < </A>]</TD> 1355 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC24"> > </A>]</TD> 1356 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD> 1357 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top"> Up </A>]</TD> 1358 <TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD> 1359 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1360 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1361 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1362 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1363 </TR></TABLE> 1364 <H1> 8. Developer's guide </H1> 1365 <!--docid::SEC23::--> 1366 <P> 1367 1368 This chapter gives some hints to understand how TCC works. You can skip 1328 1369 it if you do not intend to modify the TCC code. 1329 </p> 1330 <hr size="6"> 1331 <a name="File-reading"></a> 1332 <table cellpadding="1" cellspacing="1" border="0"> 1333 <tr><td valign="middle" align="left">[<a href="#devel" title="Previous section in reading order"> < </a>]</td> 1334 <td valign="middle" align="left">[<a href="#Lexer" title="Next section in reading order"> > </a>]</td> 1335 <td valign="middle" align="left"> </td> 1336 <td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1337 <td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td> 1338 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> >> </a>]</td> 1339 <td valign="middle" align="left"> </td> 1340 <td valign="middle" align="left"> </td> 1341 <td valign="middle" align="left"> </td> 1342 <td valign="middle" align="left"> </td> 1343 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1344 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1345 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1346 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1347 </tr></table> 1348 <h2 class="section">8.1 File reading</h2> 1349 1350 <p>The <code>BufferedFile</code> structure contains the context needed to read a 1351 file, including the current line number. <code>tcc_open()</code> opens a new 1352 file and <code>tcc_close()</code> closes it. <code>inp()</code> returns the next 1370 </P><P> 1371 1372 <HR SIZE="6"> 1373 <A NAME="SEC24"></A> 1374 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1375 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC23"> < </A>]</TD> 1376 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC25"> > </A>]</TD> 1377 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD> 1378 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC23"> Up </A>]</TD> 1379 <TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD> 1380 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1381 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1382 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1383 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1384 </TR></TABLE> 1385 <H2> 8.1 File reading </H2> 1386 <!--docid::SEC24::--> 1387 <P> 1388 1389 The <CODE>BufferedFile</CODE> structure contains the context needed to read a 1390 file, including the current line number. <CODE>tcc_open()</CODE> opens a new 1391 file and <CODE>tcc_close()</CODE> closes it. <CODE>inp()</CODE> returns the next 1353 1392 character. 1354 </p> 1355 <hr size="6"> 1356 <a name="Lexer"></a> 1357 <table cellpadding="1" cellspacing="1" border="0"> 1358 <tr><td valign="middle" align="left">[<a href="#File-reading" title="Previous section in reading order"> < </a>]</td> 1359 <td valign="middle" align="left">[<a href="#Parser" title="Next section in reading order"> > </a>]</td> 1360 <td valign="middle" align="left"> </td> 1361 <td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1362 <td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td> 1363 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> >> </a>]</td> 1364 <td valign="middle" align="left"> </td> 1365 <td valign="middle" align="left"> </td> 1366 <td valign="middle" align="left"> </td> 1367 <td valign="middle" align="left"> </td> 1368 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1369 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1370 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1371 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1372 </tr></table> 1373 <h2 class="section">8.2 Lexer</h2> 1374 1375 <p><code>next()</code> reads the next token in the current 1376 file. <code>next_nomacro()</code> reads the next token without macro 1393 </P><P> 1394 1395 <HR SIZE="6"> 1396 <A NAME="SEC25"></A> 1397 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1398 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC24"> < </A>]</TD> 1399 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC26"> > </A>]</TD> 1400 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC26"> << </A>]</TD> 1401 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC23"> Up </A>]</TD> 1402 <TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD> 1403 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1404 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1405 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1406 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1407 </TR></TABLE> 1408 <H2> 8.2 Lexer </H2> 1409 <!--docid::SEC25::--> 1410 <P> 1411 1412 <CODE>next()</CODE> reads the next token in the current 1413 file. <CODE>next_nomacro()</CODE> reads the next token without macro 1377 1414 expansion. 1378 </p> 1379 <p><code>tok</code> contains the current token (see <code>TOK_xxx</code>) 1380 constants. Identifiers and keywords are also keywords. <code>tokc</code> 1415 </P><P> 1416 1417 <CODE>tok</CODE> contains the current token (see <CODE>TOK_xxx</CODE>) 1418 constants. Identifiers and keywords are also keywords. <CODE>tokc</CODE> 1381 1419 contains additional infos about the token (for example a constant value 1382 1420 if number or string token). 1383 </p> 1384 <hr size="6"> 1385 <a name="Parser"></a> 1386 <table cellpadding="1" cellspacing="1" border="0"> 1387 <tr><td valign="middle" align="left">[<a href="#Lexer" title="Previous section in reading order"> < </a>]</td> 1388 <td valign="middle" align="left">[<a href="#Types" title="Next section in reading order"> > </a>]</td> 1389 <td valign="middle" align="left"> </td> 1390 <td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1391 <td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td> 1392 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> >> </a>]</td> 1393 <td valign="middle" align="left"> </td> 1394 <td valign="middle" align="left"> </td> 1395 <td valign="middle" align="left"> </td> 1396 <td valign="middle" align="left"> </td> 1397 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1398 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1399 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1400 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1401 </tr></table> 1402 <h2 class="section">8.3 Parser</h2> 1403 1404 <p>The parser is hardcoded (yacc is not necessary). It does only one pass, 1421 </P><P> 1422 1423 <HR SIZE="6"> 1424 <A NAME="SEC26"></A> 1425 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1426 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC25"> < </A>]</TD> 1427 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC27"> > </A>]</TD> 1428 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC27"> << </A>]</TD> 1429 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC23"> Up </A>]</TD> 1430 <TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD> 1431 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1432 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1433 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1434 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1435 </TR></TABLE> 1436 <H2> 8.3 Parser </H2> 1437 <!--docid::SEC26::--> 1438 <P> 1439 1440 The parser is hardcoded (yacc is not necessary). It does only one pass, 1405 1441 except: 1406 </p> 1407 <ul> 1408 <li> For initialized arrays with unknown size, a first pass 1442 </P><P> 1443 1444 <UL> 1445 1446 <LI>For initialized arrays with unknown size, a first pass 1409 1447 is done to count the number of elements. 1410 1411 </li><li> For architectures where arguments are evaluated in 1448 <P> 1449 1450 <LI>For architectures where arguments are evaluated in 1412 1451 reverse order, a first pass is done to reverse the argument order. 1413 1414 </li></ul> 1415 1416 <hr size="6"> 1417 <a name="Types"></a> 1418 <table cellpadding="1" cellspacing="1" border="0"> 1419 <tr><td valign="middle" align="left">[<a href="#Parser" title="Previous section in reading order"> < </a>]</td> 1420 <td valign="middle" align="left">[<a href="#Symbols" title="Next section in reading order"> > </a>]</td> 1421 <td valign="middle" align="left"> </td> 1422 <td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1423 <td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td> 1424 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> >> </a>]</td> 1425 <td valign="middle" align="left"> </td> 1426 <td valign="middle" align="left"> </td> 1427 <td valign="middle" align="left"> </td> 1428 <td valign="middle" align="left"> </td> 1429 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1430 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1431 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1432 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1433 </tr></table> 1434 <h2 class="section">8.4 Types</h2> 1435 1436 <p>The types are stored in a single ’int’ variable. It was choosen in the 1452 <P> 1453 1454 </UL> 1455 <P> 1456 1457 <HR SIZE="6"> 1458 <A NAME="SEC27"></A> 1459 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1460 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC26"> < </A>]</TD> 1461 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC28"> > </A>]</TD> 1462 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC28"> << </A>]</TD> 1463 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC23"> Up </A>]</TD> 1464 <TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD> 1465 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1466 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1467 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1468 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1469 </TR></TABLE> 1470 <H2> 8.4 Types </H2> 1471 <!--docid::SEC27::--> 1472 <P> 1473 1474 The types are stored in a single 'int' variable. It was chosen in the 1437 1475 first stages of development when tcc was much simpler. Now, it may not 1438 1476 be the best solution. 1439 </p> 1440 <table><tr><td> </td><td><pre class="example">#define VT_INT 0 /* integer type */ 1477 </P><P> 1478 1479 <TABLE><tr><td> </td><td class=example><pre>#define VT_INT 0 /* integer type */ 1441 1480 #define VT_BYTE 1 /* signed byte type */ 1442 1481 #define VT_SHORT 2 /* short type */ … … 1460 1499 #define VT_CONSTANT 0x0800 /* const modifier */ 1461 1500 #define VT_VOLATILE 0x1000 /* volatile modifier */ 1462 #define VT_ SIGNED0x2000 /* signed type */1501 #define VT_DEFSIGN 0x2000 /* signed type */ 1463 1502 1464 1503 #define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */ 1465 </pre></td></tr></table> 1466 1467 <p>When a reference to another type is needed (for pointers, functions and1468 structures), the < code>32 - VT_STRUCT_SHIFT</code> high order bits are used to1504 </pre></td></tr></table></P><P> 1505 1506 When a reference to another type is needed (for pointers, functions and 1507 structures), the <CODE>32 - VT_STRUCT_SHIFT</CODE> high order bits are used to 1469 1508 store an identifier reference. 1470 </p> 1471 <p>The <code>VT_UNSIGNED</code> flag can be set for chars, shorts, ints and long 1509 </P><P> 1510 1511 The <CODE>VT_UNSIGNED</CODE> flag can be set for chars, shorts, ints and long 1472 1512 longs. 1473 </p> 1474 <p>Arrays are considered as pointers <code>VT_PTR</code> with the flag 1475 <code>VT_ARRAY</code> set. Variable length arrays are considered as special 1476 arrays and have flag <code>VT_VLA</code> set instead of <code>VT_ARRAY</code>. 1477 </p> 1478 <p>The <code>VT_BITFIELD</code> flag can be set for chars, shorts, ints and long 1513 </P><P> 1514 1515 Arrays are considered as pointers <CODE>VT_PTR</CODE> with the flag 1516 <CODE>VT_ARRAY</CODE> set. Variable length arrays are considered as special 1517 arrays and have flag <CODE>VT_VLA</CODE> set instead of <CODE>VT_ARRAY</CODE>. 1518 </P><P> 1519 1520 The <CODE>VT_BITFIELD</CODE> flag can be set for chars, shorts, ints and long 1479 1521 longs. If it is set, then the bitfield position is stored from bits 1480 1522 VT_STRUCT_SHIFT to VT_STRUCT_SHIFT + 5 and the bit field size is stored 1481 1523 from bits VT_STRUCT_SHIFT + 6 to VT_STRUCT_SHIFT + 11. 1482 </p> 1483 <p><code>VT_LONG</code> is never used except during parsing. 1484 </p> 1485 <p>During parsing, the storage of an object is also stored in the type 1524 </P><P> 1525 1526 <CODE>VT_LONG</CODE> is never used except during parsing. 1527 </P><P> 1528 1529 During parsing, the storage of an object is also stored in the type 1486 1530 integer: 1487 </p> 1488 <table><tr><td> </td><td><pre class="example">#define VT_EXTERN 0x00000080 /* extern definition */ 1531 </P><P> 1532 1533 <TABLE><tr><td> </td><td class=example><pre>#define VT_EXTERN 0x00000080 /* extern definition */ 1489 1534 #define VT_STATIC 0x00000100 /* static variable */ 1490 1535 #define VT_TYPEDEF 0x00000200 /* typedef definition */ … … 1493 1538 #define VT_EXPORT 0x00008000 /* win32: data exported from dll */ 1494 1539 #define VT_WEAK 0x00010000 /* win32: data exported from dll */ 1495 </pre></td></tr></table> 1496 1497 <hr size="6"> 1498 <a name="Symbols"></a> 1499 <table cellpadding="1" cellspacing="1" border="0"> 1500 <tr><td valign="middle" align="left">[<a href="#Types" title="Previous section in reading order"> < </a>]</td> 1501 <td valign="middle" align="left">[<a href="#Sections" title="Next section in reading order"> > </a>]</td> 1502 <td valign="middle" align="left"> </td> 1503 <td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1504 <td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td> 1505 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> >> </a>]</td> 1506 <td valign="middle" align="left"> </td> 1507 <td valign="middle" align="left"> </td> 1508 <td valign="middle" align="left"> </td> 1509 <td valign="middle" align="left"> </td> 1510 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1511 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1512 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1513 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1514 </tr></table> 1515 <h2 class="section">8.5 Symbols</h2> 1516 1517 <p>All symbols are stored in hashed symbol stacks. Each symbol stack 1518 contains <code>Sym</code> structures. 1519 </p> 1520 <p><code>Sym.v</code> contains the symbol name (remember 1521 an idenfier is also a token, so a string is never necessary to store 1522 it). <code>Sym.t</code> gives the type of the symbol. <code>Sym.r</code> is usually 1523 the register in which the corresponding variable is stored. <code>Sym.c</code> is 1540 </pre></td></tr></table></P><P> 1541 1542 <HR SIZE="6"> 1543 <A NAME="SEC28"></A> 1544 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1545 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC27"> < </A>]</TD> 1546 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC29"> > </A>]</TD> 1547 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC29"> << </A>]</TD> 1548 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC23"> Up </A>]</TD> 1549 <TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD> 1550 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1551 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1552 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1553 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1554 </TR></TABLE> 1555 <H2> 8.5 Symbols </H2> 1556 <!--docid::SEC28::--> 1557 <P> 1558 1559 All symbols are stored in hashed symbol stacks. Each symbol stack 1560 contains <CODE>Sym</CODE> structures. 1561 </P><P> 1562 1563 <CODE>Sym.v</CODE> contains the symbol name (remember 1564 an identifier is also a token, so a string is never necessary to store 1565 it). <CODE>Sym.t</CODE> gives the type of the symbol. <CODE>Sym.r</CODE> is usually 1566 the register in which the corresponding variable is stored. <CODE>Sym.c</CODE> is 1524 1567 usually a constant associated to the symbol like its address for normal 1525 1568 symbols, and the number of entries for symbols representing arrays. 1526 Variable length array types use < code>Sym.c</code> as a location on the stack1569 Variable length array types use <CODE>Sym.c</CODE> as a location on the stack 1527 1570 which holds the runtime sizeof for the type. 1528 </p> 1529 <p>Four main symbol stacks are defined: 1530 </p> 1531 <dl compact="compact"> 1532 <dt> <code>define_stack</code></dt> 1533 <dd><p>for the macros (<code>#define</code>s). 1534 </p> 1535 </dd> 1536 <dt> <code>global_stack</code></dt> 1537 <dd><p>for the global variables, functions and types. 1538 </p> 1539 </dd> 1540 <dt> <code>local_stack</code></dt> 1541 <dd><p>for the local variables, functions and types. 1542 </p> 1543 </dd> 1544 <dt> <code>global_label_stack</code></dt> 1545 <dd><p>for the local labels (for <code>goto</code>). 1546 </p> 1547 </dd> 1548 <dt> <code>label_stack</code></dt> 1549 <dd><p>for GCC block local labels (see the <code>__label__</code> keyword). 1550 </p> 1551 </dd> 1552 </dl> 1553 1554 <p><code>sym_push()</code> is used to add a new symbol in the local symbol 1571 </P><P> 1572 1573 Four main symbol stacks are defined: 1574 </P><P> 1575 1576 <DL COMPACT> 1577 1578 <DT><CODE>define_stack</CODE> 1579 <DD>for the macros (<CODE>#define</CODE>s). 1580 <P> 1581 1582 <DT><CODE>global_stack</CODE> 1583 <DD>for the global variables, functions and types. 1584 <P> 1585 1586 <DT><CODE>local_stack</CODE> 1587 <DD>for the local variables, functions and types. 1588 <P> 1589 1590 <DT><CODE>global_label_stack</CODE> 1591 <DD>for the local labels (for <CODE>goto</CODE>). 1592 <P> 1593 1594 <DT><CODE>label_stack</CODE> 1595 <DD>for GCC block local labels (see the <CODE>__label__</CODE> keyword). 1596 <P> 1597 1598 </DL> 1599 <P> 1600 1601 <CODE>sym_push()</CODE> is used to add a new symbol in the local symbol 1555 1602 stack. If no local symbol stack is active, it is added in the global 1556 1603 symbol stack. 1557 </p> 1558 <p><code>sym_pop(st,b)</code> pops symbols from the symbol stack <var>st</var> until 1559 the symbol <var>b</var> is on the top of stack. If <var>b</var> is NULL, the stack 1604 </P><P> 1605 1606 <CODE>sym_pop(st,b)</CODE> pops symbols from the symbol stack <VAR>st</VAR> until 1607 the symbol <VAR>b</VAR> is on the top of stack. If <VAR>b</VAR> is NULL, the stack 1560 1608 is emptied. 1561 </p> 1562 <p><code>sym_find(v)</code> return the symbol associated to the identifier 1563 <var>v</var>. The local stack is searched first from top to bottom, then the 1609 </P><P> 1610 1611 <CODE>sym_find(v)</CODE> return the symbol associated to the identifier 1612 <VAR>v</VAR>. The local stack is searched first from top to bottom, then the 1564 1613 global stack. 1565 </p> 1566 <hr size="6"> 1567 <a name="Sections"></a> 1568 <table cellpadding="1" cellspacing="1" border="0"> 1569 <tr><td valign="middle" align="left">[<a href="#Symbols" title="Previous section in reading order"> < </a>]</td> 1570 <td valign="middle" align="left">[<a href="#Code-generation" title="Next section in reading order"> > </a>]</td> 1571 <td valign="middle" align="left"> </td> 1572 <td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1573 <td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td> 1574 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> >> </a>]</td> 1575 <td valign="middle" align="left"> </td> 1576 <td valign="middle" align="left"> </td> 1577 <td valign="middle" align="left"> </td> 1578 <td valign="middle" align="left"> </td> 1579 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1580 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1581 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1582 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1583 </tr></table> 1584 <h2 class="section">8.6 Sections</h2> 1585 1586 <p>The generated code and datas are written in sections. The structure 1587 <code>Section</code> contains all the necessary information for a given 1588 section. <code>new_section()</code> creates a new section. ELF file semantics 1614 </P><P> 1615 1616 <HR SIZE="6"> 1617 <A NAME="SEC29"></A> 1618 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1619 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC28"> < </A>]</TD> 1620 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC30"> > </A>]</TD> 1621 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC30"> << </A>]</TD> 1622 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC23"> Up </A>]</TD> 1623 <TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD> 1624 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1625 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1626 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1627 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1628 </TR></TABLE> 1629 <H2> 8.6 Sections </H2> 1630 <!--docid::SEC29::--> 1631 <P> 1632 1633 The generated code and data are written in sections. The structure 1634 <CODE>Section</CODE> contains all the necessary information for a given 1635 section. <CODE>new_section()</CODE> creates a new section. ELF file semantics 1589 1636 is assumed for each section. 1590 </p> 1591 <p>The following sections are predefined: 1592 </p> 1593 <dl compact="compact"> 1594 <dt> <code>text_section</code></dt> 1595 <dd><p>is the section containing the generated code. <var>ind</var> contains the 1637 </P><P> 1638 1639 The following sections are predefined: 1640 </P><P> 1641 1642 <DL COMPACT> 1643 1644 <DT><CODE>text_section</CODE> 1645 <DD>is the section containing the generated code. <VAR>ind</VAR> contains the 1596 1646 current position in the code section. 1597 </p> 1598 </dd> 1599 <dt> <code>data_section</code></dt> 1600 <dd><p>contains initialized data 1601 </p> 1602 </dd> 1603 <dt> <code>bss_section</code></dt> 1604 <dd><p>contains uninitialized data 1605 </p> 1606 </dd> 1607 <dt> <code>bounds_section</code></dt> 1608 <dt> <code>lbounds_section</code></dt> 1609 <dd><p>are used when bound checking is activated 1610 </p> 1611 </dd> 1612 <dt> <code>stab_section</code></dt> 1613 <dt> <code>stabstr_section</code></dt> 1614 <dd><p>are used when debugging is actived to store debug information 1615 </p> 1616 </dd> 1617 <dt> <code>symtab_section</code></dt> 1618 <dt> <code>strtab_section</code></dt> 1619 <dd><p>contain the exported symbols (currently only used for debugging). 1620 </p> 1621 </dd> 1622 </dl> 1623 1624 <hr size="6"> 1625 <a name="Code-generation"></a> 1626 <table cellpadding="1" cellspacing="1" border="0"> 1627 <tr><td valign="middle" align="left">[<a href="#Sections" title="Previous section in reading order"> < </a>]</td> 1628 <td valign="middle" align="left">[<a href="#Introduction-2" title="Next section in reading order"> > </a>]</td> 1629 <td valign="middle" align="left"> </td> 1630 <td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1631 <td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td> 1632 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> >> </a>]</td> 1633 <td valign="middle" align="left"> </td> 1634 <td valign="middle" align="left"> </td> 1635 <td valign="middle" align="left"> </td> 1636 <td valign="middle" align="left"> </td> 1637 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1638 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1639 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1640 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1641 </tr></table> 1642 <h2 class="section">8.7 Code generation</h2> 1643 <a name="index-code-generation"></a> 1644 1645 <hr size="6"> 1646 <a name="Introduction-2"></a> 1647 <table cellpadding="1" cellspacing="1" border="0"> 1648 <tr><td valign="middle" align="left">[<a href="#Code-generation" title="Previous section in reading order"> < </a>]</td> 1649 <td valign="middle" align="left">[<a href="#The-value-stack" title="Next section in reading order"> > </a>]</td> 1650 <td valign="middle" align="left"> </td> 1651 <td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1652 <td valign="middle" align="left">[<a href="#Code-generation" title="Up section"> Up </a>]</td> 1653 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> >> </a>]</td> 1654 <td valign="middle" align="left"> </td> 1655 <td valign="middle" align="left"> </td> 1656 <td valign="middle" align="left"> </td> 1657 <td valign="middle" align="left"> </td> 1658 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1659 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1660 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1661 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1662 </tr></table> 1663 <h3 class="subsection">8.7.1 Introduction</h3> 1664 1665 <p>The TCC code generator directly generates linked binary code in one 1647 <P> 1648 1649 <DT><CODE>data_section</CODE> 1650 <DD>contains initialized data 1651 <P> 1652 1653 <DT><CODE>bss_section</CODE> 1654 <DD>contains uninitialized data 1655 <P> 1656 1657 <DT><CODE>bounds_section</CODE> 1658 <DD><DT><CODE>lbounds_section</CODE> 1659 <DD>are used when bound checking is activated 1660 <P> 1661 1662 <DT><CODE>stab_section</CODE> 1663 <DD><DT><CODE>stabstr_section</CODE> 1664 <DD>are used when debugging is active to store debug information 1665 <P> 1666 1667 <DT><CODE>symtab_section</CODE> 1668 <DD><DT><CODE>strtab_section</CODE> 1669 <DD>contain the exported symbols (currently only used for debugging). 1670 <P> 1671 1672 </DL> 1673 <P> 1674 1675 <HR SIZE="6"> 1676 <A NAME="SEC30"></A> 1677 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1678 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC29"> < </A>]</TD> 1679 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC31"> > </A>]</TD> 1680 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC35"> << </A>]</TD> 1681 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC23"> Up </A>]</TD> 1682 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC35"> >> </A>]</TD> 1683 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1684 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1685 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1686 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1687 </TR></TABLE> 1688 <H2> 8.7 Code generation </H2> 1689 <!--docid::SEC30::--> 1690 <P> 1691 1692 <HR SIZE="6"> 1693 <A NAME="SEC31"></A> 1694 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1695 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC30"> < </A>]</TD> 1696 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC32"> > </A>]</TD> 1697 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC35"> << </A>]</TD> 1698 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC30"> Up </A>]</TD> 1699 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC35"> >> </A>]</TD> 1700 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1701 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1702 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1703 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1704 </TR></TABLE> 1705 <H3> 8.7.1 Introduction </H3> 1706 <!--docid::SEC31::--> 1707 <P> 1708 1709 The TCC code generator directly generates linked binary code in one 1666 1710 pass. It is rather unusual these days (see gcc for example which 1667 1711 generates text assembly), but it can be very fast and surprisingly 1668 1712 little complicated. 1669 </p> 1670 <p>The TCC code generator is register based. Optimization is only done at 1713 </P><P> 1714 1715 The TCC code generator is register based. Optimization is only done at 1671 1716 the expression level. No intermediate representation of expression is 1672 kept except the current values stored in the <em>value stack</em>. 1673 </p> 1674 <p>On x86, three temporary registers are used. When more registers are 1717 kept except the current values stored in the <EM>value stack</EM>. 1718 </P><P> 1719 1720 On x86, three temporary registers are used. When more registers are 1675 1721 needed, one register is spilled into a new temporary variable on the stack. 1676 </p> 1677 <hr size="6"> 1678 <a name="The-value-stack"></a> 1679 <table cellpadding="1" cellspacing="1" border="0"> 1680 <tr><td valign="middle" align="left">[<a href="#Introduction-2" title="Previous section in reading order"> < </a>]</td> 1681 <td valign="middle" align="left">[<a href="#Manipulating-the-value-stack" title="Next section in reading order"> > </a>]</td> 1682 <td valign="middle" align="left"> </td> 1683 <td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1684 <td valign="middle" align="left">[<a href="#Code-generation" title="Up section"> Up </a>]</td> 1685 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> >> </a>]</td> 1686 <td valign="middle" align="left"> </td> 1687 <td valign="middle" align="left"> </td> 1688 <td valign="middle" align="left"> </td> 1689 <td valign="middle" align="left"> </td> 1690 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1691 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1692 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1693 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1694 </tr></table> 1695 <h3 class="subsection">8.7.2 The value stack</h3> 1696 <a name="index-value-stack_002c-introduction"></a> 1697 1698 <p>When an expression is parsed, its value is pushed on the value stack 1699 (<var>vstack</var>). The top of the value stack is <var>vtop</var>. Each value 1700 stack entry is the structure <code>SValue</code>. 1701 </p> 1702 <p><code>SValue.t</code> is the type. <code>SValue.r</code> indicates how the value is 1722 </P><P> 1723 1724 <HR SIZE="6"> 1725 <A NAME="SEC32"></A> 1726 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1727 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC31"> < </A>]</TD> 1728 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC33"> > </A>]</TD> 1729 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC33"> << </A>]</TD> 1730 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC30"> Up </A>]</TD> 1731 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC35"> >> </A>]</TD> 1732 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1733 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1734 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1735 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1736 </TR></TABLE> 1737 <H3> 8.7.2 The value stack </H3> 1738 <!--docid::SEC32::--> 1739 <P> 1740 1741 When an expression is parsed, its value is pushed on the value stack 1742 (<VAR>vstack</VAR>). The top of the value stack is <VAR>vtop</VAR>. Each value 1743 stack entry is the structure <CODE>SValue</CODE>. 1744 </P><P> 1745 1746 <CODE>SValue.t</CODE> is the type. <CODE>SValue.r</CODE> indicates how the value is 1703 1747 currently stored in the generated code. It is usually a CPU register 1704 index (< code>REG_xxx</code> constants), but additional values and flags are1748 index (<CODE>REG_xxx</CODE> constants), but additional values and flags are 1705 1749 defined: 1706 </p> 1707 <table><tr><td> </td><td><pre class="example">#define VT_CONST 0x00f0 1750 </P><P> 1751 1752 <TABLE><tr><td> </td><td class=example><pre>#define VT_CONST 0x00f0 1708 1753 #define VT_LLOCAL 0x00f1 1709 1754 #define VT_LOCAL 0x00f2 … … 1720 1765 #define VT_LVAL_UNSIGNED 0x4000 1721 1766 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED) 1722 </pre></td></tr></table> 1723 1724 <dl compact="compact"> 1725 <dt> <code>VT_CONST</code></dt> 1726 <dd><p>indicates that the value is a constant. It is stored in the union 1727 <code>SValue.c</code>, depending on its type. 1728 </p> 1729 </dd> 1730 <dt> <code>VT_LOCAL</code></dt> 1731 <dd><p>indicates a local variable pointer at offset <code>SValue.c.i</code> in the 1767 </pre></td></tr></table></P><P> 1768 1769 <DL COMPACT> 1770 1771 <DT><CODE>VT_CONST</CODE> 1772 <DD>indicates that the value is a constant. It is stored in the union 1773 <CODE>SValue.c</CODE>, depending on its type. 1774 <P> 1775 1776 <DT><CODE>VT_LOCAL</CODE> 1777 <DD>indicates a local variable pointer at offset <CODE>SValue.c.i</CODE> in the 1732 1778 stack. 1733 < /p>1734 </dd> 1735 < dt> <code>VT_CMP</code></dt>1736 < dd><p>indicates that the value is actually stored in the CPU flags (i.e. the1779 <P> 1780 1781 <DT><CODE>VT_CMP</CODE> 1782 <DD>indicates that the value is actually stored in the CPU flags (i.e. the 1737 1783 value is the consequence of a test). The value is either 0 or 1. The 1738 actual CPU flags used is indicated in <code>SValue.c.i</code>. 1739 </p> 1740 <p>If any code is generated which destroys the CPU flags, this value MUST be 1784 actual CPU flags used is indicated in <CODE>SValue.c.i</CODE>. 1785 <P> 1786 1787 If any code is generated which destroys the CPU flags, this value MUST be 1741 1788 put in a normal register. 1742 </ p>1743 </dd> 1744 < dt> <code>VT_JMP</code></dt>1745 < dt> <code>VT_JMPI</code></dt>1746 < dd><p>indicates that the value is the consequence of a conditional jump. For VT_JMP,1789 </P><P> 1790 1791 <DT><CODE>VT_JMP</CODE> 1792 <DD><DT><CODE>VT_JMPI</CODE> 1793 <DD>indicates that the value is the consequence of a conditional jump. For VT_JMP, 1747 1794 it is 1 if the jump is taken, 0 otherwise. For VT_JMPI it is inverted. 1748 </p> 1749 <p>These values are used to compile the <code>||</code> and <code>&&</code> logical 1795 <P> 1796 1797 These values are used to compile the <CODE>||</CODE> and <CODE>&&</CODE> logical 1750 1798 operators. 1751 </p> 1752 <p>If any code is generated, this value MUST be put in a normal 1753 register. Otherwise, the generated code won’t be executed if the jump is 1799 </P><P> 1800 1801 If any code is generated, this value MUST be put in a normal 1802 register. Otherwise, the generated code won't be executed if the jump is 1754 1803 taken. 1755 </ p>1756 </dd> 1757 < dt> <code>VT_LVAL</code></dt>1758 < dd><p>is a flag indicating that the value is actually an lvalue (left value of1804 </P><P> 1805 1806 <DT><CODE>VT_LVAL</CODE> 1807 <DD>is a flag indicating that the value is actually an lvalue (left value of 1759 1808 an assignment). It means that the value stored is actually a pointer to 1760 1809 the wanted value. 1761 </p> 1762 <p>Understanding the use <code>VT_LVAL</code> is very important if you want to 1810 <P> 1811 1812 Understanding the use <CODE>VT_LVAL</CODE> is very important if you want to 1763 1813 understand how TCC works. 1764 </ p>1765 </dd> 1766 < dt> <code>VT_LVAL_BYTE</code></dt>1767 < dt> <code>VT_LVAL_SHORT</code></dt>1768 < dt> <code>VT_LVAL_UNSIGNED</code></dt>1769 < dd><p>if the lvalue has an integer type, then these flags give its real1814 </P><P> 1815 1816 <DT><CODE>VT_LVAL_BYTE</CODE> 1817 <DD><DT><CODE>VT_LVAL_SHORT</CODE> 1818 <DD><DT><CODE>VT_LVAL_UNSIGNED</CODE> 1819 <DD>if the lvalue has an integer type, then these flags give its real 1770 1820 type. The type alone is not enough in case of cast optimisations. 1771 </p> 1772 </dd> 1773 <dt> <code>VT_LLOCAL</code></dt> 1774 <dd><p>is a saved lvalue on the stack. <code>VT_LLOCAL</code> should be eliminated 1775 ASAP because its semantics are rather complicated. 1776 </p> 1777 </dd> 1778 <dt> <code>VT_MUSTCAST</code></dt> 1779 <dd><p>indicates that a cast to the value type must be performed if the value 1821 <P> 1822 1823 <DT><CODE>VT_LLOCAL</CODE> 1824 <DD>is a saved lvalue on the stack. <CODE>VT_LVAL</CODE> must also be set with 1825 <CODE>VT_LLOCAL</CODE>. <CODE>VT_LLOCAL</CODE> can arise when a <CODE>VT_LVAL</CODE> in 1826 a register has to be saved to the stack, or it can come from an 1827 architecture-specific calling convention. 1828 <P> 1829 1830 <DT><CODE>VT_MUSTCAST</CODE> 1831 <DD>indicates that a cast to the value type must be performed if the value 1780 1832 is used (lazy casting). 1781 </p> 1782 </dd> 1783 <dt> <code>VT_SYM</code></dt> 1784 <dd><p>indicates that the symbol <code>SValue.sym</code> must be added to the constant. 1785 </p> 1786 </dd> 1787 <dt> <code>VT_MUSTBOUND</code></dt> 1788 <dt> <code>VT_BOUNDED</code></dt> 1789 <dd><p>are only used for optional bound checking. 1790 </p> 1791 </dd> 1792 </dl> 1793 1794 <hr size="6"> 1795 <a name="Manipulating-the-value-stack"></a> 1796 <table cellpadding="1" cellspacing="1" border="0"> 1797 <tr><td valign="middle" align="left">[<a href="#The-value-stack" title="Previous section in reading order"> < </a>]</td> 1798 <td valign="middle" align="left">[<a href="#CPU-dependent-code-generation" title="Next section in reading order"> > </a>]</td> 1799 <td valign="middle" align="left"> </td> 1800 <td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1801 <td valign="middle" align="left">[<a href="#Code-generation" title="Up section"> Up </a>]</td> 1802 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> >> </a>]</td> 1803 <td valign="middle" align="left"> </td> 1804 <td valign="middle" align="left"> </td> 1805 <td valign="middle" align="left"> </td> 1806 <td valign="middle" align="left"> </td> 1807 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1808 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1809 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1810 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1811 </tr></table> 1812 <h3 class="subsection">8.7.3 Manipulating the value stack</h3> 1813 <a name="index-value-stack"></a> 1814 1815 <p><code>vsetc()</code> and <code>vset()</code> pushes a new value on the value 1816 stack. If the previous <var>vtop</var> was stored in a very unsafe place(for 1833 <P> 1834 1835 <DT><CODE>VT_SYM</CODE> 1836 <DD>indicates that the symbol <CODE>SValue.sym</CODE> must be added to the constant. 1837 <P> 1838 1839 <DT><CODE>VT_MUSTBOUND</CODE> 1840 <DD><DT><CODE>VT_BOUNDED</CODE> 1841 <DD>are only used for optional bound checking. 1842 <P> 1843 1844 </DL> 1845 <P> 1846 1847 <HR SIZE="6"> 1848 <A NAME="SEC33"></A> 1849 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1850 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC32"> < </A>]</TD> 1851 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC34"> > </A>]</TD> 1852 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC34"> << </A>]</TD> 1853 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC30"> Up </A>]</TD> 1854 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC35"> >> </A>]</TD> 1855 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1856 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1857 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1858 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1859 </TR></TABLE> 1860 <H3> 8.7.3 Manipulating the value stack </H3> 1861 <!--docid::SEC33::--> 1862 <P> 1863 1864 <CODE>vsetc()</CODE> and <CODE>vset()</CODE> pushes a new value on the value 1865 stack. If the previous <VAR>vtop</VAR> was stored in a very unsafe place(for 1817 1866 example in the CPU flags), then some code is generated to put the 1818 previous <var>vtop</var> in a safe storage. 1819 </p> 1820 <p><code>vpop()</code> pops <var>vtop</var>. In some cases, it also generates cleanup 1867 previous <VAR>vtop</VAR> in a safe storage. 1868 </P><P> 1869 1870 <CODE>vpop()</CODE> pops <VAR>vtop</VAR>. In some cases, it also generates cleanup 1821 1871 code (for example if stacked floating point registers are used as on 1822 1872 x86). 1823 </p> 1824 <p>The <code>gv(rc)</code> function generates code to evaluate <var>vtop</var> (the 1825 top value of the stack) into registers. <var>rc</var> selects in which 1826 register class the value should be put. <code>gv()</code> is the <em>most 1827 important function</em> of the code generator. 1828 </p> 1829 <p><code>gv2()</code> is the same as <code>gv()</code> but for the top two stack 1873 </P><P> 1874 1875 The <CODE>gv(rc)</CODE> function generates code to evaluate <VAR>vtop</VAR> (the 1876 top value of the stack) into registers. <VAR>rc</VAR> selects in which 1877 register class the value should be put. <CODE>gv()</CODE> is the <EM>most 1878 important function</EM> of the code generator. 1879 </P><P> 1880 1881 <CODE>gv2()</CODE> is the same as <CODE>gv()</CODE> but for the top two stack 1830 1882 entries. 1831 </p> 1832 <hr size="6"> 1833 <a name="CPU-dependent-code-generation"></a> 1834 <table cellpadding="1" cellspacing="1" border="0"> 1835 <tr><td valign="middle" align="left">[<a href="#Manipulating-the-value-stack" title="Previous section in reading order"> < </a>]</td> 1836 <td valign="middle" align="left">[<a href="#Optimizations-done" title="Next section in reading order"> > </a>]</td> 1837 <td valign="middle" align="left"> </td> 1838 <td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1839 <td valign="middle" align="left">[<a href="#Code-generation" title="Up section"> Up </a>]</td> 1840 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> >> </a>]</td> 1841 <td valign="middle" align="left"> </td> 1842 <td valign="middle" align="left"> </td> 1843 <td valign="middle" align="left"> </td> 1844 <td valign="middle" align="left"> </td> 1845 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1846 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1847 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1848 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1849 </tr></table> 1850 <h3 class="subsection">8.7.4 CPU dependent code generation</h3> 1851 <a name="index-CPU-dependent"></a> 1852 <p>See the ‘<tt>i386-gen.c</tt>’ file to have an example. 1853 </p> 1854 <dl compact="compact"> 1855 <dt> <code>load()</code></dt> 1856 <dd><p>must generate the code needed to load a stack value into a register. 1857 </p> 1858 </dd> 1859 <dt> <code>store()</code></dt> 1860 <dd><p>must generate the code needed to store a register into a stack value 1883 </P><P> 1884 1885 <HR SIZE="6"> 1886 <A NAME="SEC34"></A> 1887 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1888 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC33"> < </A>]</TD> 1889 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC35"> > </A>]</TD> 1890 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC35"> << </A>]</TD> 1891 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC30"> Up </A>]</TD> 1892 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC35"> >> </A>]</TD> 1893 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1894 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1895 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1896 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1897 </TR></TABLE> 1898 <H3> 8.7.4 CPU dependent code generation </H3> 1899 <!--docid::SEC34::--> 1900 See the <TT>`i386-gen.c'</TT> file to have an example. 1901 <P> 1902 1903 <DL COMPACT> 1904 1905 <DT><CODE>load()</CODE> 1906 <DD>must generate the code needed to load a stack value into a register. 1907 <P> 1908 1909 <DT><CODE>store()</CODE> 1910 <DD>must generate the code needed to store a register into a stack value 1861 1911 lvalue. 1862 </p> 1863 </dd> 1864 <dt> <code>gfunc_start()</code></dt> 1865 <dt> <code>gfunc_param()</code></dt> 1866 <dt> <code>gfunc_call()</code></dt> 1867 <dd><p>should generate a function call 1868 </p> 1869 </dd> 1870 <dt> <code>gfunc_prolog()</code></dt> 1871 <dt> <code>gfunc_epilog()</code></dt> 1872 <dd><p>should generate a function prolog/epilog. 1873 </p> 1874 </dd> 1875 <dt> <code>gen_opi(op)</code></dt> 1876 <dd><p>must generate the binary integer operation <var>op</var> on the two top 1877 entries of the stack which are guaranted to contain integer types. 1878 </p> 1879 <p>The result value should be put on the stack. 1880 </p> 1881 </dd> 1882 <dt> <code>gen_opf(op)</code></dt> 1883 <dd><p>same as <code>gen_opi()</code> for floating point operations. The two top 1884 entries of the stack are guaranted to contain floating point values of 1912 <P> 1913 1914 <DT><CODE>gfunc_start()</CODE> 1915 <DD><DT><CODE>gfunc_param()</CODE> 1916 <DD><DT><CODE>gfunc_call()</CODE> 1917 <DD>should generate a function call 1918 <P> 1919 1920 <DT><CODE>gfunc_prolog()</CODE> 1921 <DD><DT><CODE>gfunc_epilog()</CODE> 1922 <DD>should generate a function prolog/epilog. 1923 <P> 1924 1925 <DT><CODE>gen_opi(op)</CODE> 1926 <DD>must generate the binary integer operation <VAR>op</VAR> on the two top 1927 entries of the stack which are guaranteed to contain integer types. 1928 <P> 1929 1930 The result value should be put on the stack. 1931 </P><P> 1932 1933 <DT><CODE>gen_opf(op)</CODE> 1934 <DD>same as <CODE>gen_opi()</CODE> for floating point operations. The two top 1935 entries of the stack are guaranteed to contain floating point values of 1885 1936 same types. 1886 </p> 1887 </dd> 1888 <dt> <code>gen_cvt_itof()</code></dt> 1889 <dd><p>integer to floating point conversion. 1890 </p> 1891 </dd> 1892 <dt> <code>gen_cvt_ftoi()</code></dt> 1893 <dd><p>floating point to integer conversion. 1894 </p> 1895 </dd> 1896 <dt> <code>gen_cvt_ftof()</code></dt> 1897 <dd><p>floating point to floating point of different size conversion. 1898 </p> 1899 </dd> 1900 <dt> <code>gen_bounded_ptr_add()</code></dt> 1901 <dt> <code>gen_bounded_ptr_deref()</code></dt> 1902 <dd><p>are only used for bounds checking. 1903 </p> 1904 </dd> 1905 </dl> 1906 1907 <hr size="6"> 1908 <a name="Optimizations-done"></a> 1909 <table cellpadding="1" cellspacing="1" border="0"> 1910 <tr><td valign="middle" align="left">[<a href="#CPU-dependent-code-generation" title="Previous section in reading order"> < </a>]</td> 1911 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next section in reading order"> > </a>]</td> 1912 <td valign="middle" align="left"> </td> 1913 <td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1914 <td valign="middle" align="left">[<a href="#devel" title="Up section"> Up </a>]</td> 1915 <td valign="middle" align="left">[<a href="#Concept-Index" title="Next chapter"> >> </a>]</td> 1916 <td valign="middle" align="left"> </td> 1917 <td valign="middle" align="left"> </td> 1918 <td valign="middle" align="left"> </td> 1919 <td valign="middle" align="left"> </td> 1920 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1921 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1922 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1923 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1924 </tr></table> 1925 <h2 class="section">8.8 Optimizations done</h2> 1926 <a name="index-optimizations"></a> 1927 <a name="index-constant-propagation"></a> 1928 <a name="index-strength-reduction"></a> 1929 <a name="index-comparison-operators"></a> 1930 <a name="index-caching-processor-flags"></a> 1931 <a name="index-flags_002c-caching"></a> 1932 <a name="index-jump-optimization"></a> 1933 <p>Constant propagation is done for all operations. Multiplications and 1937 <P> 1938 1939 <DT><CODE>gen_cvt_itof()</CODE> 1940 <DD>integer to floating point conversion. 1941 <P> 1942 1943 <DT><CODE>gen_cvt_ftoi()</CODE> 1944 <DD>floating point to integer conversion. 1945 <P> 1946 1947 <DT><CODE>gen_cvt_ftof()</CODE> 1948 <DD>floating point to floating point of different size conversion. 1949 <P> 1950 1951 <DT><CODE>gen_bounded_ptr_add()</CODE> 1952 <DD><DT><CODE>gen_bounded_ptr_deref()</CODE> 1953 <DD>are only used for bounds checking. 1954 <P> 1955 1956 </DL> 1957 <P> 1958 1959 <HR SIZE="6"> 1960 <A NAME="SEC35"></A> 1961 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1962 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC34"> < </A>]</TD> 1963 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36"> > </A>]</TD> 1964 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD> 1965 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC23"> Up </A>]</TD> 1966 <TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD> 1967 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1968 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1969 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1970 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1971 </TR></TABLE> 1972 <H2> 8.8 Optimizations done </H2> 1973 <!--docid::SEC35::--> 1974 Constant propagation is done for all operations. Multiplications and 1934 1975 divisions are optimized to shifts when appropriate. Comparison 1935 1976 operators are optimized by maintaining a special cache for the 1936 processor flags. & amp;&, || and ! are optimized by maintaining a special1937 ’jump target’value. No other jump optimization is currently performed1977 processor flags. &&, || and ! are optimized by maintaining a special 1978 'jump target' value. No other jump optimization is currently performed 1938 1979 because it would require to store the code in a more abstract fashion. 1939 </p> 1940 <hr size="6"> 1941 <a name="Concept-Index"></a> 1942 <table cellpadding="1" cellspacing="1" border="0"> 1943 <tr><td valign="middle" align="left">[<a href="#Optimizations-done" title="Previous section in reading order"> < </a>]</td> 1944 <td valign="middle" align="left">[ > ]</td> 1945 <td valign="middle" align="left"> </td> 1946 <td valign="middle" align="left">[<a href="#devel" title="Beginning of this chapter or previous chapter"> << </a>]</td> 1947 <td valign="middle" align="left">[<a href="#Top" title="Up section"> Up </a>]</td> 1948 <td valign="middle" align="left">[ >> ]</td> 1949 <td valign="middle" align="left"> </td> 1950 <td valign="middle" align="left"> </td> 1951 <td valign="middle" align="left"> </td> 1952 <td valign="middle" align="left"> </td> 1953 <td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 1954 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 1955 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 1956 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 1957 </tr></table> 1958 <h1 class="unnumbered">Concept Index</h1> 1959 <table><tr><th valign="top">Jump to: </th><td><a href="#Concept-Index_cp_symbol-1" class="summary-letter"><b>_</b></a> 1960 1961 <br> 1962 <a href="#Concept-Index_cp_letter-A" class="summary-letter"><b>A</b></a> 1963 1964 <a href="#Concept-Index_cp_letter-B" class="summary-letter"><b>B</b></a> 1965 1966 <a href="#Concept-Index_cp_letter-C" class="summary-letter"><b>C</b></a> 1967 1968 <a href="#Concept-Index_cp_letter-D" class="summary-letter"><b>D</b></a> 1969 1970 <a href="#Concept-Index_cp_letter-E" class="summary-letter"><b>E</b></a> 1971 1972 <a href="#Concept-Index_cp_letter-F" class="summary-letter"><b>F</b></a> 1973 1974 <a href="#Concept-Index_cp_letter-G" class="summary-letter"><b>G</b></a> 1975 1976 <a href="#Concept-Index_cp_letter-I" class="summary-letter"><b>I</b></a> 1977 1978 <a href="#Concept-Index_cp_letter-J" class="summary-letter"><b>J</b></a> 1979 1980 <a href="#Concept-Index_cp_letter-L" class="summary-letter"><b>L</b></a> 1981 1982 <a href="#Concept-Index_cp_letter-M" class="summary-letter"><b>M</b></a> 1983 1984 <a href="#Concept-Index_cp_letter-O" class="summary-letter"><b>O</b></a> 1985 1986 <a href="#Concept-Index_cp_letter-P" class="summary-letter"><b>P</b></a> 1987 1988 <a href="#Concept-Index_cp_letter-Q" class="summary-letter"><b>Q</b></a> 1989 1990 <a href="#Concept-Index_cp_letter-R" class="summary-letter"><b>R</b></a> 1991 1992 <a href="#Concept-Index_cp_letter-S" class="summary-letter"><b>S</b></a> 1993 1994 <a href="#Concept-Index_cp_letter-T" class="summary-letter"><b>T</b></a> 1995 1996 <a href="#Concept-Index_cp_letter-U" class="summary-letter"><b>U</b></a> 1997 1998 <a href="#Concept-Index_cp_letter-V" class="summary-letter"><b>V</b></a> 1999 2000 <a href="#Concept-Index_cp_letter-W" class="summary-letter"><b>W</b></a> 2001 2002 </td></tr></table> 2003 <table border="0" class="index-cp"> 2004 <tr><td></td><th align="left">Index Entry</th><th align="left"> Section</th></tr> 2005 <tr><td colspan="3"> <hr></td></tr> 2006 <tr><th><a name="Concept-Index_cp_symbol-1">_</a></th><td></td><td></td></tr> 2007 <tr><td></td><td valign="top"><a href="#index-_005f_005fasm_005f_005f">__asm__</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr> 2008 <tr><td colspan="3"> <hr></td></tr> 2009 <tr><th><a name="Concept-Index_cp_letter-A">A</a></th><td></td><td></td></tr> 2010 <tr><td></td><td valign="top"><a href="#index-align-directive">align directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2011 <tr><td></td><td valign="top"><a href="#index-aligned-attribute">aligned attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr> 2012 <tr><td></td><td valign="top"><a href="#index-ascii-directive">ascii directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2013 <tr><td></td><td valign="top"><a href="#index-asciz-directive">asciz directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2014 <tr><td></td><td valign="top"><a href="#index-assembler">assembler</a></td><td valign="top"><a href="#X86-Assembler">4.5 X86 Assembler</a></td></tr> 2015 <tr><td></td><td valign="top"><a href="#index-assembler-directives">assembler directives</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2016 <tr><td></td><td valign="top"><a href="#index-assembly_002c-inline">assembly, inline</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr> 2017 <tr><td colspan="3"> <hr></td></tr> 2018 <tr><th><a name="Concept-Index_cp_letter-B">B</a></th><td></td><td></td></tr> 2019 <tr><td></td><td valign="top"><a href="#index-bound-checks">bound checks</a></td><td valign="top"><a href="#Bounds">6. TinyCC Memory and Bound checks</a></td></tr> 2020 <tr><td></td><td valign="top"><a href="#index-bss-directive">bss directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2021 <tr><td></td><td valign="top"><a href="#index-byte-directive">byte directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2022 <tr><td colspan="3"> <hr></td></tr> 2023 <tr><th><a name="Concept-Index_cp_letter-C">C</a></th><td></td><td></td></tr> 2024 <tr><td></td><td valign="top"><a href="#index-caching-processor-flags">caching processor flags</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr> 2025 <tr><td></td><td valign="top"><a href="#index-cdecl-attribute">cdecl attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr> 2026 <tr><td></td><td valign="top"><a href="#index-code-generation">code generation</a></td><td valign="top"><a href="#Code-generation">8.7 Code generation</a></td></tr> 2027 <tr><td></td><td valign="top"><a href="#index-comparison-operators">comparison operators</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr> 2028 <tr><td></td><td valign="top"><a href="#index-constant-propagation">constant propagation</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr> 2029 <tr><td></td><td valign="top"><a href="#index-CPU-dependent">CPU dependent</a></td><td valign="top"><a href="#CPU-dependent-code-generation">8.7.4 CPU dependent code generation</a></td></tr> 2030 <tr><td colspan="3"> <hr></td></tr> 2031 <tr><th><a name="Concept-Index_cp_letter-D">D</a></th><td></td><td></td></tr> 2032 <tr><td></td><td valign="top"><a href="#index-data-directive">data directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2033 <tr><td></td><td valign="top"><a href="#index-directives_002c-assembler">directives, assembler</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2034 <tr><td></td><td valign="top"><a href="#index-dllexport-attribute">dllexport attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr> 2035 <tr><td colspan="3"> <hr></td></tr> 2036 <tr><th><a name="Concept-Index_cp_letter-E">E</a></th><td></td><td></td></tr> 2037 <tr><td></td><td valign="top"><a href="#index-ELF">ELF</a></td><td valign="top"><a href="#ELF-file-generation">5.1 ELF file generation</a></td></tr> 2038 <tr><td colspan="3"> <hr></td></tr> 2039 <tr><th><a name="Concept-Index_cp_letter-F">F</a></th><td></td><td></td></tr> 2040 <tr><td></td><td valign="top"><a href="#index-FILE_002c-linker-command">FILE, linker command</a></td><td valign="top"><a href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></td></tr> 2041 <tr><td></td><td valign="top"><a href="#index-fill-directive">fill directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2042 <tr><td></td><td valign="top"><a href="#index-flags_002c-caching">flags, caching</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr> 2043 <tr><td colspan="3"> <hr></td></tr> 2044 <tr><th><a name="Concept-Index_cp_letter-G">G</a></th><td></td><td></td></tr> 2045 <tr><td></td><td valign="top"><a href="#index-gas">gas</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr> 2046 <tr><td></td><td valign="top"><a href="#index-global-directive">global directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2047 <tr><td></td><td valign="top"><a href="#index-globl-directive">globl directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2048 <tr><td></td><td valign="top"><a href="#index-GROUP_002c-linker-command">GROUP, linker command</a></td><td valign="top"><a href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></td></tr> 2049 <tr><td colspan="3"> <hr></td></tr> 2050 <tr><th><a name="Concept-Index_cp_letter-I">I</a></th><td></td><td></td></tr> 2051 <tr><td></td><td valign="top"><a href="#index-inline-assembly">inline assembly</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr> 2052 <tr><td></td><td valign="top"><a href="#index-int-directive">int directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2053 <tr><td colspan="3"> <hr></td></tr> 2054 <tr><th><a name="Concept-Index_cp_letter-J">J</a></th><td></td><td></td></tr> 2055 <tr><td></td><td valign="top"><a href="#index-jump-optimization">jump optimization</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr> 2056 <tr><td colspan="3"> <hr></td></tr> 2057 <tr><th><a name="Concept-Index_cp_letter-L">L</a></th><td></td><td></td></tr> 2058 <tr><td></td><td valign="top"><a href="#index-linker">linker</a></td><td valign="top"><a href="#linker">5. TinyCC Linker</a></td></tr> 2059 <tr><td></td><td valign="top"><a href="#index-linker-scripts">linker scripts</a></td><td valign="top"><a href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></td></tr> 2060 <tr><td></td><td valign="top"><a href="#index-long-directive">long directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2061 <tr><td colspan="3"> <hr></td></tr> 2062 <tr><th><a name="Concept-Index_cp_letter-M">M</a></th><td></td><td></td></tr> 2063 <tr><td></td><td valign="top"><a href="#index-memory-checks">memory checks</a></td><td valign="top"><a href="#Bounds">6. TinyCC Memory and Bound checks</a></td></tr> 2064 <tr><td colspan="3"> <hr></td></tr> 2065 <tr><th><a name="Concept-Index_cp_letter-O">O</a></th><td></td><td></td></tr> 2066 <tr><td></td><td valign="top"><a href="#index-optimizations">optimizations</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr> 2067 <tr><td></td><td valign="top"><a href="#index-org-directive">org directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2068 <tr><td></td><td valign="top"><a href="#index-OUTPUT_005fFORMAT_002c-linker-command">OUTPUT_FORMAT, linker command</a></td><td valign="top"><a href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></td></tr> 2069 <tr><td colspan="3"> <hr></td></tr> 2070 <tr><th><a name="Concept-Index_cp_letter-P">P</a></th><td></td><td></td></tr> 2071 <tr><td></td><td valign="top"><a href="#index-packed-attribute">packed attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr> 2072 <tr><td></td><td valign="top"><a href="#index-PE_002di386">PE-i386</a></td><td valign="top"><a href="#PE_002di386-file-generation">5.3 PE-i386 file generation</a></td></tr> 2073 <tr><td></td><td valign="top"><a href="#index-previous-directive">previous directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2074 <tr><td colspan="3"> <hr></td></tr> 2075 <tr><th><a name="Concept-Index_cp_letter-Q">Q</a></th><td></td><td></td></tr> 2076 <tr><td></td><td valign="top"><a href="#index-quad-directive">quad directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2077 <tr><td colspan="3"> <hr></td></tr> 2078 <tr><th><a name="Concept-Index_cp_letter-R">R</a></th><td></td><td></td></tr> 2079 <tr><td></td><td valign="top"><a href="#index-regparm-attribute">regparm attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr> 2080 <tr><td colspan="3"> <hr></td></tr> 2081 <tr><th><a name="Concept-Index_cp_letter-S">S</a></th><td></td><td></td></tr> 2082 <tr><td></td><td valign="top"><a href="#index-scripts_002c-linker">scripts, linker</a></td><td valign="top"><a href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></td></tr> 2083 <tr><td></td><td valign="top"><a href="#index-section-attribute">section attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr> 2084 <tr><td></td><td valign="top"><a href="#index-section-directive">section directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2085 <tr><td></td><td valign="top"><a href="#index-short-directive">short directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2086 <tr><td></td><td valign="top"><a href="#index-skip-directive">skip directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2087 <tr><td></td><td valign="top"><a href="#index-space-directive">space directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2088 <tr><td></td><td valign="top"><a href="#index-stdcall-attribute">stdcall attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr> 2089 <tr><td></td><td valign="top"><a href="#index-strength-reduction">strength reduction</a></td><td valign="top"><a href="#Optimizations-done">8.8 Optimizations done</a></td></tr> 2090 <tr><td></td><td valign="top"><a href="#index-string-directive">string directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2091 <tr><td colspan="3"> <hr></td></tr> 2092 <tr><th><a name="Concept-Index_cp_letter-T">T</a></th><td></td><td></td></tr> 2093 <tr><td></td><td valign="top"><a href="#index-TARGET_002c-linker-command">TARGET, linker command</a></td><td valign="top"><a href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></td></tr> 2094 <tr><td></td><td valign="top"><a href="#index-text-directive">text directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2095 <tr><td colspan="3"> <hr></td></tr> 2096 <tr><th><a name="Concept-Index_cp_letter-U">U</a></th><td></td><td></td></tr> 2097 <tr><td></td><td valign="top"><a href="#index-unused-attribute">unused attribute</a></td><td valign="top"><a href="#GNU-C-extensions">3.3 GNU C extensions</a></td></tr> 2098 <tr><td colspan="3"> <hr></td></tr> 2099 <tr><th><a name="Concept-Index_cp_letter-V">V</a></th><td></td><td></td></tr> 2100 <tr><td></td><td valign="top"><a href="#index-value-stack">value stack</a></td><td valign="top"><a href="#Manipulating-the-value-stack">8.7.3 Manipulating the value stack</a></td></tr> 2101 <tr><td></td><td valign="top"><a href="#index-value-stack_002c-introduction">value stack, introduction</a></td><td valign="top"><a href="#The-value-stack">8.7.2 The value stack</a></td></tr> 2102 <tr><td colspan="3"> <hr></td></tr> 2103 <tr><th><a name="Concept-Index_cp_letter-W">W</a></th><td></td><td></td></tr> 2104 <tr><td></td><td valign="top"><a href="#index-word-directive">word directive</a></td><td valign="top"><a href="#Directives">4.4 Directives</a></td></tr> 2105 <tr><td colspan="3"> <hr></td></tr> 2106 </table> 2107 <table><tr><th valign="top">Jump to: </th><td><a href="#Concept-Index_cp_symbol-1" class="summary-letter"><b>_</b></a> 2108 2109 <br> 2110 <a href="#Concept-Index_cp_letter-A" class="summary-letter"><b>A</b></a> 2111 2112 <a href="#Concept-Index_cp_letter-B" class="summary-letter"><b>B</b></a> 2113 2114 <a href="#Concept-Index_cp_letter-C" class="summary-letter"><b>C</b></a> 2115 2116 <a href="#Concept-Index_cp_letter-D" class="summary-letter"><b>D</b></a> 2117 2118 <a href="#Concept-Index_cp_letter-E" class="summary-letter"><b>E</b></a> 2119 2120 <a href="#Concept-Index_cp_letter-F" class="summary-letter"><b>F</b></a> 2121 2122 <a href="#Concept-Index_cp_letter-G" class="summary-letter"><b>G</b></a> 2123 2124 <a href="#Concept-Index_cp_letter-I" class="summary-letter"><b>I</b></a> 2125 2126 <a href="#Concept-Index_cp_letter-J" class="summary-letter"><b>J</b></a> 2127 2128 <a href="#Concept-Index_cp_letter-L" class="summary-letter"><b>L</b></a> 2129 2130 <a href="#Concept-Index_cp_letter-M" class="summary-letter"><b>M</b></a> 2131 2132 <a href="#Concept-Index_cp_letter-O" class="summary-letter"><b>O</b></a> 2133 2134 <a href="#Concept-Index_cp_letter-P" class="summary-letter"><b>P</b></a> 2135 2136 <a href="#Concept-Index_cp_letter-Q" class="summary-letter"><b>Q</b></a> 2137 2138 <a href="#Concept-Index_cp_letter-R" class="summary-letter"><b>R</b></a> 2139 2140 <a href="#Concept-Index_cp_letter-S" class="summary-letter"><b>S</b></a> 2141 2142 <a href="#Concept-Index_cp_letter-T" class="summary-letter"><b>T</b></a> 2143 2144 <a href="#Concept-Index_cp_letter-U" class="summary-letter"><b>U</b></a> 2145 2146 <a href="#Concept-Index_cp_letter-V" class="summary-letter"><b>V</b></a> 2147 2148 <a href="#Concept-Index_cp_letter-W" class="summary-letter"><b>W</b></a> 2149 2150 </td></tr></table> 2151 2152 <hr size="6"> 2153 <a name="SEC_Contents"></a> 2154 <table cellpadding="1" cellspacing="1" border="0"> 2155 <tr><td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 2156 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 2157 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 2158 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 2159 </tr></table> 2160 <h1>Table of Contents</h1> 2161 <div class="contents"> 2162 2163 <ul class="toc"> 2164 <li><a name="toc-Introduction-1" href="#Introduction">1. Introduction</a></li> 2165 <li><a name="toc-Command-line-invocation" href="#Invoke">2. Command line invocation</a> 2166 <ul class="toc"> 2167 <li><a name="toc-Quick-start" href="#Quick-start">2.1 Quick start</a></li> 2168 <li><a name="toc-Option-summary" href="#Option-summary">2.2 Option summary</a></li> 2169 </ul></li> 2170 <li><a name="toc-C-language-support" href="#Clang">3. C language support</a> 2171 <ul class="toc"> 2172 <li><a name="toc-ANSI-C" href="#ANSI-C">3.1 ANSI C</a></li> 2173 <li><a name="toc-ISOC99-extensions" href="#ISOC99-extensions">3.2 ISOC99 extensions</a></li> 2174 <li><a name="toc-GNU-C-extensions" href="#GNU-C-extensions">3.3 GNU C extensions</a></li> 2175 <li><a name="toc-TinyCC-extensions" href="#TinyCC-extensions">3.4 TinyCC extensions</a></li> 2176 </ul></li> 2177 <li><a name="toc-TinyCC-Assembler" href="#asm">4. TinyCC Assembler</a> 2178 <ul class="toc"> 2179 <li><a name="toc-Syntax" href="#Syntax">4.1 Syntax</a></li> 2180 <li><a name="toc-Expressions" href="#Expressions">4.2 Expressions</a></li> 2181 <li><a name="toc-Labels" href="#Labels">4.3 Labels</a></li> 2182 <li><a name="toc-Directives" href="#Directives">4.4 Directives</a></li> 2183 <li><a name="toc-X86-Assembler" href="#X86-Assembler">4.5 X86 Assembler</a></li> 2184 </ul></li> 2185 <li><a name="toc-TinyCC-Linker" href="#linker">5. TinyCC Linker</a> 2186 <ul class="toc"> 2187 <li><a name="toc-ELF-file-generation" href="#ELF-file-generation">5.1 ELF file generation</a></li> 2188 <li><a name="toc-ELF-file-loader" href="#ELF-file-loader">5.2 ELF file loader</a></li> 2189 <li><a name="toc-PE_002di386-file-generation" href="#PE_002di386-file-generation">5.3 PE-i386 file generation</a></li> 2190 <li><a name="toc-GNU-Linker-Scripts" href="#GNU-Linker-Scripts">5.4 GNU Linker Scripts</a></li> 2191 </ul></li> 2192 <li><a name="toc-TinyCC-Memory-and-Bound-checks" href="#Bounds">6. TinyCC Memory and Bound checks</a></li> 2193 <li><a name="toc-The-libtcc-library" href="#Libtcc">7. The <code>libtcc</code> library</a></li> 2194 <li><a name="toc-Developer_0027s-guide" href="#devel">8. Developer’s guide</a> 2195 <ul class="toc"> 2196 <li><a name="toc-File-reading" href="#File-reading">8.1 File reading</a></li> 2197 <li><a name="toc-Lexer" href="#Lexer">8.2 Lexer</a></li> 2198 <li><a name="toc-Parser" href="#Parser">8.3 Parser</a></li> 2199 <li><a name="toc-Types" href="#Types">8.4 Types</a></li> 2200 <li><a name="toc-Symbols" href="#Symbols">8.5 Symbols</a></li> 2201 <li><a name="toc-Sections" href="#Sections">8.6 Sections</a></li> 2202 <li><a name="toc-Code-generation" href="#Code-generation">8.7 Code generation</a> 2203 <ul class="toc"> 2204 <li><a name="toc-Introduction-2" href="#Introduction-2">8.7.1 Introduction</a></li> 2205 <li><a name="toc-The-value-stack" href="#The-value-stack">8.7.2 The value stack</a></li> 2206 <li><a name="toc-Manipulating-the-value-stack" href="#Manipulating-the-value-stack">8.7.3 Manipulating the value stack</a></li> 2207 <li><a name="toc-CPU-dependent-code-generation" href="#CPU-dependent-code-generation">8.7.4 CPU dependent code generation</a></li> 2208 </ul></li> 2209 <li><a name="toc-Optimizations-done" href="#Optimizations-done">8.8 Optimizations done</a></li> 2210 </ul></li> 2211 <li><a name="toc-Concept-Index" href="#Concept-Index">Concept Index</a></li> 2212 </ul> 2213 </div> 2214 <hr size="1"> 2215 <a name="SEC_About"></a> 2216 <table cellpadding="1" cellspacing="1" border="0"> 2217 <tr><td valign="middle" align="left">[<a href="#Top" title="Cover (top) of document">Top</a>]</td> 2218 <td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of contents">Contents</a>]</td> 2219 <td valign="middle" align="left">[<a href="#Concept-Index" title="Index">Index</a>]</td> 2220 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? </a>]</td> 2221 </tr></table> 2222 <h1>About This Document</h1> 2223 <p> 2224 This document was generated by <em>Thomas Preud'homme</em> on <em>February 15, 2013</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html 1.82</em></a>. 2225 </p> 2226 <p> 2227 The buttons in the navigation panels have the following meaning: 2228 </p> 2229 <table border="1"> 2230 <tr> 2231 <th> Button </th> 2232 <th> Name </th> 2233 <th> Go to </th> 2234 <th> From 1.2.3 go to</th> 2235 </tr> 2236 <tr> 2237 <td align="center"> [ < ] </td> 2238 <td align="center">Back</td> 2239 <td>Previous section in reading order</td> 2240 <td>1.2.2</td> 2241 </tr> 2242 <tr> 2243 <td align="center"> [ > ] </td> 2244 <td align="center">Forward</td> 2245 <td>Next section in reading order</td> 2246 <td>1.2.4</td> 2247 </tr> 2248 <tr> 2249 <td align="center"> [ << ] </td> 2250 <td align="center">FastBack</td> 2251 <td>Beginning of this chapter or previous chapter</td> 2252 <td>1</td> 2253 </tr> 2254 <tr> 2255 <td align="center"> [ Up ] </td> 2256 <td align="center">Up</td> 2257 <td>Up section</td> 2258 <td>1.2</td> 2259 </tr> 2260 <tr> 2261 <td align="center"> [ >> ] </td> 2262 <td align="center">FastForward</td> 2263 <td>Next chapter</td> 2264 <td>2</td> 2265 </tr> 2266 <tr> 2267 <td align="center"> [Top] </td> 2268 <td align="center">Top</td> 2269 <td>Cover (top) of document</td> 2270 <td> </td> 2271 </tr> 2272 <tr> 2273 <td align="center"> [Contents] </td> 2274 <td align="center">Contents</td> 2275 <td>Table of contents</td> 2276 <td> </td> 2277 </tr> 2278 <tr> 2279 <td align="center"> [Index] </td> 2280 <td align="center">Index</td> 2281 <td>Index</td> 2282 <td> </td> 2283 </tr> 2284 <tr> 2285 <td align="center"> [ ? ] </td> 2286 <td align="center">About</td> 2287 <td>About (help)</td> 2288 <td> </td> 2289 </tr> 2290 </table> 2291 2292 <p> 2293 where the <strong> Example </strong> assumes that the current position is at <strong> Subsubsection One-Two-Three </strong> of a document of the following structure: 2294 </p> 2295 2296 <ul> 2297 <li> 1. Section One 2298 <ul> 2299 <li>1.1 Subsection One-One 2300 <ul> 2301 <li>...</li> 2302 </ul> 2303 </li> 2304 <li>1.2 Subsection One-Two 2305 <ul> 2306 <li>1.2.1 Subsubsection One-Two-One</li> 2307 <li>1.2.2 Subsubsection One-Two-Two</li> 2308 <li>1.2.3 Subsubsection One-Two-Three 2309 <strong><== Current Position </strong></li> 2310 <li>1.2.4 Subsubsection One-Two-Four</li> 2311 </ul> 2312 </li> 2313 <li>1.3 Subsection One-Three 2314 <ul> 2315 <li>...</li> 2316 </ul> 2317 </li> 2318 <li>1.4 Subsection One-Four</li> 2319 </ul> 2320 </li> 2321 </ul> 2322 2323 <hr size="1"> 2324 <p> 2325 <font size="-1"> 2326 This document was generated by <em>Thomas Preud'homme</em> on <em>February 15, 2013</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html 1.82</em></a>. 2327 </font> 2328 <br> 2329 2330 </p> 2331 </body> 2332 </html> 1980 <P> 1981 1982 <HR SIZE="6"> 1983 <A NAME="SEC36"></A> 1984 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 1985 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC35"> < </A>]</TD> 1986 <TD VALIGN="MIDDLE" ALIGN="LEFT">[ > ]</TD> 1987 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD> 1988 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top"> Up </A>]</TD> 1989 <TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD> 1990 <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 1991 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 1992 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 1993 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 1994 </TR></TABLE> 1995 <H1> Concept Index </H1> 1996 <!--docid::SEC36::--> 1997 <table><tr><th valign=top>Jump to: </th><td><A HREF="tcc-doc.html#cp__" style="text-decoration:none"><b>_</b></A> 1998 1999 <BR> 2000 <A HREF="tcc-doc.html#cp_A" style="text-decoration:none"><b>A</b></A> 2001 2002 <A HREF="tcc-doc.html#cp_B" style="text-decoration:none"><b>B</b></A> 2003 2004 <A HREF="tcc-doc.html#cp_C" style="text-decoration:none"><b>C</b></A> 2005 2006 <A HREF="tcc-doc.html#cp_D" style="text-decoration:none"><b>D</b></A> 2007 2008 <A HREF="tcc-doc.html#cp_E" style="text-decoration:none"><b>E</b></A> 2009 2010 <A HREF="tcc-doc.html#cp_F" style="text-decoration:none"><b>F</b></A> 2011 2012 <A HREF="tcc-doc.html#cp_G" style="text-decoration:none"><b>G</b></A> 2013 2014 <A HREF="tcc-doc.html#cp_I" style="text-decoration:none"><b>I</b></A> 2015 2016 <A HREF="tcc-doc.html#cp_J" style="text-decoration:none"><b>J</b></A> 2017 2018 <A HREF="tcc-doc.html#cp_L" style="text-decoration:none"><b>L</b></A> 2019 2020 <A HREF="tcc-doc.html#cp_M" style="text-decoration:none"><b>M</b></A> 2021 2022 <A HREF="tcc-doc.html#cp_O" style="text-decoration:none"><b>O</b></A> 2023 2024 <A HREF="tcc-doc.html#cp_P" style="text-decoration:none"><b>P</b></A> 2025 2026 <A HREF="tcc-doc.html#cp_Q" style="text-decoration:none"><b>Q</b></A> 2027 2028 <A HREF="tcc-doc.html#cp_R" style="text-decoration:none"><b>R</b></A> 2029 2030 <A HREF="tcc-doc.html#cp_S" style="text-decoration:none"><b>S</b></A> 2031 2032 <A HREF="tcc-doc.html#cp_T" style="text-decoration:none"><b>T</b></A> 2033 2034 <A HREF="tcc-doc.html#cp_U" style="text-decoration:none"><b>U</b></A> 2035 2036 <A HREF="tcc-doc.html#cp_V" style="text-decoration:none"><b>V</b></A> 2037 2038 <A HREF="tcc-doc.html#cp_W" style="text-decoration:none"><b>W</b></A> 2039 2040 </td></tr></table><br><P></P> 2041 <TABLE border=0> 2042 <TR><TD></TD><TH ALIGN=LEFT>Index Entry</TH><TH ALIGN=LEFT> Section</TH></TR> 2043 <TR><TD COLSPAN=3> <HR></TD></TR> 2044 <TR><TH><A NAME="cp__"></A>_</TH><TD></TD><TD></TD></TR> 2045 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#IDX11">__asm__</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC8">3.3 GNU C extensions</A></TD></TR> 2046 <TR><TD COLSPAN=3> <HR></TD></TR> 2047 <TR><TH><A NAME="cp_A"></A>A</TH><TD></TD><TD></TD></TR> 2048 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">align directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2049 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#IDX1">aligned attribute</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC8">3.3 GNU C extensions</A></TD></TR> 2050 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">ascii directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2051 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">asciz directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2052 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC15">assembler</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC15">4.5 X86 Assembler</A></TD></TR> 2053 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">assembler directives</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2054 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#IDX10">assembly, inline</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC8">3.3 GNU C extensions</A></TD></TR> 2055 <TR><TD COLSPAN=3> <HR></TD></TR> 2056 <TR><TH><A NAME="cp_B"></A>B</TH><TD></TD><TD></TD></TR> 2057 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC21">bound checks</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC21">6. TinyCC Memory and Bound checks</A></TD></TR> 2058 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">bss directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2059 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">byte directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2060 <TR><TD COLSPAN=3> <HR></TD></TR> 2061 <TR><TH><A NAME="cp_C"></A>C</TH><TD></TD><TD></TD></TR> 2062 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">caching processor flags</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">8.8 Optimizations done</A></TD></TR> 2063 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#IDX5">cdecl attribute</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC8">3.3 GNU C extensions</A></TD></TR> 2064 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC30">code generation</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC30">8.7 Code generation</A></TD></TR> 2065 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">comparison operators</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">8.8 Optimizations done</A></TD></TR> 2066 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">constant propagation</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">8.8 Optimizations done</A></TD></TR> 2067 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC34">CPU dependent</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC34">8.7.4 CPU dependent code generation</A></TD></TR> 2068 <TR><TD COLSPAN=3> <HR></TD></TR> 2069 <TR><TH><A NAME="cp_D"></A>D</TH><TD></TD><TD></TD></TR> 2070 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">data directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2071 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">directives, assembler</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2072 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#IDX8">dllexport attribute</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC8">3.3 GNU C extensions</A></TD></TR> 2073 <TR><TD COLSPAN=3> <HR></TD></TR> 2074 <TR><TH><A NAME="cp_E"></A>E</TH><TD></TD><TD></TD></TR> 2075 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC17">ELF</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC17">5.1 ELF file generation</A></TD></TR> 2076 <TR><TD COLSPAN=3> <HR></TD></TR> 2077 <TR><TH><A NAME="cp_F"></A>F</TH><TD></TD><TD></TD></TR> 2078 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC20">FILE, linker command</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC20">5.4 GNU Linker Scripts</A></TD></TR> 2079 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">fill directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2080 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">flags, caching</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">8.8 Optimizations done</A></TD></TR> 2081 <TR><TD COLSPAN=3> <HR></TD></TR> 2082 <TR><TH><A NAME="cp_G"></A>G</TH><TD></TD><TD></TD></TR> 2083 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#IDX12">gas</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC8">3.3 GNU C extensions</A></TD></TR> 2084 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">global directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2085 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">globl directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2086 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC20">GROUP, linker command</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC20">5.4 GNU Linker Scripts</A></TD></TR> 2087 <TR><TD COLSPAN=3> <HR></TD></TR> 2088 <TR><TH><A NAME="cp_I"></A>I</TH><TD></TD><TD></TD></TR> 2089 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#IDX9">inline assembly</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC8">3.3 GNU C extensions</A></TD></TR> 2090 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">int directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2091 <TR><TD COLSPAN=3> <HR></TD></TR> 2092 <TR><TH><A NAME="cp_J"></A>J</TH><TD></TD><TD></TD></TR> 2093 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">jump optimization</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">8.8 Optimizations done</A></TD></TR> 2094 <TR><TD COLSPAN=3> <HR></TD></TR> 2095 <TR><TH><A NAME="cp_L"></A>L</TH><TD></TD><TD></TD></TR> 2096 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC16">linker</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC16">5. TinyCC Linker</A></TD></TR> 2097 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC20">linker scripts</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC20">5.4 GNU Linker Scripts</A></TD></TR> 2098 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">long directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2099 <TR><TD COLSPAN=3> <HR></TD></TR> 2100 <TR><TH><A NAME="cp_M"></A>M</TH><TD></TD><TD></TD></TR> 2101 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC21">memory checks</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC21">6. TinyCC Memory and Bound checks</A></TD></TR> 2102 <TR><TD COLSPAN=3> <HR></TD></TR> 2103 <TR><TH><A NAME="cp_O"></A>O</TH><TD></TD><TD></TD></TR> 2104 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">optimizations</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">8.8 Optimizations done</A></TD></TR> 2105 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">org directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2106 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC20">OUTPUT_FORMAT, linker command</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC20">5.4 GNU Linker Scripts</A></TD></TR> 2107 <TR><TD COLSPAN=3> <HR></TD></TR> 2108 <TR><TH><A NAME="cp_P"></A>P</TH><TD></TD><TD></TD></TR> 2109 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#IDX2">packed attribute</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC8">3.3 GNU C extensions</A></TD></TR> 2110 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC19">PE-i386</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC19">5.3 PE-i386 file generation</A></TD></TR> 2111 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">previous directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2112 <TR><TD COLSPAN=3> <HR></TD></TR> 2113 <TR><TH><A NAME="cp_Q"></A>Q</TH><TD></TD><TD></TD></TR> 2114 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">quad directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2115 <TR><TD COLSPAN=3> <HR></TD></TR> 2116 <TR><TH><A NAME="cp_R"></A>R</TH><TD></TD><TD></TD></TR> 2117 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#IDX7">regparm attribute</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC8">3.3 GNU C extensions</A></TD></TR> 2118 <TR><TD COLSPAN=3> <HR></TD></TR> 2119 <TR><TH><A NAME="cp_S"></A>S</TH><TD></TD><TD></TD></TR> 2120 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC20">scripts, linker</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC20">5.4 GNU Linker Scripts</A></TD></TR> 2121 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#IDX3">section attribute</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC8">3.3 GNU C extensions</A></TD></TR> 2122 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">section directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2123 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">short directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2124 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">skip directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2125 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">space directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2126 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#IDX6">stdcall attribute</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC8">3.3 GNU C extensions</A></TD></TR> 2127 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">strength reduction</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC35">8.8 Optimizations done</A></TD></TR> 2128 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">string directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2129 <TR><TD COLSPAN=3> <HR></TD></TR> 2130 <TR><TH><A NAME="cp_T"></A>T</TH><TD></TD><TD></TD></TR> 2131 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC20">TARGET, linker command</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC20">5.4 GNU Linker Scripts</A></TD></TR> 2132 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">text directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2133 <TR><TD COLSPAN=3> <HR></TD></TR> 2134 <TR><TH><A NAME="cp_U"></A>U</TH><TD></TD><TD></TD></TR> 2135 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#IDX4">unused attribute</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC8">3.3 GNU C extensions</A></TD></TR> 2136 <TR><TD COLSPAN=3> <HR></TD></TR> 2137 <TR><TH><A NAME="cp_V"></A>V</TH><TD></TD><TD></TD></TR> 2138 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC33">value stack</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC33">8.7.3 Manipulating the value stack</A></TD></TR> 2139 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC32">value stack, introduction</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC32">8.7.2 The value stack</A></TD></TR> 2140 <TR><TD COLSPAN=3> <HR></TD></TR> 2141 <TR><TH><A NAME="cp_W"></A>W</TH><TD></TD><TD></TD></TR> 2142 <TR><TD></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">word directive</A></TD><TD valign=top><A HREF="tcc-doc.html#SEC14">4.4 Directives</A></TD></TR> 2143 <TR><TD COLSPAN=3> <HR></TD></TR> 2144 </TABLE><P></P><table><tr><th valign=top>Jump to: </th><td><A HREF="tcc-doc.html#cp__" style="text-decoration:none"><b>_</b></A> 2145 2146 <BR> 2147 <A HREF="tcc-doc.html#cp_A" style="text-decoration:none"><b>A</b></A> 2148 2149 <A HREF="tcc-doc.html#cp_B" style="text-decoration:none"><b>B</b></A> 2150 2151 <A HREF="tcc-doc.html#cp_C" style="text-decoration:none"><b>C</b></A> 2152 2153 <A HREF="tcc-doc.html#cp_D" style="text-decoration:none"><b>D</b></A> 2154 2155 <A HREF="tcc-doc.html#cp_E" style="text-decoration:none"><b>E</b></A> 2156 2157 <A HREF="tcc-doc.html#cp_F" style="text-decoration:none"><b>F</b></A> 2158 2159 <A HREF="tcc-doc.html#cp_G" style="text-decoration:none"><b>G</b></A> 2160 2161 <A HREF="tcc-doc.html#cp_I" style="text-decoration:none"><b>I</b></A> 2162 2163 <A HREF="tcc-doc.html#cp_J" style="text-decoration:none"><b>J</b></A> 2164 2165 <A HREF="tcc-doc.html#cp_L" style="text-decoration:none"><b>L</b></A> 2166 2167 <A HREF="tcc-doc.html#cp_M" style="text-decoration:none"><b>M</b></A> 2168 2169 <A HREF="tcc-doc.html#cp_O" style="text-decoration:none"><b>O</b></A> 2170 2171 <A HREF="tcc-doc.html#cp_P" style="text-decoration:none"><b>P</b></A> 2172 2173 <A HREF="tcc-doc.html#cp_Q" style="text-decoration:none"><b>Q</b></A> 2174 2175 <A HREF="tcc-doc.html#cp_R" style="text-decoration:none"><b>R</b></A> 2176 2177 <A HREF="tcc-doc.html#cp_S" style="text-decoration:none"><b>S</b></A> 2178 2179 <A HREF="tcc-doc.html#cp_T" style="text-decoration:none"><b>T</b></A> 2180 2181 <A HREF="tcc-doc.html#cp_U" style="text-decoration:none"><b>U</b></A> 2182 2183 <A HREF="tcc-doc.html#cp_V" style="text-decoration:none"><b>V</b></A> 2184 2185 <A HREF="tcc-doc.html#cp_W" style="text-decoration:none"><b>W</b></A> 2186 2187 </td></tr></table><br><P> 2188 2189 <HR SIZE="6"> 2190 <A NAME="SEC_Contents"></A> 2191 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 2192 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 2193 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 2194 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 2195 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 2196 </TR></TABLE> 2197 <H1>Table of Contents</H1> 2198 <UL> 2199 <A NAME="TOC1" HREF="tcc-doc.html#SEC1">1. Introduction</A> 2200 <BR> 2201 <A NAME="TOC2" HREF="tcc-doc.html#SEC2">2. Command line invocation</A> 2202 <BR> 2203 <UL> 2204 <A NAME="TOC3" HREF="tcc-doc.html#SEC3">2.1 Quick start</A> 2205 <BR> 2206 <A NAME="TOC4" HREF="tcc-doc.html#SEC4">2.2 Option summary</A> 2207 <BR> 2208 </UL> 2209 <A NAME="TOC5" HREF="tcc-doc.html#SEC5">3. C language support</A> 2210 <BR> 2211 <UL> 2212 <A NAME="TOC6" HREF="tcc-doc.html#SEC6">3.1 ANSI C</A> 2213 <BR> 2214 <A NAME="TOC7" HREF="tcc-doc.html#SEC7">3.2 ISOC99 extensions</A> 2215 <BR> 2216 <A NAME="TOC8" HREF="tcc-doc.html#SEC8">3.3 GNU C extensions</A> 2217 <BR> 2218 <A NAME="TOC9" HREF="tcc-doc.html#SEC9">3.4 TinyCC extensions</A> 2219 <BR> 2220 </UL> 2221 <A NAME="TOC10" HREF="tcc-doc.html#SEC10">4. TinyCC Assembler</A> 2222 <BR> 2223 <UL> 2224 <A NAME="TOC11" HREF="tcc-doc.html#SEC11">4.1 Syntax</A> 2225 <BR> 2226 <A NAME="TOC12" HREF="tcc-doc.html#SEC12">4.2 Expressions</A> 2227 <BR> 2228 <A NAME="TOC13" HREF="tcc-doc.html#SEC13">4.3 Labels</A> 2229 <BR> 2230 <A NAME="TOC14" HREF="tcc-doc.html#SEC14">4.4 Directives</A> 2231 <BR> 2232 <A NAME="TOC15" HREF="tcc-doc.html#SEC15">4.5 X86 Assembler</A> 2233 <BR> 2234 </UL> 2235 <A NAME="TOC16" HREF="tcc-doc.html#SEC16">5. TinyCC Linker</A> 2236 <BR> 2237 <UL> 2238 <A NAME="TOC17" HREF="tcc-doc.html#SEC17">5.1 ELF file generation</A> 2239 <BR> 2240 <A NAME="TOC18" HREF="tcc-doc.html#SEC18">5.2 ELF file loader</A> 2241 <BR> 2242 <A NAME="TOC19" HREF="tcc-doc.html#SEC19">5.3 PE-i386 file generation</A> 2243 <BR> 2244 <A NAME="TOC20" HREF="tcc-doc.html#SEC20">5.4 GNU Linker Scripts</A> 2245 <BR> 2246 </UL> 2247 <A NAME="TOC21" HREF="tcc-doc.html#SEC21">6. TinyCC Memory and Bound checks</A> 2248 <BR> 2249 <A NAME="TOC22" HREF="tcc-doc.html#SEC22">7. The <CODE>libtcc</CODE> library</A> 2250 <BR> 2251 <A NAME="TOC23" HREF="tcc-doc.html#SEC23">8. Developer's guide</A> 2252 <BR> 2253 <UL> 2254 <A NAME="TOC24" HREF="tcc-doc.html#SEC24">8.1 File reading</A> 2255 <BR> 2256 <A NAME="TOC25" HREF="tcc-doc.html#SEC25">8.2 Lexer</A> 2257 <BR> 2258 <A NAME="TOC26" HREF="tcc-doc.html#SEC26">8.3 Parser</A> 2259 <BR> 2260 <A NAME="TOC27" HREF="tcc-doc.html#SEC27">8.4 Types</A> 2261 <BR> 2262 <A NAME="TOC28" HREF="tcc-doc.html#SEC28">8.5 Symbols</A> 2263 <BR> 2264 <A NAME="TOC29" HREF="tcc-doc.html#SEC29">8.6 Sections</A> 2265 <BR> 2266 <A NAME="TOC30" HREF="tcc-doc.html#SEC30">8.7 Code generation</A> 2267 <BR> 2268 <UL> 2269 <A NAME="TOC31" HREF="tcc-doc.html#SEC31">8.7.1 Introduction</A> 2270 <BR> 2271 <A NAME="TOC32" HREF="tcc-doc.html#SEC32">8.7.2 The value stack</A> 2272 <BR> 2273 <A NAME="TOC33" HREF="tcc-doc.html#SEC33">8.7.3 Manipulating the value stack</A> 2274 <BR> 2275 <A NAME="TOC34" HREF="tcc-doc.html#SEC34">8.7.4 CPU dependent code generation</A> 2276 <BR> 2277 </UL> 2278 <A NAME="TOC35" HREF="tcc-doc.html#SEC35">8.8 Optimizations done</A> 2279 <BR> 2280 </UL> 2281 <A NAME="TOC36" HREF="tcc-doc.html#SEC36">Concept Index</A> 2282 <BR> 2283 </UL> 2284 <HR SIZE=1> 2285 <A NAME="SEC_OVERVIEW"></A> 2286 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 2287 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 2288 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 2289 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 2290 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 2291 </TR></TABLE> 2292 <H1>Short Table of Contents</H1> 2293 <BLOCKQUOTE> 2294 <A NAME="TOC1" HREF="tcc-doc.html#SEC1">1. Introduction</A> 2295 <BR> 2296 <A NAME="TOC2" HREF="tcc-doc.html#SEC2">2. Command line invocation</A> 2297 <BR> 2298 <A NAME="TOC5" HREF="tcc-doc.html#SEC5">3. C language support</A> 2299 <BR> 2300 <A NAME="TOC10" HREF="tcc-doc.html#SEC10">4. TinyCC Assembler</A> 2301 <BR> 2302 <A NAME="TOC16" HREF="tcc-doc.html#SEC16">5. TinyCC Linker</A> 2303 <BR> 2304 <A NAME="TOC21" HREF="tcc-doc.html#SEC21">6. TinyCC Memory and Bound checks</A> 2305 <BR> 2306 <A NAME="TOC22" HREF="tcc-doc.html#SEC22">7. The <CODE>libtcc</CODE> library</A> 2307 <BR> 2308 <A NAME="TOC23" HREF="tcc-doc.html#SEC23">8. Developer's guide</A> 2309 <BR> 2310 <A NAME="TOC36" HREF="tcc-doc.html#SEC36">Concept Index</A> 2311 <BR> 2312 2313 </BLOCKQUOTE> 2314 <HR SIZE=1> 2315 <A NAME="SEC_About"></A> 2316 <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> 2317 <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Top">Top</A>]</TD> 2318 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_Contents">Contents</A>]</TD> 2319 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC36">Index</A>]</TD> 2320 <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="tcc-doc.html#SEC_About"> ? </A>]</TD> 2321 </TR></TABLE> 2322 <H1>About this document</H1> 2323 This document was generated on <I>December, 17 2017</I> 2324 using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html 2325 "><I>texi2html</I></A> 2326 <P></P> 2327 The buttons in the navigation panels have the following meaning: 2328 <P></P> 2329 <table border = "1"> 2330 <TR> 2331 <TH> Button </TH> 2332 <TH> Name </TH> 2333 <TH> Go to </TH> 2334 <TH> From 1.2.3 go to</TH> 2335 </TR> 2336 <TR> 2337 <TD ALIGN="CENTER"> 2338 [ < ] </TD> 2339 <TD ALIGN="CENTER"> 2340 Back 2341 </TD> 2342 <TD> 2343 previous section in reading order 2344 </TD> 2345 <TD> 2346 1.2.2 2347 </TD> 2348 </TR> 2349 <TR> 2350 <TD ALIGN="CENTER"> 2351 [ > ] </TD> 2352 <TD ALIGN="CENTER"> 2353 Forward 2354 </TD> 2355 <TD> 2356 next section in reading order 2357 </TD> 2358 <TD> 2359 1.2.4 2360 </TD> 2361 </TR> 2362 <TR> 2363 <TD ALIGN="CENTER"> 2364 [ << ] </TD> 2365 <TD ALIGN="CENTER"> 2366 FastBack 2367 </TD> 2368 <TD> 2369 previous or up-and-previous section 2370 </TD> 2371 <TD> 2372 1.1 2373 </TD> 2374 </TR> 2375 <TR> 2376 <TD ALIGN="CENTER"> 2377 [ Up ] </TD> 2378 <TD ALIGN="CENTER"> 2379 Up 2380 </TD> 2381 <TD> 2382 up section 2383 </TD> 2384 <TD> 2385 1.2 2386 </TD> 2387 </TR> 2388 <TR> 2389 <TD ALIGN="CENTER"> 2390 [ >> ] </TD> 2391 <TD ALIGN="CENTER"> 2392 FastForward 2393 </TD> 2394 <TD> 2395 next or up-and-next section 2396 </TD> 2397 <TD> 2398 1.3 2399 </TD> 2400 </TR> 2401 <TR> 2402 <TD ALIGN="CENTER"> 2403 [Top] </TD> 2404 <TD ALIGN="CENTER"> 2405 Top 2406 </TD> 2407 <TD> 2408 cover (top) of document 2409 </TD> 2410 <TD> 2411 2412 </TD> 2413 </TR> 2414 <TR> 2415 <TD ALIGN="CENTER"> 2416 [Contents] </TD> 2417 <TD ALIGN="CENTER"> 2418 Contents 2419 </TD> 2420 <TD> 2421 table of contents 2422 </TD> 2423 <TD> 2424 2425 </TD> 2426 </TR> 2427 <TR> 2428 <TD ALIGN="CENTER"> 2429 [Index] </TD> 2430 <TD ALIGN="CENTER"> 2431 Index 2432 </TD> 2433 <TD> 2434 concept index 2435 </TD> 2436 <TD> 2437 2438 </TD> 2439 </TR> 2440 <TR> 2441 <TD ALIGN="CENTER"> 2442 [ ? ] </TD> 2443 <TD ALIGN="CENTER"> 2444 About 2445 </TD> 2446 <TD> 2447 this page 2448 </TD> 2449 <TD> 2450 2451 </TD> 2452 </TR> 2453 </TABLE> 2454 <P></P> 2455 where the <STRONG> Example </STRONG> assumes that the current position 2456 is at <STRONG> Subsubsection One-Two-Three </STRONG> of a document of 2457 the following structure: 2458 <UL> 2459 <LI> 1. Section One </LI> 2460 <UL> 2461 <LI>1.1 Subsection One-One</LI> 2462 <UL> 2463 <LI> ... </LI> 2464 </UL> 2465 <LI>1.2 Subsection One-Two</LI> 2466 <UL> 2467 <LI>1.2.1 Subsubsection One-Two-One 2468 </LI><LI>1.2.2 Subsubsection One-Two-Two 2469 </LI><LI>1.2.3 Subsubsection One-Two-Three <STRONG> 2470 <== Current Position </STRONG> 2471 </LI><LI>1.2.4 Subsubsection One-Two-Four 2472 </LI></UL> 2473 <LI>1.3 Subsection One-Three</LI> 2474 <UL> 2475 <LI> ... </LI> 2476 </UL> 2477 <LI>1.4 Subsection One-Four</LI> 2478 </UL> 2479 </UL> 2480 2481 <HR SIZE=1> 2482 <BR> 2483 <FONT SIZE="-1"> 2484 This document was generated 2485 on <I>December, 17 2017</I> 2486 using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html 2487 "><I>texi2html</I></A> 2488 2489 </BODY> 2490 </HTML> -
EcnlProtoTool/trunk/tcc-0.9.27/tcc-doc.texi
r279 r331 177 177 @end example 178 178 179 @item -dumpversion180 Print only the compiler version and nothing else.181 182 179 @item -v 183 180 Display TCC version. 184 181 185 182 @item -vv 186 Show included files. As sole argument, print search dirs (as below).183 Show included files. As sole argument, print search dirs. -vvv shows tries too. 187 184 188 185 @item -bench 189 186 Display compilation statistics. 190 191 @item -print-search-dirs192 Print the configured installation directory and a list of library193 and include directories tcc will search.194 187 195 188 @end table … … 214 207 @item -Usym 215 208 Undefine preprocessor symbol @samp{sym}. 209 210 @item -E 211 Preprocess only, to stdout or file (with -o). 212 216 213 @end table 217 214 218 215 Compilation flags: 219 216 220 Note: each of the following warningoptions has a negative form beginning with217 Note: each of the following options has a negative form beginning with 221 218 @option{-fno-}. 222 219 … … 233 230 @item -fleading-underscore 234 231 Add a leading underscore at the beginning of each C symbol. 232 233 @item -fms-extensions 234 Allow a MS C compiler extensions to the language. Currently this 235 assumes a nested named structure declaration without an identifier 236 behaves like an unnamed one. 237 238 @item -fdollars-in-identifiers 239 Allow dollar signs in identifiers 235 240 236 241 @end table … … 277 282 Link your program with dynamic library libxxx.so or static library 278 283 libxxx.a. The library is searched in the paths specified by the 279 @option{-L} option .284 @option{-L} option and @env{LIBRARY_PATH} variable. 280 285 281 286 @item -Bdir … … 301 306 302 307 @item -Wl,-rpath=path 303 Put custom seatch path for dynamic libraries into executable. 308 Put custom search path for dynamic libraries into executable. 309 310 @item -Wl,--enable-new-dtags 311 When putting a custom search path for dynamic libraries into the executable, 312 create the new ELF dynamic tag DT_RUNPATH instead of the old legacy DT_RPATH. 304 313 305 314 @item -Wl,--oformat=fmt … … 323 332 Set DT_SYMBOLIC tag. 324 333 334 @item -Wl,-(no-)whole-archive 335 Turn on/off linking of all objects in archives. 336 325 337 @end table 326 338 … … 339 351 that the generated code is slower and bigger in this case. 340 352 341 Note: @option{-b} is only available on i386 for the moment.353 Note: @option{-b} is only available on i386 when using libtcc for the moment. 342 354 343 355 @item -bt N … … 356 368 Use @file{depfile} as output for -MD. 357 369 370 @item -print-search-dirs 371 Print the configured installation directory and a list of library 372 and include directories tcc will search. 373 374 @item -dumpversion 375 Print version. 376 377 @end table 378 379 Target specific options: 380 381 @table @option 382 @item -mms-bitfields 383 Use an algorithm for bitfield alignment consistent with MSVC. Default is 384 gcc's algorithm. 385 386 @item -mfloat-abi (ARM only) 387 Select the float ABI. Possible values: @code{softfp} and @code{hard} 388 389 @item -mno-sse 390 Do not use sse registers on x86_64 391 392 @item -m32, -m64 393 Pass command line to the i386/x86_64 cross compiler. 394 358 395 @end table 359 396 … … 362 399 @c man end 363 400 401 @c man begin ENVIRONMENT 402 Environment variables that affect how tcc operates. 403 404 @table @option 405 406 @item CPATH 407 @item C_INCLUDE_PATH 408 A colon-separated list of directories searched for include files, 409 directories given with @option{-I} are searched first. 410 411 @item LIBRARY_PATH 412 A colon-separated list of directories searched for libraries for the 413 @option{-l} option, directories given with @option{-L} are searched first. 414 415 @end table 416 417 @c man end 418 364 419 @ignore 365 420 … … 368 423 369 424 @c man begin SEEALSO 425 cpp(1), 370 426 gcc(1) 371 427 @c man end … … 389 445 390 446 TCC implements many features of the new C standard: ISO C99. Currently 391 missing items are: complex and imaginary numbers and variable length 392 arrays. 447 missing items are: complex and imaginary numbers. 393 448 394 449 Currently implemented ISOC99 features: 395 450 396 451 @itemize 452 453 @item variable length arrays. 397 454 398 455 @item 64 bit @code{long long} types are fully supported. … … 597 654 @itemize 598 655 599 @item @code{__TINYC__} is a predefined macro to @code{1} to 600 indicate that you use TCC. 656 @item @code{__TINYC__} is a predefined macro to indicate that you use TCC. 601 657 602 658 @item @code{#!} at the start of a line is ignored to allow scripting. … … 614 670 Since version 0.9.16, TinyCC integrates its own assembler. TinyCC 615 671 assembler supports a gas-like syntax (GNU assembler). You can 616 de sactivate assembler support if you want a smaller TinyCC executable672 deactivate assembler support if you want a smaller TinyCC executable 617 673 (the C compiler does not rely on the assembler). 618 674 … … 703 759 @cindex ascii directive 704 760 705 All directives are prece eded by a '.'. The following directives are761 All directives are preceded by a '.'. The following directives are 706 762 supported: 707 763 … … 922 978 @section Types 923 979 924 The types are stored in a single 'int' variable. It was cho osen in the980 The types are stored in a single 'int' variable. It was chosen in the 925 981 first stages of development when tcc was much simpler. Now, it may not 926 982 be the best solution. … … 949 1005 #define VT_CONSTANT 0x0800 /* const modifier */ 950 1006 #define VT_VOLATILE 0x1000 /* volatile modifier */ 951 #define VT_ SIGNED0x2000 /* signed type */1007 #define VT_DEFSIGN 0x2000 /* signed type */ 952 1008 953 1009 #define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */ … … 991 1047 992 1048 @code{Sym.v} contains the symbol name (remember 993 an iden fier is also a token, so a string is never necessary to store1049 an identifier is also a token, so a string is never necessary to store 994 1050 it). @code{Sym.t} gives the type of the symbol. @code{Sym.r} is usually 995 1051 the register in which the corresponding variable is stored. @code{Sym.c} is … … 1034 1090 @section Sections 1035 1091 1036 The generated code and data sare written in sections. The structure1092 The generated code and data are written in sections. The structure 1037 1093 @code{Section} contains all the necessary information for a given 1038 1094 section. @code{new_section()} creates a new section. ELF file semantics … … 1059 1115 @item stab_section 1060 1116 @itemx stabstr_section 1061 are used when debugging is active dto store debug information1117 are used when debugging is active to store debug information 1062 1118 1063 1119 @item symtab_section … … 1159 1215 1160 1216 @item VT_LLOCAL 1161 is a saved lvalue on the stack. @code{VT_LLOCAL} should be eliminated 1162 ASAP because its semantics are rather complicated. 1217 is a saved lvalue on the stack. @code{VT_LVAL} must also be set with 1218 @code{VT_LLOCAL}. @code{VT_LLOCAL} can arise when a @code{VT_LVAL} in 1219 a register has to be saved to the stack, or it can come from an 1220 architecture-specific calling convention. 1163 1221 1164 1222 @item VT_MUSTCAST … … 1219 1277 @item gen_opi(op) 1220 1278 must generate the binary integer operation @var{op} on the two top 1221 entries of the stack which are guarante d to contain integer types.1279 entries of the stack which are guaranteed to contain integer types. 1222 1280 1223 1281 The result value should be put on the stack. … … 1225 1283 @item gen_opf(op) 1226 1284 same as @code{gen_opi()} for floating point operations. The two top 1227 entries of the stack are guarante d to contain floating point values of1285 entries of the stack are guaranteed to contain floating point values of 1228 1286 same types. 1229 1287 -
EcnlProtoTool/trunk/tcc-0.9.27/tcc.1
r279 r331 1 .\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 2 .\" 3 .\" Standard preamble: 4 .\" ======================================================================== 5 .de Sh \" Subsection heading 6 .br 7 .if t .Sp 8 .ne 5 9 .PP 10 \fB\\$1\fR 11 .PP 12 .. 13 .de Sp \" Vertical space (when we can't use .PP) 14 .if t .sp .5v 15 .if n .sp 16 .. 17 .de Vb \" Begin verbatim text 18 .ft CW 19 .nf 20 .ne \\$1 21 .. 22 .de Ve \" End verbatim text 23 .ft R 24 .fi 25 .. 26 .\" Set up some character translations and predefined strings. \*(-- will 27 .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left 28 .\" double quote, and \*(R" will give a right double quote. | will give a 29 .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to 30 .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' 31 .\" expand to `' in nroff, nothing in troff, for use with C<>. 32 .tr \(*W-|\(bv\*(Tr 33 .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' 34 .ie n \{\ 35 . ds -- \(*W- 36 . ds PI pi 37 . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch 38 . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch 39 . ds L" "" 40 . ds R" "" 41 . ds C` "" 42 . ds C' "" 43 'br\} 44 .el\{\ 45 . ds -- \|\(em\| 46 . ds PI \(*p 47 . ds L" `` 48 . ds R" '' 49 'br\} 50 .\" 51 .\" If the F register is turned on, we'll generate index entries on stderr for 52 .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index 53 .\" entries marked with X<> in POD. Of course, you'll have to process the 54 .\" output yourself in some meaningful fashion. 55 .if \nF \{\ 56 . de IX 57 . tm Index:\\$1\t\\n%\t"\\$2" 58 .. 59 . nr % 0 60 . rr F 61 .\} 62 .\" 63 .\" For nroff, turn off justification. Always turn off hyphenation; it makes 64 .\" way too many mistakes in technical documents. 65 .hy 0 66 .if n .na 67 .\" 68 .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). 69 .\" Fear. Run. Save yourself. No user-serviceable parts. 70 . \" fudge factors for nroff and troff 71 .if n \{\ 72 . ds #H 0 73 . ds #V .8m 74 . ds #F .3m 75 . ds #[ \f1 76 . ds #] \fP 77 .\} 78 .if t \{\ 79 . ds #H ((1u-(\\\\n(.fu%2u))*.13m) 80 . ds #V .6m 81 . ds #F 0 82 . ds #[ \& 83 . ds #] \& 84 .\} 85 . \" simple accents for nroff and troff 86 .if n \{\ 87 . ds ' \& 88 . ds ` \& 89 . ds ^ \& 90 . ds , \& 91 . ds ~ ~ 92 . ds / 93 .\} 94 .if t \{\ 95 . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" 96 . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' 97 . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' 98 . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' 99 . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' 100 . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' 101 .\} 102 . \" troff and (daisy-wheel) nroff accents 103 .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' 104 .ds 8 \h'\*(#H'\(*b\h'-\*(#H' 105 .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] 106 .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' 107 .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' 108 .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] 109 .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] 110 .ds ae a\h'-(\w'a'u*4/10)'e 111 .ds Ae A\h'-(\w'A'u*4/10)'E 112 . \" corrections for vroff 113 .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' 114 .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' 115 . \" for low resolution devices (crt and lpr) 116 .if \n(.H>23 .if \n(.V>19 \ 117 \{\ 118 . ds : e 119 . ds 8 ss 120 . ds o a 121 . ds d- d\h'-1'\(ga 122 . ds D- D\h'-1'\(hy 123 . ds th \o'bp' 124 . ds Th \o'LP' 125 . ds ae ae 126 . ds Ae AE 127 .\} 128 .rm #[ #] #H #V #F C 129 .\" ======================================================================== 130 .\" 131 .IX Title "TCC 1" 132 .TH TCC 1 "2018-01-07" "0.9.27" "Tiny C Compiler" 133 .SH "NAME" 134 tcc \- Tiny C Compiler 135 .SH "SYNOPSIS" 136 .IX Header "SYNOPSIS" 137 usage: tcc [options] [\fIinfile1\fR \fIinfile2\fR...] [\fB\-run\fR \fIinfile\fR \fIargs\fR...] 138 .SH "DESCRIPTION" 139 .IX Header "DESCRIPTION" 140 \&\s-1TCC\s0 options are a very much like gcc options. The main difference is that \s-1TCC\s0 141 can also execute directly the resulting program and give it runtime 142 arguments. 143 .PP 144 Here are some examples to understand the logic: 145 .ie n .IP """\f(CBtcc \-run a.c\f(CW""" 4 146 .el .IP "\f(CW\f(CBtcc \-run a.c\f(CW\fR" 4 147 .IX Item "tcc -run a.c" 148 Compile \fIa.c\fR and execute it directly 149 .ie n .IP """\f(CBtcc \-run a.c arg1\f(CW""" 4 150 .el .IP "\f(CW\f(CBtcc \-run a.c arg1\f(CW\fR" 4 151 .IX Item "tcc -run a.c arg1" 152 Compile a.c and execute it directly. arg1 is given as first argument to 153 the \f(CW\*(C`main()\*(C'\fR of a.c. 154 .ie n .IP """\f(CBtcc a.c \-run b.c arg1\f(CW""" 4 155 .el .IP "\f(CW\f(CBtcc a.c \-run b.c arg1\f(CW\fR" 4 156 .IX Item "tcc a.c -run b.c arg1" 157 Compile \fIa.c\fR and \fIb.c\fR, link them together and execute them. arg1 is given 158 as first argument to the \f(CW\*(C`main()\*(C'\fR of the resulting program. 159 .ie n .IP """\f(CBtcc \-o myprog a.c b.c\f(CW""" 4 160 .el .IP "\f(CW\f(CBtcc \-o myprog a.c b.c\f(CW\fR" 4 161 .IX Item "tcc -o myprog a.c b.c" 162 Compile \fIa.c\fR and \fIb.c\fR, link them and generate the executable \fImyprog\fR. 163 .ie n .IP """\f(CBtcc \-o myprog a.o b.o\f(CW""" 4 164 .el .IP "\f(CW\f(CBtcc \-o myprog a.o b.o\f(CW\fR" 4 165 .IX Item "tcc -o myprog a.o b.o" 166 link \fIa.o\fR and \fIb.o\fR together and generate the executable \fImyprog\fR. 167 .ie n .IP """\f(CBtcc \-c a.c\f(CW""" 4 168 .el .IP "\f(CW\f(CBtcc \-c a.c\f(CW\fR" 4 169 .IX Item "tcc -c a.c" 170 Compile \fIa.c\fR and generate object file \fIa.o\fR. 171 .ie n .IP """\f(CBtcc \-c asmfile.S\f(CW""" 4 172 .el .IP "\f(CW\f(CBtcc \-c asmfile.S\f(CW\fR" 4 173 .IX Item "tcc -c asmfile.S" 174 Preprocess with C preprocess and assemble \fIasmfile.S\fR and generate 175 object file \fIasmfile.o\fR. 176 .ie n .IP """\f(CBtcc \-c asmfile.s\f(CW""" 4 177 .el .IP "\f(CW\f(CBtcc \-c asmfile.s\f(CW\fR" 4 178 .IX Item "tcc -c asmfile.s" 179 Assemble (but not preprocess) \fIasmfile.s\fR and generate object file 180 \&\fIasmfile.o\fR. 181 .ie n .IP """\f(CBtcc \-r \-o ab.o a.c b.c\f(CW""" 4 182 .el .IP "\f(CW\f(CBtcc \-r \-o ab.o a.c b.c\f(CW\fR" 4 183 .IX Item "tcc -r -o ab.o a.c b.c" 184 Compile \fIa.c\fR and \fIb.c\fR, link them together and generate the object file \fIab.o\fR. 185 .PP 186 Scripting: 187 .PP 188 \&\s-1TCC\s0 can be invoked from \fIscripts\fR, just as shell scripts. You just 189 need to add \f(CW\*(C`#!/usr/local/bin/tcc \-run\*(C'\fR at the start of your C source: 190 .PP 191 .Vb 2 192 \& #!/usr/local/bin/tcc -run 193 \& #include <stdio.h> 194 .Ve 195 .PP 196 .Vb 5 197 \& int main() 198 \& { 199 \& printf("Hello World\en"); 200 \& return 0; 201 \& } 202 .Ve 203 .PP 204 \&\s-1TCC\s0 can read C source code from \fIstandard input\fR when \fB\-\fR is used in 205 place of \fBinfile\fR. Example: 206 .PP 207 .Vb 1 208 \& echo 'main(){puts("hello");}' | tcc -run - 209 .Ve 210 .SH "OPTIONS" 211 .IX Header "OPTIONS" 212 .IP "\fB\-c\fR" 4 213 .IX Item "-c" 214 Generate an object file. 215 .IP "\fB\-o outfile\fR" 4 216 .IX Item "-o outfile" 217 Put object file, executable, or dll into output file \fIoutfile\fR. 218 .IP "\fB\-run source [args...]\fR" 4 219 .IX Item "-run source [args...]" 220 Compile file \fIsource\fR and run it with the command line arguments 221 \&\fIargs\fR. In order to be able to give more than one argument to a 222 script, several \s-1TCC\s0 options can be given \fIafter\fR the 223 \&\fB\-run\fR option, separated by spaces: 224 .Sp 225 .Vb 1 226 \& tcc "-run -L/usr/X11R6/lib -lX11" ex4.c 227 .Ve 228 .Sp 229 In a script, it gives the following header: 230 .Sp 231 .Vb 1 232 \& #!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11 233 .Ve 234 .IP "\fB\-v\fR" 4 235 .IX Item "-v" 236 Display \s-1TCC\s0 version. 237 .IP "\fB\-vv\fR" 4 238 .IX Item "-vv" 239 Show included files. As sole argument, print search dirs. \-vvv shows tries too. 240 .IP "\fB\-bench\fR" 4 241 .IX Item "-bench" 242 Display compilation statistics. 243 .PP 244 Preprocessor options: 245 .IP "\fB\-Idir\fR" 4 246 .IX Item "-Idir" 247 Specify an additional include path. Include paths are searched in the 248 order they are specified. 249 .Sp 250 System include paths are always searched after. The default system 251 include paths are: \fI/usr/local/include\fR, \fI/usr/include\fR 252 and \fIPREFIX/lib/tcc/include\fR. (\fI\s-1PREFIX\s0\fR is usually 253 \&\fI/usr\fR or \fI/usr/local\fR). 254 .IP "\fB\-Dsym[=val]\fR" 4 255 .IX Item "-Dsym[=val]" 256 Define preprocessor symbol \fBsym\fR to 257 val. If val is not present, its value is \fB1\fR. Function-like macros can 258 also be defined: \fB\-DF(a)=a+1\fR 259 .IP "\fB\-Usym\fR" 4 260 .IX Item "-Usym" 261 Undefine preprocessor symbol \fBsym\fR. 262 .IP "\fB\-E\fR" 4 263 .IX Item "-E" 264 Preprocess only, to stdout or file (with \-o). 265 .PP 266 Compilation flags: 267 .PP 268 Note: each of the following options has a negative form beginning with 269 \&\fB\-fno\-\fR. 270 .IP "\fB\-funsigned\-char\fR" 4 271 .IX Item "-funsigned-char" 272 Let the \f(CW\*(C`char\*(C'\fR type be unsigned. 273 .IP "\fB\-fsigned\-char\fR" 4 274 .IX Item "-fsigned-char" 275 Let the \f(CW\*(C`char\*(C'\fR type be signed. 276 .IP "\fB\-fno\-common\fR" 4 277 .IX Item "-fno-common" 278 Do not generate common symbols for uninitialized data. 279 .IP "\fB\-fleading\-underscore\fR" 4 280 .IX Item "-fleading-underscore" 281 Add a leading underscore at the beginning of each C symbol. 282 .IP "\fB\-fms\-extensions\fR" 4 283 .IX Item "-fms-extensions" 284 Allow a \s-1MS\s0 C compiler extensions to the language. Currently this 285 assumes a nested named structure declaration without an identifier 286 behaves like an unnamed one. 287 .IP "\fB\-fdollars\-in\-identifiers\fR" 4 288 .IX Item "-fdollars-in-identifiers" 289 Allow dollar signs in identifiers 290 .PP 291 Warning options: 292 .IP "\fB\-w\fR" 4 293 .IX Item "-w" 294 Disable all warnings. 295 .PP 296 Note: each of the following warning options has a negative form beginning with 297 \&\fB\-Wno\-\fR. 298 .IP "\fB\-Wimplicit\-function\-declaration\fR" 4 299 .IX Item "-Wimplicit-function-declaration" 300 Warn about implicit function declaration. 301 .IP "\fB\-Wunsupported\fR" 4 302 .IX Item "-Wunsupported" 303 Warn about unsupported \s-1GCC\s0 features that are ignored by \s-1TCC\s0. 304 .IP "\fB\-Wwrite\-strings\fR" 4 305 .IX Item "-Wwrite-strings" 306 Make string constants be of type \f(CW\*(C`const char *\*(C'\fR instead of \f(CW\*(C`char 307 *\*(C'\fR. 308 .IP "\fB\-Werror\fR" 4 309 .IX Item "-Werror" 310 Abort compilation if warnings are issued. 311 .IP "\fB\-Wall\fR" 4 312 .IX Item "-Wall" 313 Activate all warnings, except \fB\-Werror\fR, \fB\-Wunusupported\fR and 314 \&\fB\-Wwrite\-strings\fR. 315 .PP 316 Linker options: 317 .IP "\fB\-Ldir\fR" 4 318 .IX Item "-Ldir" 319 Specify an additional static library path for the \fB\-l\fR option. The 320 default library paths are \fI/usr/local/lib\fR, \fI/usr/lib\fR and \fI/lib\fR. 321 .IP "\fB\-lxxx\fR" 4 322 .IX Item "-lxxx" 323 Link your program with dynamic library libxxx.so or static library 324 libxxx.a. The library is searched in the paths specified by the 325 \&\fB\-L\fR option and \fB\s-1LIBRARY_PATH\s0\fR variable. 326 .IP "\fB\-Bdir\fR" 4 327 .IX Item "-Bdir" 328 Set the path where the tcc internal libraries (and include files) can be 329 found (default is \fIPREFIX/lib/tcc\fR). 330 .IP "\fB\-shared\fR" 4 331 .IX Item "-shared" 332 Generate a shared library instead of an executable. 333 .IP "\fB\-soname name\fR" 4 334 .IX Item "-soname name" 335 set name for shared library to be used at runtime 336 .IP "\fB\-static\fR" 4 337 .IX Item "-static" 338 Generate a statically linked executable (default is a shared linked 339 executable). 340 .IP "\fB\-rdynamic\fR" 4 341 .IX Item "-rdynamic" 342 Export global symbols to the dynamic linker. It is useful when a library 343 opened with \f(CW\*(C`dlopen()\*(C'\fR needs to access executable symbols. 344 .IP "\fB\-r\fR" 4 345 .IX Item "-r" 346 Generate an object file combining all input files. 347 .IP "\fB\-Wl,\-rpath=path\fR" 4 348 .IX Item "-Wl,-rpath=path" 349 Put custom search path for dynamic libraries into executable. 350 .IP "\fB\-Wl,\-\-enable\-new\-dtags\fR" 4 351 .IX Item "-Wl,--enable-new-dtags" 352 When putting a custom search path for dynamic libraries into the executable, 353 create the new \s-1ELF\s0 dynamic tag \s-1DT_RUNPATH\s0 instead of the old legacy \s-1DT_RPATH\s0. 354 .IP "\fB\-Wl,\-\-oformat=fmt\fR" 4 355 .IX Item "-Wl,--oformat=fmt" 356 Use \fIfmt\fR as output format. The supported output formats are: 357 .RS 4 358 .ie n .IP """elf32\-i386""" 4 359 .el .IP "\f(CWelf32\-i386\fR" 4 360 .IX Item "elf32-i386" 361 \&\s-1ELF\s0 output format (default) 362 .ie n .IP """binary""" 4 363 .el .IP "\f(CWbinary\fR" 4 364 .IX Item "binary" 365 Binary image (only for executable output) 366 .ie n .IP """coff""" 4 367 .el .IP "\f(CWcoff\fR" 4 368 .IX Item "coff" 369 \&\s-1COFF\s0 output format (only for executable output for TMS320C67xx target) 370 .RE 371 .RS 4 372 .RE 373 .IP "\fB\-Wl,\-subsystem=console/gui/wince/...\fR" 4 374 .IX Item "-Wl,-subsystem=console/gui/wince/..." 375 Set type for \s-1PE\s0 (Windows) executables. 376 .IP "\fB\-Wl,\-[Ttext=# | section\-alignment=# | file\-alignment=# | image\-base=# | stack=#]\fR" 4 377 .IX Item "-Wl,-[Ttext=# | section-alignment=# | file-alignment=# | image-base=# | stack=#]" 378 Modify executable layout. 379 .IP "\fB\-Wl,\-Bsymbolic\fR" 4 380 .IX Item "-Wl,-Bsymbolic" 381 Set \s-1DT_SYMBOLIC\s0 tag. 382 .IP "\fB\-Wl,\-(no\-)whole\-archive\fR" 4 383 .IX Item "-Wl,-(no-)whole-archive" 384 Turn on/off linking of all objects in archives. 385 .PP 386 Debugger options: 387 .IP "\fB\-g\fR" 4 388 .IX Item "-g" 389 Generate run time debug information so that you get clear run time 390 error messages: \f(CW\*(C` test.c:68: in function 'test5()': dereferencing 391 invalid pointer\*(C'\fR instead of the laconic \f(CW\*(C`Segmentation 392 fault\*(C'\fR. 393 .IP "\fB\-b\fR" 4 394 .IX Item "-b" 395 Generate additional support code to check 396 memory allocations and array/pointer bounds. \fB\-g\fR is implied. Note 397 that the generated code is slower and bigger in this case. 398 .Sp 399 Note: \fB\-b\fR is only available on i386 when using libtcc for the moment. 400 .IP "\fB\-bt N\fR" 4 401 .IX Item "-bt N" 402 Display N callers in stack traces. This is useful with \fB\-g\fR or 403 \&\fB\-b\fR. 404 .PP 405 Misc options: 406 .IP "\fB\-MD\fR" 4 407 .IX Item "-MD" 408 Generate makefile fragment with dependencies. 409 .IP "\fB\-MF depfile\fR" 4 410 .IX Item "-MF depfile" 411 Use \fIdepfile\fR as output for \-MD. 412 .IP "\fB\-print\-search\-dirs\fR" 4 413 .IX Item "-print-search-dirs" 414 Print the configured installation directory and a list of library 415 and include directories tcc will search. 416 .IP "\fB\-dumpversion\fR" 4 417 .IX Item "-dumpversion" 418 Print version. 419 .PP 420 Target specific options: 421 .IP "\fB\-mms\-bitfields\fR" 4 422 .IX Item "-mms-bitfields" 423 Use an algorithm for bitfield alignment consistent with \s-1MSVC\s0. Default is 424 gcc's algorithm. 425 .IP "\fB\-mfloat\-abi (\s-1ARM\s0 only)\fR" 4 426 .IX Item "-mfloat-abi (ARM only)" 427 Select the float \s-1ABI\s0. Possible values: \f(CW\*(C`softfp\*(C'\fR and \f(CW\*(C`hard\*(C'\fR 428 .IP "\fB\-mno\-sse\fR" 4 429 .IX Item "-mno-sse" 430 Do not use sse registers on x86_64 431 .IP "\fB\-m32, \-m64\fR" 4 432 .IX Item "-m32, -m64" 433 Pass command line to the i386/x86_64 cross compiler. 434 .PP 435 Note: \s-1GCC\s0 options \fB\-Ox\fR, \fB\-fx\fR and \fB\-mx\fR are 436 ignored. 437 .SH "ENVIRONMENT" 438 .IX Header "ENVIRONMENT" 439 Environment variables that affect how tcc operates. 440 .IP "\fB\s-1CPATH\s0\fR" 4 441 .IX Item "CPATH" 442 .PD 0 443 .IP "\fBC_INCLUDE_PATH\fR" 4 444 .IX Item "C_INCLUDE_PATH" 445 .PD 446 A colon-separated list of directories searched for include files, 447 directories given with \fB\-I\fR are searched first. 448 .IP "\fB\s-1LIBRARY_PATH\s0\fR" 4 449 .IX Item "LIBRARY_PATH" 450 A colon-separated list of directories searched for libraries for the 451 \&\fB\-l\fR option, directories given with \fB\-L\fR are searched first. 452 .SH "SEE ALSO" 453 .IX Header "SEE ALSO" 454 \&\fIcpp\fR\|(1), 455 \&\fIgcc\fR\|(1) 456 .SH "AUTHOR" 457 .IX Header "AUTHOR" 458 Fabrice Bellard -
EcnlProtoTool/trunk/tcc-0.9.27/tcc.c
r321 r331 19 19 */ 20 20 21 #ifdef ONE_SOURCE 22 #include "libtcc.c" 21 #include "tcc.h" 22 #if ONE_SOURCE 23 # include "libtcc.c" 24 #endif 25 #include "tcctools.c" 26 27 static const char help[] = 28 "Tiny C Compiler "TCC_VERSION" - Copyright (C) 2001-2006 Fabrice Bellard\n" 29 "Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n" 30 " tcc [options...] -run infile [arguments...]\n" 31 "General options:\n" 32 " -c compile only - generate an object file\n" 33 " -o outfile set output filename\n" 34 " -run run compiled source\n" 35 " -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n" 36 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n" 37 " -w disable all warnings\n" 38 " -v -vv show version, show search paths or loaded files\n" 39 " -h -hh show this, show more help\n" 40 " -bench show compilation statistics\n" 41 " - use stdin pipe as infile\n" 42 " @listfile read arguments from listfile\n" 43 "Preprocessor options:\n" 44 " -Idir add include path 'dir'\n" 45 " -Dsym[=val] define 'sym' with value 'val'\n" 46 " -Usym undefine 'sym'\n" 47 " -E preprocess only\n" 48 "Linker options:\n" 49 " -Ldir add library path 'dir'\n" 50 " -llib link with dynamic or static library 'lib'\n" 51 " -r generate (relocatable) object file\n" 52 " -shared generate a shared library/dll\n" 53 " -rdynamic export all global symbols to dynamic linker\n" 54 " -soname set name for shared library to be used at runtime\n" 55 " -Wl,-opt[=val] set linker option (see tcc -hh)\n" 56 "Debugger options:\n" 57 " -g generate runtime debug info\n" 58 #ifdef CONFIG_TCC_BCHECK 59 " -b compile with built-in memory and bounds checker (implies -g)\n" 60 #endif 61 #ifdef CONFIG_TCC_BACKTRACE 62 " -bt N show N callers in stack traces\n" 63 #endif 64 "Misc. options:\n" 65 " -x[c|a|n] specify type of the next infile\n" 66 " -nostdinc do not use standard system include paths\n" 67 " -nostdlib do not link with standard crt and libraries\n" 68 " -Bdir set tcc's private include/library dir\n" 69 " -MD generate dependency file for make\n" 70 " -MF file specify dependency file name\n" 71 " -m32/64 defer to i386/x86_64 cross compiler\n" 72 "Tools:\n" 73 " create library : tcc -ar [rcsv] lib.a files\n" 74 #ifdef TCC_TARGET_PE 75 " create def file : tcc -impdef lib.dll [-v] [-o lib.def]\n" 76 #endif 77 ; 78 79 static const char help2[] = 80 "Tiny C Compiler "TCC_VERSION" - More Options\n" 81 "Special options:\n" 82 " -P -P1 with -E: no/alternative #line output\n" 83 " -dD -dM with -E: output #define directives\n" 84 " -pthread same as -D_REENTRANT and -lpthread\n" 85 " -On same as -D__OPTIMIZE__ for n > 0\n" 86 " -Wp,-opt same as -opt\n" 87 " -include file include 'file' above each input file\n" 88 " -isystem dir add 'dir' to system include path\n" 89 " -static link to static libraries (not recommended)\n" 90 " -dumpversion print version\n" 91 " -print-search-dirs print search paths\n" 92 " -dt with -run/-E: auto-define 'test_...' macros\n" 93 "Ignored options:\n" 94 " --param -pedantic -pipe -s -std -traditional\n" 95 "-W... warnings:\n" 96 " all turn on some (*) warnings\n" 97 " error stop after first warning\n" 98 " unsupported warn about ignored options, pragmas, etc.\n" 99 " write-strings strings are const\n" 100 " implicit-function-declaration warn for missing prototype (*)\n" 101 "-f[no-]... flags:\n" 102 " unsigned-char default char is unsigned\n" 103 " signed-char default char is signed\n" 104 " common use common section instead of bss\n" 105 " leading-underscore decorate extern symbols\n" 106 " ms-extensions allow anonymous struct in struct\n" 107 " dollars-in-identifiers allow '$' in C symbols\n" 108 "-m... target specific options:\n" 109 " ms-bitfields use MSVC bitfield layout\n" 110 #ifdef TCC_TARGET_ARM 111 " float-abi hard/softfp on arm\n" 112 #endif 113 #ifdef TCC_TARGET_X86_64 114 " no-sse disable floats on x86_64\n" 115 #endif 116 "-Wl,... linker options:\n" 117 " -nostdlib do not link with standard crt/libs\n" 118 " -[no-]whole-archive load lib(s) fully/only as needed\n" 119 " -export-all-symbols same as -rdynamic\n" 120 " -image-base= -Ttext= set base address of executable\n" 121 " -section-alignment= set section alignment in executable\n" 122 #ifdef TCC_TARGET_PE 123 " -file-alignment= set PE file alignment\n" 124 " -stack= set PE stack reserve\n" 125 " -large-address-aware set related PE option\n" 126 " -subsystem=[console/windows] set PE subsystem\n" 127 " -oformat=[pe-* binary] set executable output format\n" 128 "Predefined macros:\n" 129 " tcc -E -dM - < nul\n" 23 130 #else 24 #include "tcc.h" 25 #endif 26 27 static void help(void) 28 { 29 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n" 30 "Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n" 31 " tcc [options...] -run infile [arguments...]\n" 32 "General options:\n" 33 " -c compile only - generate an object file\n" 34 " -o outfile set output filename\n" 35 " -run run compiled source\n" 36 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n" 37 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n" 38 " -w disable all warnings\n" 39 " -v show version\n" 40 " -vv show included files (as sole argument: show search paths)\n" 41 " -dumpversion\n" 42 " -bench show compilation statistics\n" 43 "Preprocessor options:\n" 44 " -E preprocess only\n" 45 " -Idir add include path 'dir'\n" 46 " -Dsym[=val] define 'sym' with value 'val'\n" 47 " -Usym undefine 'sym'\n" 48 "Linker options:\n" 49 " -Ldir add library path 'dir'\n" 50 " -llib link with dynamic or static library 'lib'\n" 51 " -pthread link with -lpthread and -D_REENTRANT (POSIX Linux)\n" 52 " -r generate (relocatable) object file\n" 53 " -rdynamic export all global symbols to dynamic linker\n" 54 " -shared generate a shared library\n" 55 " -soname set name for shared library to be used at runtime\n" 56 " -static static linking\n" 57 " -Wl,-opt[=val] set linker option (see manual)\n" 58 "Debugger options:\n" 59 " -g generate runtime debug info\n" 60 #ifdef CONFIG_TCC_BCHECK 61 " -b compile with built-in memory and bounds checker (implies -g)\n" 62 #endif 63 #ifdef CONFIG_TCC_BACKTRACE 64 " -bt N show N callers in stack traces\n" 65 #endif 66 "Misc options:\n" 67 " -nostdinc do not use standard system include paths\n" 68 " -nostdlib do not link with standard crt and libraries\n" 69 " -Bdir use 'dir' as tcc internal library and include path\n" 70 " -MD generate target dependencies for make\n" 71 " -MF depfile put generated dependencies here\n" 72 ); 73 } 74 75 /* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */ 76 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 77 #ifdef _WIN32 78 #include <process.h> 79 static int execvp_win32(const char *prog, char **argv) 80 { 81 int ret = spawnvp(P_NOWAIT, prog, (char const*const*)argv); 82 if (-1 == ret) 83 return ret; 84 cwait(&ret, ret, WAIT_CHILD); 85 exit(ret); 86 } 87 #define execvp execvp_win32 88 #endif 89 static void exec_other_tcc(TCCState *s, char **argv, const char *optarg) 90 { 91 char child_path[4096], *child_name; const char *target; 92 switch (atoi(optarg)) { 131 " -rpath= set dynamic library search path\n" 132 " -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n" 133 " -soname= set DT_SONAME elf tag\n" 134 " -Bsymbolic set DT_SYMBOLIC elf tag\n" 135 " -oformat=[elf32/64-* binary] set executable output format\n" 136 " -init= -fini= -as-needed -O (ignored)\n" 137 "Predefined macros:\n" 138 " tcc -E -dM - < /dev/null\n" 139 #endif 140 "See also the manual for more details.\n" 141 ; 142 143 static const char version[] = 144 "tcc version "TCC_VERSION" (" 93 145 #ifdef TCC_TARGET_I386 94 case 32: break; 95 case 64: target = "x86_64"; 146 "i386" 147 #elif defined TCC_TARGET_X86_64 148 "x86_64" 149 #elif defined TCC_TARGET_C67 150 "C67" 151 #elif defined TCC_TARGET_ARM 152 "ARM" 153 #elif defined TCC_TARGET_ARM64 154 "AArch64" 155 #endif 156 #ifdef TCC_ARM_HARDFLOAT 157 " Hard Float" 158 #endif 159 #ifdef TCC_TARGET_PE 160 " Windows" 161 #elif defined(TCC_TARGET_MACHO) 162 " Darwin" 163 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 164 " FreeBSD" 96 165 #else 97 case 64: break; 98 case 32: target = "i386"; 99 #endif 100 pstrcpy(child_path, sizeof child_path - 40, argv[0]); 101 child_name = tcc_basename(child_path); 102 strcpy(child_name, target); 103 #ifdef TCC_TARGET_PE 104 strcat(child_name, "-win32"); 105 #endif 106 strcat(child_name, "-tcc"); 107 if (strcmp(argv[0], child_path)) { 108 if (s->verbose > 0) 109 printf("tcc: using '%s'\n", child_name), fflush(stdout); 110 execvp(argv[0] = child_path, argv); 111 } 112 tcc_error("'%s' not found", child_name); 113 case 0: /* ignore -march etc. */ 114 break; 115 default: 116 tcc_warning("unsupported option \"-m%s\"", optarg); 117 } 118 } 119 #else 120 #define exec_other_tcc(s, argv, optarg) 121 #endif 122 123 static void gen_makedeps(TCCState *s, const char *target, const char *filename) 124 { 125 FILE *depout; 126 char buf[1024], *ext; 166 " Linux" 167 #endif 168 ")\n" 169 ; 170 171 static void print_dirs(const char *msg, char **paths, int nb_paths) 172 { 127 173 int i; 128 129 if (!filename) { 130 /* compute filename automatically 131 * dir/file.o -> dir/file.d */ 132 pstrcpy(buf, sizeof(buf), target); 133 ext = tcc_fileextension(buf); 134 pstrcpy(ext, sizeof(buf) - (ext-buf), ".d"); 135 filename = buf; 136 } 137 138 if (s->verbose) 139 printf("<- %s\n", filename); 140 141 /* XXX return err codes instead of error() ? */ 142 depout = fopen(filename, "w"); 143 if (!depout) 144 tcc_error("could not open '%s'", filename); 145 146 fprintf(depout, "%s : \\\n", target); 147 for (i=0; i<s->nb_target_deps; ++i) 148 fprintf(depout, " %s \\\n", s->target_deps[i]); 149 fprintf(depout, "\n"); 150 fclose(depout); 174 printf("%s:\n%s", msg, nb_paths ? "" : " -\n"); 175 for(i = 0; i < nb_paths; i++) 176 printf(" %s\n", paths[i]); 177 } 178 179 static void print_search_dirs(TCCState *s) 180 { 181 printf("install: %s\n", s->tcc_lib_path); 182 /* print_dirs("programs", NULL, 0); */ 183 print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths); 184 print_dirs("libraries", s->library_paths, s->nb_library_paths); 185 printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path); 186 #ifndef TCC_TARGET_PE 187 print_dirs("crt", s->crt_paths, s->nb_crt_paths); 188 printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); 189 #endif 190 } 191 192 static void set_environment(TCCState *s) 193 { 194 char * path; 195 196 path = getenv("C_INCLUDE_PATH"); 197 if(path != NULL) { 198 tcc_add_sysinclude_path(s, path); 199 } 200 path = getenv("CPATH"); 201 if(path != NULL) { 202 tcc_add_include_path(s, path); 203 } 204 path = getenv("LIBRARY_PATH"); 205 if(path != NULL) { 206 tcc_add_library_path(s, path); 207 } 151 208 } 152 209 … … 159 216 if (first_file && strcmp(first_file, "-")) 160 217 name = tcc_basename(first_file); 161 pstrcpy(buf, sizeof(buf), name);218 snprintf(buf, sizeof(buf), "%s", name); 162 219 ext = tcc_fileextension(buf); 163 220 #ifdef TCC_TARGET_PE … … 169 226 else 170 227 #endif 171 if (( (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) || 172 (s->output_type == TCC_OUTPUT_PREPROCESS) ) 173 && *ext) 228 if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r && *ext) 174 229 strcpy(ext, ".o"); 175 230 else 176 231 strcpy(buf, "a.out"); 177 178 232 return tcc_strdup(buf); 179 233 } 180 234 181 static void print_paths(const char *msg, char **paths, int nb_paths) 182 { 183 int i; 184 printf("%s:\n%s", msg, nb_paths ? "" : " -\n"); 185 for(i = 0; i < nb_paths; i++) 186 printf(" %s\n", paths[i]); 187 } 188 189 static void display_info(TCCState *s, int what) 190 { 191 switch (what) { 192 case 0: 193 printf("tcc version %s (" 194 #ifdef TCC_TARGET_I386 195 "i386" 196 # ifdef TCC_TARGET_PE 197 " Win32" 198 # endif 199 #elif defined TCC_TARGET_X86_64 200 "x86-64" 201 # ifdef TCC_TARGET_PE 202 " Win64" 203 # endif 204 #elif defined TCC_TARGET_ARM 205 "ARM" 206 # ifdef TCC_ARM_HARDFLOAT 207 " Hard Float" 208 # endif 209 # ifdef TCC_TARGET_PE 210 " WinCE" 211 # endif 212 #endif 213 #ifndef TCC_TARGET_PE 214 # ifdef __linux 215 " Linux" 216 # endif 217 #endif 218 ")\n", TCC_VERSION); 219 break; 220 case 1: 221 printf("install: %s/\n", s->tcc_lib_path); 222 /* print_paths("programs", NULL, 0); */ 223 print_paths("crt", s->crt_paths, s->nb_crt_paths); 224 print_paths("libraries", s->library_paths, s->nb_library_paths); 225 print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths); 226 printf("elfinterp:\n %s\n", CONFIG_TCC_ELFINTERP); 227 break; 228 } 229 } 230 231 static int64_t getclock_us(void) 232 { 233 #if 0//def _WIN32 234 struct _timeb tb; 235 _ftime(&tb); 236 return (tb.time * 1000LL + tb.millitm) * 1000LL; 235 static unsigned getclock_ms(void) 236 { 237 #ifdef _WIN32 238 return GetTickCount(); 237 239 #else 238 240 struct timeval tv; 239 241 gettimeofday(&tv, NULL); 240 return tv.tv_sec * 1000000LL + tv.tv_usec;241 #endif 242 } 243 244 int tcc_main(int argc , char **argv)242 return tv.tv_sec*1000 + (tv.tv_usec+500)/1000; 243 #endif 244 } 245 246 int tcc_main(int argc0, char **argv0) 245 247 { 246 248 TCCState *s; 247 int ret, optind, i, bench; 248 int64_t start_time = 0; 249 const char *first_file = NULL; 250 249 int ret, opt, n = 0, t = 0; 250 unsigned start_time = 0; 251 const char *first_file; 252 int argc; char **argv; 253 FILE *ppfp = stdout; 254 255 redo: 256 argc = argc0, argv = argv0; 251 257 s = tcc_new(); 252 s->output_type = TCC_OUTPUT_EXE; 253 254 optind = tcc_parse_args(s, argc - 1, argv + 1); 255 256 if (optind == 0) { 257 help(); 258 return 1; 259 } 260 261 if (s->option_m) 262 exec_other_tcc(s, argv, s->option_m); 263 264 if (s->verbose) 265 display_info(s, 0); 266 267 if (s->print_search_dirs || (s->verbose == 2 && optind == 1)) { 268 tcc_set_output_type(s, TCC_OUTPUT_MEMORY); 269 display_info(s, 1); 270 return 0; 271 } 272 273 if (s->verbose && optind == 1) 274 return 0; 275 276 if (s->nb_files == 0) 277 tcc_error("no input files\n"); 278 279 /* check -c consistency : only single file handled. XXX: checks file type */ 280 if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) { 281 if (s->nb_libraries != 0) 282 tcc_error("cannot specify libraries with -c"); 283 /* accepts only a single input file */ 284 if (s->nb_files != 1) 285 tcc_error("cannot specify multiple files with -c"); 286 } 287 288 if (s->output_type == TCC_OUTPUT_PREPROCESS) { 289 if (!s->outfile) { 290 s->ppfp = stdout; 258 opt = tcc_parse_args(s, &argc, &argv, 1); 259 260 if ((n | t) == 0) { 261 if (opt == OPT_HELP) 262 return printf(help), 1; 263 if (opt == OPT_HELP2) 264 return printf(help2), 1; 265 if (opt == OPT_M32 || opt == OPT_M64) 266 tcc_tool_cross(s, argv, opt); /* never returns */ 267 if (s->verbose) 268 printf(version); 269 if (opt == OPT_AR) 270 return tcc_tool_ar(s, argc, argv); 271 #ifdef TCC_TARGET_PE 272 if (opt == OPT_IMPDEF) 273 return tcc_tool_impdef(s, argc, argv); 274 #endif 275 if (opt == OPT_V) 276 return 0; 277 if (opt == OPT_PRINT_DIRS) { 278 /* initialize search dirs */ 279 set_environment(s); 280 tcc_set_output_type(s, TCC_OUTPUT_MEMORY); 281 print_search_dirs(s); 282 return 0; 283 } 284 285 n = s->nb_files; 286 if (n == 0) 287 tcc_error("no input files\n"); 288 289 if (s->output_type == TCC_OUTPUT_PREPROCESS) { 290 if (s->outfile) { 291 ppfp = fopen(s->outfile, "w"); 292 if (!ppfp) 293 tcc_error("could not write '%s'", s->outfile); 294 } 295 } else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) { 296 if (s->nb_libraries) 297 tcc_error("cannot specify libraries with -c"); 298 if (n > 1 && s->outfile) 299 tcc_error("cannot specify output file with -c many files"); 291 300 } else { 292 s->ppfp = fopen(s->outfile, "w"); 293 if (!s->ppfp) 294 tcc_error("could not write '%s'", s->outfile); 301 if (s->option_pthread) 302 tcc_set_options(s, "-lpthread"); 295 303 } 296 } 297 298 bench = s->do_bench; 299 if (bench) 300 start_time = getclock_us(); 301 304 305 if (s->do_bench) 306 start_time = getclock_ms(); 307 } 308 309 set_environment(s); 310 if (s->output_type == 0) 311 s->output_type = TCC_OUTPUT_EXE; 302 312 tcc_set_output_type(s, s->output_type); 313 s->ppfp = ppfp; 314 315 if ((s->output_type == TCC_OUTPUT_MEMORY 316 || s->output_type == TCC_OUTPUT_PREPROCESS) && (s->dflag & 16)) 317 s->dflag |= t ? 32 : 0, s->run_test = ++t, n = s->nb_files; 303 318 304 319 /* compile or add each files or library */ 305 for(i = ret = 0; i < s->nb_files && ret == 0; i++) { 306 const char *filename; 307 308 filename = s->files[i]; 309 if (filename[0] == '-' && filename[1] == 'l') { 310 if (tcc_add_library(s, filename + 2) < 0) { 311 tcc_error_noabort("cannot find '%s'", filename); 320 for (first_file = NULL, ret = 0;;) { 321 struct filespec *f = s->files[s->nb_files - n]; 322 s->filetype = f->type; 323 s->alacarte_link = f->alacarte; 324 if (f->type == AFF_TYPE_LIB) { 325 if (tcc_add_library_err(s, f->name) < 0) 312 326 ret = 1; 313 }314 327 } else { 315 328 if (1 == s->verbose) 316 printf("-> %s\n", filename); 317 if (tcc_add_file(s, filename) < 0) 329 printf("-> %s\n", f->name); 330 if (!first_file) 331 first_file = f->name; 332 if (tcc_add_file(s, f->name) < 0) 318 333 ret = 1; 319 if (!first_file)320 first_file = filename;321 334 } 322 } 323 324 if (0 == ret) { 325 if (bench) 326 tcc_print_stats(s, getclock_us() - start_time); 327 335 s->filetype = 0; 336 s->alacarte_link = 1; 337 if (--n == 0 || ret 338 || (s->output_type == TCC_OUTPUT_OBJ && !s->option_r)) 339 break; 340 } 341 342 if (s->run_test) { 343 t = 0; 344 } else if (s->output_type == TCC_OUTPUT_PREPROCESS) { 345 ; 346 } else if (0 == ret) { 328 347 if (s->output_type == TCC_OUTPUT_MEMORY) { 329 348 #ifdef TCC_IS_NATIVE 330 ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind); 331 #else 332 tcc_error_noabort("-run is not available in a cross compiler"); 333 ret = 1; 334 #endif 335 } else if (s->output_type == TCC_OUTPUT_PREPROCESS) { 336 if (s->outfile) 337 fclose(s->ppfp); 349 ret = tcc_run(s, argc, argv); 350 #endif 338 351 } else { 339 352 if (!s->outfile) 340 353 s->outfile = default_outputfile(s, first_file); 341 ret = !!tcc_output_file(s, s->outfile);342 /* dump collected dependencies */343 if (s->gen_deps && !ret)354 if (tcc_output_file(s, s->outfile)) 355 ret = 1; 356 else if (s->gen_deps) 344 357 gen_makedeps(s, s->outfile, s->deps_outfile); 345 358 } 346 359 } 347 360 361 if (s->do_bench && (n | t | ret) == 0) 362 tcc_print_stats(s, getclock_ms() - start_time); 348 363 tcc_delete(s); 349 if (bench) 350 tcc_memstats(); 364 if (ret == 0 && n) 365 goto redo; /* compile more files with -c */ 366 if (t) 367 goto redo; /* run more tests with -dt -run */ 368 if (ppfp && ppfp != stdout) 369 fclose(ppfp); 351 370 return ret; 352 371 } -
EcnlProtoTool/trunk/tcc-0.9.27/tcc.h
r321 r331 1 1 /* 2 2 * TCC - Tiny C Compiler 3 * 3 * 4 4 * Copyright (c) 2001-2004 Fabrice Bellard 5 5 * … … 25 25 #include "config.h" 26 26 27 #ifdef CONFIG_TCCBOOT28 #include "tccboot.h"29 #define CONFIG_TCC_STATIC30 #else31 32 27 #include <stdlib.h> 33 28 #include <stdio.h> … … 36 31 #include <errno.h> 37 32 #include <math.h> 38 #include <signal.h>39 #define SA_RESETHAND 0x8000000040 #define FPE_INTDIV 141 #define FPE_FLTDIV 342 typedef struct { int si_signo, si_errno, si_code; } siginfo_t;43 33 #include <fcntl.h> 44 34 #include <setjmp.h> … … 48 38 # include <unistd.h> 49 39 # include <sys/time.h> 50 /*# include <sys/ucontext.h>*/51 typedef struct __ucontext ucontext_t;52 /*# include <sys/mman.h>*/53 #define PROT_READ 154 #define PROT_WRITE 255 #define PROT_EXEC 456 40 # ifndef CONFIG_TCC_STATIC 57 41 # include <dlfcn.h> 58 42 # endif 59 #else 60 # include <unistd.h> 61 # include <sys/time.h> 62 # include <sys/ucontext.h> 63 # include <sys/mman.h> 43 /* XXX: need to define this to use them in non ISOC99 context */ 44 extern float strtof (const char *__nptr, char **__endptr); 45 extern long double strtold (const char *__nptr, char **__endptr); 46 #endif 47 48 #ifdef _WIN32 49 # include <windows.h> 50 # include <io.h> /* open, close etc. */ 51 # include <direct.h> /* getcwd */ 52 # ifdef __GNUC__ 64 53 # include <stdint.h> 54 # endif 65 55 # define inline __inline 66 # define inp next_inp 56 # define snprintf _snprintf 57 # define vsnprintf _vsnprintf 58 # ifndef __GNUC__ 59 # define strtold (long double)strtod 60 # define strtof (float)strtod 61 # define strtoll _strtoi64 62 # define strtoull _strtoui64 63 # endif 67 64 # ifdef LIBTCC_AS_DLL 68 65 # define LIBTCCAPI __declspec(dllexport) 69 66 # define PUB_FUNC LIBTCCAPI 70 67 # endif 71 #endif 72 73 #endif /* !CONFIG_TCCBOOT */ 68 # define inp next_inp /* inp is an intrinsic on msvc/mingw */ 69 # ifdef _MSC_VER 70 # pragma warning (disable : 4244) // conversion from 'uint64_t' to 'int', possible loss of data 71 # pragma warning (disable : 4267) // conversion from 'size_t' to 'int', possible loss of data 72 # pragma warning (disable : 4996) // The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name 73 # pragma warning (disable : 4018) // signed/unsigned mismatch 74 # pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned 75 # define ssize_t intptr_t 76 # endif 77 # undef CONFIG_TCC_STATIC 78 #endif 74 79 75 80 #ifndef O_BINARY … … 77 82 #endif 78 83 79 #include "elf.h" 80 #ifdef TCC_TARGET_X86_64 81 # define ELFCLASSW ELFCLASS64 82 # define ElfW(type) Elf##64##_##type 83 # define ELFW(type) ELF##64##_##type 84 # define ElfW_Rel ElfW(Rela) 85 # define SHT_RELX SHT_RELA 86 # define REL_SECTION_FMT ".rela%s" 87 /* XXX: DLL with PLT would only work with x86-64 for now */ 88 # define TCC_OUTPUT_DLL_WITH_PLT 84 #ifndef offsetof 85 #define offsetof(type, field) ((size_t) &((type *)0)->field) 86 #endif 87 88 #ifndef countof 89 #define countof(tab) (sizeof(tab) / sizeof((tab)[0])) 90 #endif 91 92 #ifdef _MSC_VER 93 # define NORETURN __declspec(noreturn) 94 # define ALIGNED(x) __declspec(align(x)) 89 95 #else 90 # define ELFCLASSW ELFCLASS32 91 # define ElfW(type) Elf##32##_##type 92 # define ELFW(type) ELF##32##_##type 93 # define ElfW_Rel ElfW(Rel) 94 # define SHT_RELX SHT_REL 95 # define REL_SECTION_FMT ".rel%s" 96 #endif 97 98 /* target address type */ 99 #define addr_t ElfW(Addr) 100 101 #include "stab.h" 102 #include "libtcc.h" 96 # define NORETURN __attribute__((noreturn)) 97 # define ALIGNED(x) __attribute__((aligned(x))) 98 #endif 99 100 #ifdef _WIN32 101 # define IS_DIRSEP(c) (c == '/' || c == '\\') 102 # define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2]))) 103 # define PATHCMP stricmp 104 # define PATHSEP ";" 105 #else 106 # define IS_DIRSEP(c) (c == '/') 107 # define IS_ABSPATH(p) IS_DIRSEP(p[0]) 108 # define PATHCMP strcmp 109 # define PATHSEP ":" 110 #endif 111 112 /* -------------------------------------------- */ 103 113 104 114 /* parser debug */ 105 / /#define PARSE_DEBUG115 /* #define PARSE_DEBUG */ 106 116 /* preprocessor debug */ 107 / /#define PP_DEBUG117 /* #define PP_DEBUG */ 108 118 /* include file debug */ 109 / /#define INC_DEBUG119 /* #define INC_DEBUG */ 110 120 /* memory leak debug */ 111 / /#define MEM_DEBUG121 /* #define MEM_DEBUG */ 112 122 /* assembler debug */ 113 / /#define ASM_DEBUG123 /* #define ASM_DEBUG */ 114 124 115 125 /* target selection */ 116 / /#define TCC_TARGET_I386/* i386 code generator */117 / /#define TCC_TARGET_ARM /* ARMv4 code generator */118 / /#define TCC_TARGET_C67 /* TMS320C67xxcode generator */119 / /#define TCC_TARGET_X86_64 /* x86-64code generator */120 / /#define TCC_TARGET_IL /* ILcode generator */126 /* #define TCC_TARGET_I386 *//* i386 code generator */ 127 /* #define TCC_TARGET_X86_64 *//* x86-64 code generator */ 128 /* #define TCC_TARGET_ARM *//* ARMv4 code generator */ 129 /* #define TCC_TARGET_ARM64 *//* ARMv8 code generator */ 130 /* #define TCC_TARGET_C67 *//* TMS320C67xx code generator */ 121 131 122 132 /* default target is I386 */ 123 133 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \ 124 !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64) && \ 125 !defined(TCC_TARGET_IL) 126 #define TCC_TARGET_I386 127 #endif 128 129 #if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \ 130 !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64) 131 #define CONFIG_TCC_BCHECK /* enable bound checking code */ 132 #endif 133 134 /* define it to include assembler support */ 135 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67) 136 #define CONFIG_TCC_ASM 137 #endif 138 139 /* object format selection */ 140 #if defined(TCC_TARGET_C67) 141 #define TCC_TARGET_COFF 134 !defined(TCC_TARGET_ARM64) && !defined(TCC_TARGET_C67) && \ 135 !defined(TCC_TARGET_X86_64) 136 # if defined __x86_64__ || defined _AMD64_ 137 # define TCC_TARGET_X86_64 138 # elif defined __arm__ 139 # define TCC_TARGET_ARM 140 # define TCC_ARM_EABI 141 # define TCC_ARM_HARDFLOAT 142 # elif defined __aarch64__ 143 # define TCC_TARGET_ARM64 144 # else 145 # define TCC_TARGET_I386 146 # endif 147 # ifdef _WIN32 148 # define TCC_TARGET_PE 1 149 # endif 142 150 #endif 143 151 … … 150 158 # elif defined __arm__ && defined TCC_TARGET_ARM 151 159 # define TCC_IS_NATIVE 160 # elif defined __aarch64__ && defined TCC_TARGET_ARM64 161 # define TCC_IS_NATIVE 152 162 # endif 153 163 #endif … … 155 165 #if defined TCC_IS_NATIVE && !defined CONFIG_TCCBOOT 156 166 # define CONFIG_TCC_BACKTRACE 167 # if (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64) \ 168 && !defined TCC_UCLIBC && !defined TCC_MUSL 169 # define CONFIG_TCC_BCHECK /* enable bound checking code */ 170 # endif 157 171 #endif 158 172 … … 163 177 #endif 164 178 #ifndef CONFIG_TCCDIR 165 # define CONFIG_TCCDIR " ."179 # define CONFIG_TCCDIR "/usr/local/lib/tcc" 166 180 #endif 167 181 #ifndef CONFIG_LDDIR 168 182 # define CONFIG_LDDIR "lib" 169 183 #endif 184 #ifdef CONFIG_TRIPLET 185 # define USE_TRIPLET(s) s "/" CONFIG_TRIPLET 186 # define ALSO_TRIPLET(s) USE_TRIPLET(s) ":" s 187 #else 188 # define USE_TRIPLET(s) s 189 # define ALSO_TRIPLET(s) s 190 #endif 170 191 171 192 /* path to find crt1.o, crti.o and crtn.o */ 172 193 #ifndef CONFIG_TCC_CRTPREFIX 173 # define CONFIG_TCC_CRTPREFIX CONFIG_SYSROOT "/usr/" CONFIG_LDDIR194 # define CONFIG_TCC_CRTPREFIX USE_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) 174 195 #endif 175 196 … … 179 200 #ifndef CONFIG_TCC_SYSINCLUDEPATHS 180 201 # ifdef TCC_TARGET_PE 181 # define CONFIG_TCC_SYSINCLUDEPATHS "{B}/include;{B}/include/winapi" 182 # elif defined CONFIG_MULTIARCHDIR 183 # define CONFIG_TCC_SYSINCLUDEPATHS \ 184 CONFIG_SYSROOT "/usr/local/include" \ 185 ":" CONFIG_SYSROOT "/usr/local/include/" CONFIG_MULTIARCHDIR \ 186 ":" CONFIG_SYSROOT "/usr/include" \ 187 ":" CONFIG_SYSROOT "/usr/include/" CONFIG_MULTIARCHDIR \ 188 ":" "{B}/include" 202 # define CONFIG_TCC_SYSINCLUDEPATHS "{B}/include"PATHSEP"{B}/include/winapi" 189 203 # else 190 204 # define CONFIG_TCC_SYSINCLUDEPATHS \ 191 CONFIG_SYSROOT "/usr/local/include" \192 ":" CONFIG_SYSROOT "/usr/include"\193 ":" "{B}/include"205 "{B}/include" \ 206 ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/include") \ 207 ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/include") 194 208 # endif 195 209 #endif … … 201 215 # else 202 216 # define CONFIG_TCC_LIBPATHS \ 203 CONFIG_SYSROOT "/usr/" CONFIG_LDDIR\204 ":" CONFIG_SYSROOT "/" CONFIG_LDDIR\205 ":" CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR217 ALSO_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \ 218 ":" ALSO_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) \ 219 ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR) 206 220 # endif 207 221 #endif … … 212 226 # define CONFIG_TCC_ELFINTERP "/libexec/ld-elf.so.1" 213 227 # elif defined __FreeBSD_kernel__ 214 # define CONFIG_TCC_ELFINTERP "/lib/ld.so.1" 215 # elif defined TCC_ARM_HARDFLOAT 216 # define CONFIG_TCC_ELFINTERP "/lib/ld-linux-armhf.so.3" 217 # elif defined TCC_ARM_EABI 218 # define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.3" 219 # elif defined(TCC_TARGET_X86_64) 220 # define CONFIG_TCC_ELFINTERP "/lib64/ld-linux-x86-64.so.2" 221 # elif defined(TCC_UCLIBC) 222 # define CONFIG_TCC_ELFINTERP "/lib/ld-uClibc.so.0" 228 # if defined(TCC_TARGET_X86_64) 229 # define CONFIG_TCC_ELFINTERP "/lib/ld-kfreebsd-x86-64.so.1" 230 # else 231 # define CONFIG_TCC_ELFINTERP "/lib/ld.so.1" 232 # endif 233 # elif defined __DragonFly__ 234 # define CONFIG_TCC_ELFINTERP "/usr/libexec/ld-elf.so.2" 235 # elif defined __NetBSD__ 236 # define CONFIG_TCC_ELFINTERP "/usr/libexec/ld.elf_so" 237 # elif defined __GNU__ 238 # define CONFIG_TCC_ELFINTERP "/lib/ld.so" 223 239 # elif defined(TCC_TARGET_PE) 224 240 # define CONFIG_TCC_ELFINTERP "-" 225 # else 226 # define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2" 241 # elif defined(TCC_UCLIBC) 242 # define CONFIG_TCC_ELFINTERP "/lib/ld-uClibc.so.0" /* is there a uClibc for x86_64 ? */ 243 # elif defined TCC_TARGET_ARM64 244 # if defined(TCC_MUSL) 245 # define CONFIG_TCC_ELFINTERP "/lib/ld-musl-aarch64.so.1" 246 # else 247 # define CONFIG_TCC_ELFINTERP "/lib/ld-linux-aarch64.so.1" 248 # endif 249 # elif defined(TCC_TARGET_X86_64) 250 # if defined(TCC_MUSL) 251 # define CONFIG_TCC_ELFINTERP "/lib/ld-musl-x86_64.so.1" 252 # else 253 # define CONFIG_TCC_ELFINTERP "/lib64/ld-linux-x86-64.so.2" 254 # endif 255 # elif !defined(TCC_ARM_EABI) 256 # if defined(TCC_MUSL) 257 # define CONFIG_TCC_ELFINTERP "/lib/ld-musl-arm.so.1" 258 # else 259 # define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2" 260 # endif 227 261 # endif 228 262 #endif 229 263 264 /* var elf_interp dans *-gen.c */ 265 #ifdef CONFIG_TCC_ELFINTERP 266 # define DEFAULT_ELFINTERP(s) CONFIG_TCC_ELFINTERP 267 #else 268 # define DEFAULT_ELFINTERP(s) default_elfinterp(s) 269 #endif 270 271 /* (target specific) libtcc1.a */ 272 #ifndef TCC_LIBTCC1 273 # define TCC_LIBTCC1 "libtcc1.a" 274 #endif 275 230 276 /* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */ 231 #define TCC_LIBGCC CONFIG_SYSROOT "/" CONFIG_LDDIR "/libgcc_s.so.1" 277 #if defined CONFIG_USE_LIBGCC && !defined TCC_LIBGCC 278 #define TCC_LIBGCC USE_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1" 279 #endif 280 281 /* -------------------------------------------- */ 282 283 #include "libtcc.h" 284 #include "elf.h" 285 #include "stab.h" 286 287 /* -------------------------------------------- */ 288 289 #ifndef PUB_FUNC /* functions used by tcc.c but not in libtcc.h */ 290 # define PUB_FUNC 291 #endif 292 293 #ifndef ONE_SOURCE 294 # define ONE_SOURCE 1 295 #endif 296 297 #if ONE_SOURCE 298 #define ST_INLN static inline 299 #define ST_FUNC static 300 #define ST_DATA static 301 #else 302 #define ST_INLN 303 #define ST_FUNC 304 #define ST_DATA extern 305 #endif 306 307 #ifdef TCC_PROFILE /* profile all functions */ 308 # define static 309 #endif 232 310 233 311 /* -------------------------------------------- */ … … 237 315 #ifdef TCC_TARGET_I386 238 316 # include "i386-gen.c" 317 # include "i386-link.c" 239 318 #endif 240 319 #ifdef TCC_TARGET_X86_64 241 320 # include "x86_64-gen.c" 321 # include "x86_64-link.c" 242 322 #endif 243 323 #ifdef TCC_TARGET_ARM 244 324 # include "arm-gen.c" 325 # include "arm-link.c" 326 # include "arm-asm.c" 327 #endif 328 #ifdef TCC_TARGET_ARM64 329 # include "arm64-gen.c" 330 # include "arm64-link.c" 245 331 #endif 246 332 #ifdef TCC_TARGET_C67 333 # define TCC_TARGET_COFF 247 334 # include "coff.h" 248 335 # include "c67-gen.c" 249 #endif 250 #ifdef TCC_TARGET_IL 251 #include "il-gen.c" 336 # include "c67-link.c" 252 337 #endif 253 338 #undef TARGET_DEFS_ONLY 339 340 /* -------------------------------------------- */ 341 342 #if PTR_SIZE == 8 343 # define ELFCLASSW ELFCLASS64 344 # define ElfW(type) Elf##64##_##type 345 # define ELFW(type) ELF##64##_##type 346 # define ElfW_Rel ElfW(Rela) 347 # define SHT_RELX SHT_RELA 348 # define REL_SECTION_FMT ".rela%s" 349 #else 350 # define ELFCLASSW ELFCLASS32 351 # define ElfW(type) Elf##32##_##type 352 # define ELFW(type) ELF##32##_##type 353 # define ElfW_Rel ElfW(Rel) 354 # define SHT_RELX SHT_REL 355 # define REL_SECTION_FMT ".rel%s" 356 #endif 357 /* target address type */ 358 #define addr_t ElfW(Addr) 359 #define ElfSym ElfW(Sym) 360 361 #if PTR_SIZE == 8 && !defined TCC_TARGET_PE 362 # define LONG_SIZE 8 363 #else 364 # define LONG_SIZE 4 365 #endif 254 366 255 367 /* -------------------------------------------- */ … … 259 371 #define VSTACK_SIZE 256 260 372 #define STRING_MAX_SIZE 1024 373 #define TOKSTR_MAX_SIZE 256 261 374 #define PACK_STACK_SIZE 8 262 375 263 #define TOK_HASH_SIZE 8192/* must be a power of two */376 #define TOK_HASH_SIZE 16384 /* must be a power of two */ 264 377 #define TOK_ALLOC_INCR 512 /* must be a power of two */ 265 378 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */ … … 287 400 void *data; /* either 'char *' or 'nwchar_t *' */ 288 401 int size_allocated; 289 void *data_allocated; /* if non NULL, data has been malloced */290 402 } CString; 291 403 … … 301 413 double d; 302 414 float f; 303 int i; 304 unsigned int ui; 305 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */ 306 long long ll; 307 unsigned long long ull; 308 struct CString *cstr; 309 void *ptr; 415 uint64_t i; 416 struct { 417 int size; 418 const void *data; 419 } str; 310 420 int tab[LDOUBLE_SIZE/4]; 311 421 } CValue; … … 318 428 type. If not used, set to VT_CONST */ 319 429 CValue c; /* constant, if VT_CONST */ 320 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */ 430 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST), or if 431 result of unary() for an identifier. */ 321 432 } SValue; 433 434 /* symbol attributes */ 435 struct SymAttr { 436 unsigned short 437 aligned : 5, /* alignment as log2+1 (0 == unspecified) */ 438 packed : 1, 439 weak : 1, 440 visibility : 2, 441 dllexport : 1, 442 dllimport : 1, 443 unused : 5; 444 }; 445 446 /* function attributes or temporary attributes for parsing */ 447 struct FuncAttr { 448 unsigned 449 func_call : 3, /* calling convention (0..5), see below */ 450 func_type : 2, /* FUNC_OLD/NEW/ELLIPSIS */ 451 func_args : 8; /* PE __stdcall args */ 452 }; 453 454 /* GNUC attribute definition */ 455 typedef struct AttributeDef { 456 struct SymAttr a; 457 struct FuncAttr f; 458 struct Section *section; 459 int alias_target; /* token */ 460 int asm_label; /* associated asm label */ 461 char attr_mode; /* __attribute__((__mode__(...))) */ 462 } AttributeDef; 322 463 323 464 /* symbol management */ 324 465 typedef struct Sym { 325 int v; 326 char *asm_label; /* associated asm label*/327 long r; /* associated register*/466 int v; /* symbol token */ 467 unsigned short r; /* associated register or VT_CONST/VT_LOCAL and LVAL type */ 468 struct SymAttr a; /* symbol attributes */ 328 469 union { 329 long c; /* associated number */ 330 int *d; /* define token stream */ 470 struct { 471 int c; /* associated number or Elf symbol index */ 472 union { 473 int sym_scope; /* scope level for locals */ 474 int jnext; /* next jump label */ 475 struct FuncAttr f; /* function attributes */ 476 int auxtype; /* bitfield access type */ 477 }; 478 }; 479 long long enum_val; /* enum constant if IS_ENUM_VAL */ 480 int *d; /* define token stream */ 331 481 }; 332 CType type; 482 CType type; /* associated type */ 333 483 union { 334 struct Sym *next; /* next related symbol */335 long jnext; /* next jumplabel */484 struct Sym *next; /* next related symbol (for fields and anoms) */ 485 int asm_label; /* associated asm label */ 336 486 }; 337 487 struct Sym *prev; /* prev symbol in stack */ … … 340 490 341 491 /* section definition */ 342 /* XXX: use directly ELF structure for parameters ? */343 /* special flag to indicate that the section should not be linked to344 the other ones */345 #define SHF_PRIVATE 0x80000000346 347 /* special flag, too */348 #define SECTION_ABS ((void *)1)349 350 492 typedef struct Section { 351 493 unsigned long data_offset; /* current data offset */ … … 365 507 struct Section *link; /* link to another section */ 366 508 struct Section *reloc; /* corresponding section for relocation, if any */ 367 struct Section *hash; 368 struct Section * next;509 struct Section *hash; /* hash table for symbols */ 510 struct Section *prev; /* previous section on section stack */ 369 511 char name[1]; /* section name */ 370 512 } Section; … … 376 518 } DLLReference; 377 519 378 /* GNUC attribute definition */379 typedef struct AttributeDef {380 unsigned381 func_call : 3, /* calling convention (0..5), see below */382 aligned : 5, /* alignement (0..16) */383 packed : 1,384 func_export : 1,385 func_import : 1,386 func_args : 5,387 mode : 4,388 weak : 1,389 fill : 11;390 struct Section *section;391 int alias_target; /* token */392 } AttributeDef;393 394 /* gr: wrappers for casting sym->r for other purposes */395 #define FUNC_CALL(r) (((AttributeDef*)&(r))->func_call)396 #define FUNC_EXPORT(r) (((AttributeDef*)&(r))->func_export)397 #define FUNC_IMPORT(r) (((AttributeDef*)&(r))->func_import)398 #define FUNC_ARGS(r) (((AttributeDef*)&(r))->func_args)399 #define FUNC_ALIGN(r) (((AttributeDef*)&(r))->aligned)400 #define FUNC_PACKED(r) (((AttributeDef*)&(r))->packed)401 #define ATTR_MODE(r) (((AttributeDef*)&(r))->mode)402 #define INT_ATTR(ad) (*(int*)(ad))403 404 520 /* -------------------------------------------------- */ 405 521 … … 408 524 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */ 409 525 410 /* stored in 'Sym .c' field */526 /* stored in 'Sym->f.func_type' field */ 411 527 #define FUNC_NEW 1 /* ansi function prototype */ 412 528 #define FUNC_OLD 2 /* old function prototype */ 413 529 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */ 414 530 415 /* stored in 'Sym .r' field */531 /* stored in 'Sym->f.func_call' field */ 416 532 #define FUNC_CDECL 0 /* standard c call */ 417 533 #define FUNC_STDCALL 1 /* pascal c call */ … … 442 558 struct BufferedFile *prev; 443 559 int line_num; /* current line number - here to simplify code */ 560 int line_ref; /* tcc -E: last printed line */ 444 561 int ifndef_macro; /* #ifndef macro / #endif search */ 445 562 int ifndef_macro_saved; /* saved ifndef_macro */ 446 563 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */ 564 int include_next_index; /* next search path */ 447 565 char filename[1024]; /* filename */ 448 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */ 566 char *true_filename; /* filename not modified by # line directive */ 567 unsigned char unget[4]; 568 unsigned char buffer[1]; /* extra size for CH_EOB char */ 449 569 } BufferedFile; 450 570 451 571 #define CH_EOB '\\' /* end of buffer or '\0' char in file */ 452 572 #define CH_EOF (-1) /* end of file */ 453 454 /* parsing state (used to save parser state to reparse part of the455 source several times) */456 typedef struct ParseState {457 const int *macro_ptr;458 int line_num;459 int tok;460 CValue tokc;461 } ParseState;462 573 463 574 /* used to record tokens */ … … 465 576 int *str; 466 577 int len; 578 int lastlen; 467 579 int allocated_len; 468 580 int last_line_num; 581 int save_line_num; 582 /* used to chain token-strings with begin/end_macro() */ 583 struct TokenString *prev; 584 const int *prev_ptr; 585 char alloc; 469 586 } TokenString; 470 587 471 588 /* inline functions */ 472 589 typedef struct InlineFunc { 473 int *token_str;590 TokenString *func_str; 474 591 Sym *sym; 475 592 char filename[1]; … … 480 597 typedef struct CachedInclude { 481 598 int ifndef_macro; 599 int once; 482 600 int hash_next; /* -1 if none */ 483 601 char filename[1]; /* path specified in #include */ 484 602 } CachedInclude; 485 603 486 #define CACHED_INCLUDES_HASH_SIZE 512604 #define CACHED_INCLUDES_HASH_SIZE 32 487 605 488 606 #ifdef CONFIG_TCC_ASM 489 607 typedef struct ExprValue { 490 uint 32_t v;608 uint64_t v; 491 609 Sym *sym; 610 int pcrel; 492 611 } ExprValue; 493 612 494 613 #define MAX_ASM_OPERANDS 30 495 614 typedef struct ASMOperand { 496 int id; /* GCC 3 option nal identifier (0 if number only supported */615 int id; /* GCC 3 optional identifier (0 if number only supported */ 497 616 char *constraint; 498 617 char asm_str[16]; /* computed asm string for operand */ … … 508 627 #endif 509 628 629 /* extra symbol attributes (not in symbol table) */ 510 630 struct sym_attr { 511 unsigned long got_offset; 631 unsigned got_offset; 632 unsigned plt_offset; 633 int plt_sym; 634 int dyn_index; 512 635 #ifdef TCC_TARGET_ARM 513 636 unsigned char plt_thumb_stub:1; … … 529 652 char *soname; /* as specified on the command line (-soname) */ 530 653 char *rpath; /* as specified on the command line (-Wl,-rpath=) */ 654 int enable_new_dtags; /* ditto, (-Wl,--enable-new-dtags) */ 531 655 532 656 /* output type, see TCC_OUTPUT_XXX */ … … 538 662 int char_is_unsigned; 539 663 int leading_underscore; 540 664 int ms_extensions; /* allow nested named struct w/o identifier behave like unnamed */ 665 int dollars_in_identifiers; /* allows '$' char in identifiers */ 666 int ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */ 667 541 668 /* warning switches */ 542 669 int warn_write_strings; … … 545 672 int warn_none; 546 673 int warn_implicit_function_declaration; 674 int warn_gcc_compat; 547 675 548 676 /* compile with debug symbol (and use them if error during execution) */ … … 552 680 int do_bounds_check; 553 681 #endif 682 #ifdef TCC_TARGET_ARM 683 enum float_abi float_abi; /* float ABI of the generated code*/ 684 #endif 685 int run_test; /* nth test to run with -dt -run */ 554 686 555 687 addr_t text_addr; /* address of text section */ 556 688 int has_text_addr; 557 689 558 unsigned longsection_align; /* section alignment */690 unsigned section_align; /* section alignment */ 559 691 560 692 char *init_symbol; /* symbols to call at load-time (not used currently) */ 561 693 char *fini_symbol; /* symbols to call at unload-time (not used currently) */ 562 694 563 695 #ifdef TCC_TARGET_I386 564 696 int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */ 697 #endif 698 #ifdef TCC_TARGET_X86_64 699 int nosse; /* For -mno-sse support. */ 565 700 #endif 566 701 … … 583 718 char **crt_paths; 584 719 int nb_crt_paths; 720 721 /* -include files */ 722 char **cmd_include_files; 723 int nb_cmd_include_files; 585 724 586 725 /* error handling */ … … 593 732 /* output file for preprocessing (-E) */ 594 733 FILE *ppfp; 734 enum { 735 LINE_MACRO_OUTPUT_FORMAT_GCC, 736 LINE_MACRO_OUTPUT_FORMAT_NONE, 737 LINE_MACRO_OUTPUT_FORMAT_STD, 738 LINE_MACRO_OUTPUT_FORMAT_P10 = 11 739 } Pflag; /* -P switch */ 740 char dflag; /* -dX value */ 595 741 596 742 /* for -MD/-MF: collected dependencies for this compilation */ … … 613 759 int pack_stack[PACK_STACK_SIZE]; 614 760 int *pack_stack_ptr; 761 char **pragma_libs; 762 int nb_pragma_libs; 615 763 616 764 /* inline functions are stored as token lists and compiled last … … 629 777 Section *got; 630 778 Section *plt; 631 struct sym_attr *sym_attrs;632 int nb_sym_attrs;633 /* give the correspondance from symtab indexes to dynsym indexes */634 int *symtab_to_dynsym;635 779 636 780 /* temporary dynamic symbol sections (for dll loading) */ … … 638 782 /* exported dynamic symbol section */ 639 783 Section *dynsym; 640 /* copy of the g obal symtab_section variable */784 /* copy of the global symtab_section variable */ 641 785 Section *symtab; 642 /* tiny assembler state */ 643 Sym *asm_labels; 786 /* extra attributes (eg. GOT/PLT value) for symtab symbols */ 787 struct sym_attr *sym_attrs; 788 int nb_sym_attrs; 644 789 645 790 #ifdef TCC_TARGET_PE 646 791 /* PE info */ 647 792 int pe_subsystem; 793 unsigned pe_characteristics; 648 794 unsigned pe_file_align; 649 795 unsigned pe_stack_size; 796 addr_t pe_imagebase; 650 797 # ifdef TCC_TARGET_X86_64 651 798 Section *uw_pdata; … … 656 803 657 804 #ifdef TCC_IS_NATIVE 658 /* for tcc_relocate */ 659 void *runtime_mem; 660 # ifdef HAVE_SELINUX 661 void *write_mem; 662 unsigned long mem_size; 663 # endif 664 # if !defined TCC_TARGET_PE && (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM) 665 /* write PLT and GOT here */ 666 char *runtime_plt_and_got; 667 unsigned runtime_plt_and_got_offset; 668 # define TCC_HAS_RUNTIME_PLTGOT 669 # endif 805 const char *runtime_main; 806 void **runtime_mem; 807 int nb_runtime_mem; 670 808 #endif 671 809 672 810 /* used by main and tcc_parse_args only */ 673 char**files; /* files seen on command line */811 struct filespec **files; /* files seen on command line */ 674 812 int nb_files; /* number thereof */ 675 813 int nb_libraries; /* number of libs thereof */ 814 int filetype; 676 815 char *outfile; /* output filename */ 677 char *option_m; /* only -m32/-m64 handled */678 int print_search_dirs; /* option */679 816 int option_r; /* option -r */ 680 817 int do_bench; /* option -bench */ 681 818 int gen_deps; /* option -MD */ 682 819 char *deps_outfile; /* option -MF */ 820 int option_pthread; /* -pthread option */ 821 int argc; 822 char **argv; 823 }; 824 825 struct filespec { 826 char type; 827 char alacarte; 828 char name[1]; 683 829 }; 684 830 … … 691 837 #define VT_JMP 0x0034 /* value is the consequence of jmp true (even) */ 692 838 #define VT_JMPI 0x0035 /* value is the consequence of jmp false (odd) */ 693 #define VT_REF 0x0040 /* value is pointer to structure rather than address */694 839 #define VT_LVAL 0x0100 /* var is an lvalue */ 695 840 #define VT_SYM 0x0200 /* a symbol value is added */ … … 707 852 /* types */ 708 853 #define VT_BTYPE 0x000f /* mask for basic type */ 709 #define VT_ INT 0 /* integertype */854 #define VT_VOID 0 /* void type */ 710 855 #define VT_BYTE 1 /* signed byte type */ 711 856 #define VT_SHORT 2 /* short type */ 712 #define VT_ VOID 3 /* voidtype */713 #define VT_ PTR 4 /* pointer */714 #define VT_ ENUM 5 /* enum definition*/857 #define VT_INT 3 /* integer type */ 858 #define VT_LLONG 4 /* 64 bit integer */ 859 #define VT_PTR 5 /* pointer */ 715 860 #define VT_FUNC 6 /* function type */ 716 861 #define VT_STRUCT 7 /* struct/union definition */ … … 719 864 #define VT_LDOUBLE 10 /* IEEE long double */ 720 865 #define VT_BOOL 11 /* ISOC99 boolean type */ 721 #define VT_ LLONG 12 /* 64 bit integer*/722 #define VT_ LONG 13 /* long integer (NEVER USED as type, only723 during parsing) */ 866 #define VT_QLONG 13 /* 128-bit integer. Only used for x86-64 ABI */ 867 #define VT_QFLOAT 14 /* 128-bit float. Only used for x86-64 ABI */ 868 724 869 #define VT_UNSIGNED 0x0010 /* unsigned type */ 725 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */ 726 #define VT_BITFIELD 0x0040 /* bitfield modifier */ 727 #define VT_CONSTANT 0x0800 /* const modifier */ 728 #define VT_VOLATILE 0x1000 /* volatile modifier */ 729 #define VT_SIGNED 0x2000 /* signed type */ 730 #define VT_VLA 0x00020000 /* VLA type (also has VT_PTR and VT_ARRAY) */ 870 #define VT_DEFSIGN 0x0020 /* explicitly signed or unsigned */ 871 #define VT_ARRAY 0x0040 /* array type (also has VT_PTR) */ 872 #define VT_BITFIELD 0x0080 /* bitfield modifier */ 873 #define VT_CONSTANT 0x0100 /* const modifier */ 874 #define VT_VOLATILE 0x0200 /* volatile modifier */ 875 #define VT_VLA 0x0400 /* VLA type (also has VT_PTR and VT_ARRAY) */ 876 #define VT_LONG 0x0800 /* long type (also has VT_INT rsp. VT_LLONG) */ 731 877 732 878 /* storage */ 733 #define VT_EXTERN 0x00000080 /* extern definition */ 734 #define VT_STATIC 0x00000100 /* static variable */ 735 #define VT_TYPEDEF 0x00000200 /* typedef definition */ 736 #define VT_INLINE 0x00000400 /* inline definition */ 737 #define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */ 738 #define VT_EXPORT 0x00008000 /* win32: data exported from dll */ 739 #define VT_WEAK 0x00010000 /* weak symbol */ 740 741 #define VT_STRUCT_SHIFT 18 /* shift for bitfield shift values (max: 32 - 2*6) */ 879 #define VT_EXTERN 0x00001000 /* extern definition */ 880 #define VT_STATIC 0x00002000 /* static variable */ 881 #define VT_TYPEDEF 0x00004000 /* typedef definition */ 882 #define VT_INLINE 0x00008000 /* inline definition */ 883 /* currently unused: 0x000[1248]0000 */ 884 885 #define VT_STRUCT_SHIFT 20 /* shift for bitfield shift values (32 - 2*6) */ 886 #define VT_STRUCT_MASK (((1 << (6+6)) - 1) << VT_STRUCT_SHIFT | VT_BITFIELD) 887 #define BIT_POS(t) (((t) >> VT_STRUCT_SHIFT) & 0x3f) 888 #define BIT_SIZE(t) (((t) >> (VT_STRUCT_SHIFT + 6)) & 0x3f) 889 890 #define VT_UNION (1 << VT_STRUCT_SHIFT | VT_STRUCT) 891 #define VT_ENUM (2 << VT_STRUCT_SHIFT) /* integral type is an enum really */ 892 #define VT_ENUM_VAL (3 << VT_STRUCT_SHIFT) /* integral type is an enum constant really */ 893 894 #define IS_ENUM(t) ((t & VT_STRUCT_MASK) == VT_ENUM) 895 #define IS_ENUM_VAL(t) ((t & VT_STRUCT_MASK) == VT_ENUM_VAL) 896 #define IS_UNION(t) ((t & (VT_STRUCT_MASK|VT_BTYPE)) == VT_UNION) 742 897 743 898 /* type mask (except storage) */ 744 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK) 745 #define VT_TYPE (~(VT_STORAGE)) 899 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE) 900 #define VT_TYPE (~(VT_STORAGE|VT_STRUCT_MASK)) 901 902 /* symbol was created by tccasm.c first */ 903 #define VT_ASM (VT_VOID | VT_UNSIGNED) 904 #define IS_ASM_SYM(sym) (((sym)->type.t & (VT_BTYPE | VT_ASM)) == VT_ASM) 746 905 747 906 /* token values */ … … 763 922 #define TOK_LAND 0xa0 764 923 #define TOK_LOR 0xa1 765 766 924 #define TOK_DEC 0xa2 767 925 #define TOK_MID 0xa3 /* inc/dec, to void constant */ … … 770 928 #define TOK_UMOD 0xb1 /* unsigned modulo */ 771 929 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */ 772 #define TOK_CINT 0xb3 /* number in tokc */ 773 #define TOK_CCHAR 0xb4 /* char constant in tokc */ 774 #define TOK_STR 0xb5 /* pointer to string in tokc */ 775 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */ 776 #define TOK_LCHAR 0xb7 777 #define TOK_LSTR 0xb8 778 #define TOK_CFLOAT 0xb9 /* float constant */ 779 #define TOK_LINENUM 0xba /* line number info */ 780 #define TOK_CDOUBLE 0xc0 /* double constant */ 781 #define TOK_CLDOUBLE 0xc1 /* long double constant */ 930 931 /* tokens that carry values (in additional token string space / tokc) --> */ 932 #define TOK_CCHAR 0xb3 /* char constant in tokc */ 933 #define TOK_LCHAR 0xb4 934 #define TOK_CINT 0xb5 /* number in tokc */ 935 #define TOK_CUINT 0xb6 /* unsigned int constant */ 936 #define TOK_CLLONG 0xb7 /* long long constant */ 937 #define TOK_CULLONG 0xb8 /* unsigned long long constant */ 938 #define TOK_STR 0xb9 /* pointer to string in tokc */ 939 #define TOK_LSTR 0xba 940 #define TOK_CFLOAT 0xbb /* float constant */ 941 #define TOK_CDOUBLE 0xbc /* double constant */ 942 #define TOK_CLDOUBLE 0xbd /* long double constant */ 943 #define TOK_PPNUM 0xbe /* preprocessor number */ 944 #define TOK_PPSTR 0xbf /* preprocessor string */ 945 #define TOK_LINENUM 0xc0 /* line number info */ 946 #define TOK_TWODOTS 0xa8 /* C++ token ? */ 947 /* <-- */ 948 782 949 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */ 783 950 #define TOK_ADDC1 0xc3 /* add with carry generation */ … … 785 952 #define TOK_SUBC1 0xc5 /* add with carry generation */ 786 953 #define TOK_SUBC2 0xc6 /* add with carry use */ 787 #define TOK_CUINT 0xc8 /* unsigned int constant */ 788 #define TOK_CLLONG 0xc9 /* long long constant */ 789 #define TOK_CULLONG 0xca /* unsigned long long constant */ 790 #define TOK_ARROW 0xcb 791 #define TOK_DOTS 0xcc /* three dots */ 792 #define TOK_SHR 0xcd /* unsigned shift right */ 793 #define TOK_PPNUM 0xce /* preprocessor number */ 794 #define TOK_NOSUBST 0xcf /* means following token has already been pp'd */ 954 #define TOK_ARROW 0xc7 955 #define TOK_DOTS 0xc8 /* three dots */ 956 #define TOK_SHR 0xc9 /* unsigned shift right */ 957 #define TOK_TWOSHARPS 0xca /* ## preprocessing token */ 958 #define TOK_PLCHLDR 0xcb /* placeholder token as defined in C99 */ 959 #define TOK_NOSUBST 0xcc /* means following token has already been pp'd */ 960 #define TOK_PPJOIN 0xcd /* A '##' in the right position to mean pasting */ 961 #define TOK_CLONG 0xce /* long constant */ 962 #define TOK_CULONG 0xcf /* unsigned long constant */ 795 963 796 964 #define TOK_SHL 0x01 /* shift left */ 797 965 #define TOK_SAR 0x02 /* signed shift right */ 798 799 /* assign ement operators : normal operator or 0x80 */966 967 /* assignment operators : normal operator or 0x80 */ 800 968 #define TOK_A_MOD 0xa5 801 969 #define TOK_A_AND 0xa6 … … 809 977 #define TOK_A_SAR 0x82 810 978 811 #ifndef offsetof812 #define offsetof(type, field) ((size_t) &((type *)0)->field)813 #endif814 815 #ifndef countof816 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))817 #endif818 819 979 #define TOK_EOF (-1) /* end of file */ 820 980 #define TOK_LINEFEED 10 /* line feed */ 821 981 822 /* all identifi cators and strings have token above that */982 /* all identifiers and strings have token above that */ 823 983 #define TOK_IDENT 256 824 984 825 985 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x) 826 986 #define TOK_ASM_int TOK_INT 827 #define TOK_ASM_weak TOK_WEAK1 987 #define DEF_ASMDIR(x) DEF(TOK_ASMDIR_ ## x, "." #x) 988 #define TOK_ASMDIR_FIRST TOK_ASMDIR_byte 989 #define TOK_ASMDIR_LAST TOK_ASMDIR_section 828 990 829 991 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 … … 872 1034 DEF_FP1(x) 873 1035 874 #define DEF_ASMTEST(x ) \875 DEF_ASM(x ## o ) \876 DEF_ASM(x ## no ) \877 DEF_ASM(x ## b ) \878 DEF_ASM(x ## c ) \879 DEF_ASM(x ## nae ) \880 DEF_ASM(x ## nb ) \881 DEF_ASM(x ## nc ) \882 DEF_ASM(x ## ae ) \883 DEF_ASM(x ## e ) \884 DEF_ASM(x ## z ) \885 DEF_ASM(x ## ne ) \886 DEF_ASM(x ## nz ) \887 DEF_ASM(x ## be ) \888 DEF_ASM(x ## na ) \889 DEF_ASM(x ## nbe ) \890 DEF_ASM(x ## a ) \891 DEF_ASM(x ## s ) \892 DEF_ASM(x ## ns ) \893 DEF_ASM(x ## p ) \894 DEF_ASM(x ## pe ) \895 DEF_ASM(x ## np ) \896 DEF_ASM(x ## po ) \897 DEF_ASM(x ## l ) \898 DEF_ASM(x ## nge ) \899 DEF_ASM(x ## nl ) \900 DEF_ASM(x ## ge ) \901 DEF_ASM(x ## le ) \902 DEF_ASM(x ## ng ) \903 DEF_ASM(x ## nle ) \904 DEF_ASM(x ## g )905 906 #endif / / defined TCC_TARGET_I386 || defined TCC_TARGET_X86_641036 #define DEF_ASMTEST(x,suffix) \ 1037 DEF_ASM(x ## o ## suffix) \ 1038 DEF_ASM(x ## no ## suffix) \ 1039 DEF_ASM(x ## b ## suffix) \ 1040 DEF_ASM(x ## c ## suffix) \ 1041 DEF_ASM(x ## nae ## suffix) \ 1042 DEF_ASM(x ## nb ## suffix) \ 1043 DEF_ASM(x ## nc ## suffix) \ 1044 DEF_ASM(x ## ae ## suffix) \ 1045 DEF_ASM(x ## e ## suffix) \ 1046 DEF_ASM(x ## z ## suffix) \ 1047 DEF_ASM(x ## ne ## suffix) \ 1048 DEF_ASM(x ## nz ## suffix) \ 1049 DEF_ASM(x ## be ## suffix) \ 1050 DEF_ASM(x ## na ## suffix) \ 1051 DEF_ASM(x ## nbe ## suffix) \ 1052 DEF_ASM(x ## a ## suffix) \ 1053 DEF_ASM(x ## s ## suffix) \ 1054 DEF_ASM(x ## ns ## suffix) \ 1055 DEF_ASM(x ## p ## suffix) \ 1056 DEF_ASM(x ## pe ## suffix) \ 1057 DEF_ASM(x ## np ## suffix) \ 1058 DEF_ASM(x ## po ## suffix) \ 1059 DEF_ASM(x ## l ## suffix) \ 1060 DEF_ASM(x ## nge ## suffix) \ 1061 DEF_ASM(x ## nl ## suffix) \ 1062 DEF_ASM(x ## ge ## suffix) \ 1063 DEF_ASM(x ## le ## suffix) \ 1064 DEF_ASM(x ## ng ## suffix) \ 1065 DEF_ASM(x ## nle ## suffix) \ 1066 DEF_ASM(x ## g ## suffix) 1067 1068 #endif /* defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 */ 907 1069 908 1070 enum tcc_token { 909 TOK_LAST = TOK_IDENT - 1 ,910 #define DEF(id, str) id,1071 TOK_LAST = TOK_IDENT - 1 1072 #define DEF(id, str) ,id 911 1073 #include "tcctok.h" 912 1074 #undef DEF 913 1075 }; 914 1076 1077 /* keywords: tok >= TOK_IDENT && tok < TOK_UIDENT */ 915 1078 #define TOK_UIDENT TOK_DEFINE 916 917 #if 0//def _WIN32918 #define snprintf _snprintf919 #define vsnprintf _vsnprintf920 #ifndef __GNUC__921 #define strtold (long double)strtod922 #define strtof (float)strtod923 #define strtoll _strtoi64924 #define strtoull _strtoui64925 #endif926 #else927 /* XXX: need to define this to use them in non ISOC99 context */928 extern float strtof (const char *__nptr, char **__endptr);929 extern long double strtold (const char *__nptr, char **__endptr);930 #endif931 932 #ifdef _WIN32933 #define IS_DIRSEP(c) (c == '/' || c == '\\')934 #define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2])))935 #define PATHCMP stricmp936 #else937 #define IS_DIRSEP(c) (c == '/')938 #define IS_ABSPATH(p) IS_DIRSEP(p[0])939 #define PATHCMP strcmp940 #endif941 942 #ifdef TCC_TARGET_PE943 #define PATHSEP ';'944 #else945 #define PATHSEP ':'946 #endif947 948 /* space exlcuding newline */949 static inline int is_space(int ch)950 {951 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';952 }953 954 static inline int isid(int c)955 {956 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';957 }958 959 static inline int isnum(int c)960 {961 return c >= '0' && c <= '9';962 }963 964 static inline int isoct(int c)965 {966 return c >= '0' && c <= '7';967 }968 969 static inline int toup(int c)970 {971 return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;972 }973 974 #ifndef PUB_FUNC975 # define PUB_FUNC976 #endif977 978 #ifdef ONE_SOURCE979 #define ST_INLN static inline980 #define ST_FUNC static981 #define ST_DATA static982 #else983 #define ST_INLN984 #define ST_FUNC985 #define ST_DATA extern986 #endif987 1079 988 1080 /* ------------ libtcc.c ------------ */ … … 995 1087 ST_DATA struct TCCState *tcc_state; 996 1088 997 #ifdef MEM_DEBUG998 ST_DATA int mem_cur_size;999 ST_DATA int mem_max_size;1000 #endif1001 1002 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */1003 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */1004 #define AFF_PREPROCESS 0x0004 /* preprocess file */1005 1006 1089 /* public functions currently used by the tcc main function */ 1007 PUB_FUNC char *pstrcpy(char *buf, int buf_size, const char *s);1008 PUB_FUNC char *pstrcat(char *buf, int buf_size, const char *s);1009 PUB_FUNC char *pstrncpy(char *out, const char *in, size_t num);1090 ST_FUNC char *pstrcpy(char *buf, int buf_size, const char *s); 1091 ST_FUNC char *pstrcat(char *buf, int buf_size, const char *s); 1092 ST_FUNC char *pstrncpy(char *out, const char *in, size_t num); 1010 1093 PUB_FUNC char *tcc_basename(const char *name); 1011 1094 PUB_FUNC char *tcc_fileextension (const char *name); 1095 1096 #ifndef MEM_DEBUG 1012 1097 PUB_FUNC void tcc_free(void *ptr); 1013 1098 PUB_FUNC void *tcc_malloc(unsigned long size); … … 1015 1100 PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size); 1016 1101 PUB_FUNC char *tcc_strdup(const char *str); 1102 #else 1103 #define tcc_free(ptr) tcc_free_debug(ptr) 1104 #define tcc_malloc(size) tcc_malloc_debug(size, __FILE__, __LINE__) 1105 #define tcc_mallocz(size) tcc_mallocz_debug(size, __FILE__, __LINE__) 1106 #define tcc_realloc(ptr,size) tcc_realloc_debug(ptr, size, __FILE__, __LINE__) 1107 #define tcc_strdup(str) tcc_strdup_debug(str, __FILE__, __LINE__) 1108 PUB_FUNC void tcc_free_debug(void *ptr); 1109 PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line); 1110 PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line); 1111 PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line); 1112 PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line); 1113 #endif 1114 1017 1115 #define free(p) use_tcc_free(p) 1018 1116 #define malloc(s) use_tcc_malloc(s) … … 1020 1118 #undef strdup 1021 1119 #define strdup(s) use_tcc_strdup(s) 1022 PUB_FUNC void tcc_mem stats(void);1120 PUB_FUNC void tcc_memcheck(void); 1023 1121 PUB_FUNC void tcc_error_noabort(const char *fmt, ...); 1024 PUB_FUNC void tcc_error(const char *fmt, ...);1122 PUB_FUNC NORETURN void tcc_error(const char *fmt, ...); 1025 1123 PUB_FUNC void tcc_warning(const char *fmt, ...); 1026 1124 1027 1125 /* other utilities */ 1028 ST_FUNC void dynarray_add(void * **ptab, int *nb_ptr, void *data);1126 ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data); 1029 1127 ST_FUNC void dynarray_reset(void *pp, int *n); 1030 ST_ FUNCvoid cstr_ccat(CString *cstr, int ch);1031 ST_FUNC void cstr_cat(CString *cstr, const char *str );1128 ST_INLN void cstr_ccat(CString *cstr, int ch); 1129 ST_FUNC void cstr_cat(CString *cstr, const char *str, int len); 1032 1130 ST_FUNC void cstr_wccat(CString *cstr, int ch); 1033 1131 ST_FUNC void cstr_new(CString *cstr); … … 1035 1133 ST_FUNC void cstr_reset(CString *cstr); 1036 1134 1037 ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);1038 ST_FUNC void section_realloc(Section *sec, unsigned long new_size);1039 ST_FUNC void *section_ptr_add(Section *sec, unsigned long size);1040 ST_FUNC void section_reserve(Section *sec, unsigned long size);1041 ST_FUNC Section *find_section(TCCState *s1, const char *name);1042 1043 ST_FUNC void put_extern_sym2(Sym *sym, Section *section, addr_t value, unsigned long size, int can_add_underscore);1044 ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size);1045 ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type);1046 1047 1135 ST_INLN void sym_free(Sym *sym); 1048 ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, longc);1136 ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c); 1049 1137 ST_FUNC Sym *sym_find2(Sym *s, int v); 1050 1138 ST_FUNC Sym *sym_push(int v, CType *type, int r, int c); 1051 ST_FUNC void sym_pop(Sym **ptop, Sym *b );1139 ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep); 1052 1140 ST_INLN Sym *struct_find(int v); 1053 1141 ST_INLN Sym *sym_find(int v); … … 1059 1147 1060 1148 ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags); 1149 /* flags: */ 1150 #define AFF_PRINT_ERROR 0x10 /* print error if file not found */ 1151 #define AFF_REFERENCED_DLL 0x20 /* load a referenced dll from another dll */ 1152 #define AFF_TYPE_BIN 0x40 /* file to add is binary */ 1153 /* s->filetype: */ 1154 #define AFF_TYPE_NONE 0 1155 #define AFF_TYPE_C 1 1156 #define AFF_TYPE_ASM 2 1157 #define AFF_TYPE_ASMPP 3 1158 #define AFF_TYPE_LIB 4 1159 /* values from tcc_object_type(...) */ 1160 #define AFF_BINTYPE_REL 1 1161 #define AFF_BINTYPE_DYN 2 1162 #define AFF_BINTYPE_AR 3 1163 #define AFF_BINTYPE_C67 4 1164 1165 1061 1166 ST_FUNC int tcc_add_crt(TCCState *s, const char *filename); 1062 1167 ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags); 1063 1064 PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time); 1065 PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv); 1168 ST_FUNC void tcc_add_pragma_libs(TCCState *s1); 1169 PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f); 1170 PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time); 1171 PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind); 1172 #ifdef _WIN32 1173 ST_FUNC char *normalize_slashes(char *path); 1174 #endif 1175 1176 /* tcc_parse_args return codes: */ 1177 #define OPT_HELP 1 1178 #define OPT_HELP2 2 1179 #define OPT_V 3 1180 #define OPT_PRINT_DIRS 4 1181 #define OPT_AR 5 1182 #define OPT_IMPDEF 6 1183 #define OPT_M32 32 1184 #define OPT_M64 64 1066 1185 1067 1186 /* ------------ tccpp.c ------------ */ … … 1091 1210 token. line feed is also 1092 1211 returned at eof */ 1093 #define PARSE_FLAG_ASM_ COMMENTS 0x0008 /* '#' can be used for line comment*/1212 #define PARSE_FLAG_ASM_FILE 0x0008 /* we processing an asm file: '#' can be used for line comment, etc. */ 1094 1213 #define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */ 1214 #define PARSE_FLAG_ACCEPT_STRAYS 0x0020 /* next() returns '\\' token */ 1215 #define PARSE_FLAG_TOK_STR 0x0040 /* return parsed strings instead of TOK_PPSTR */ 1216 1217 /* isidnum_table flags: */ 1218 #define IS_SPC 1 1219 #define IS_ID 2 1220 #define IS_NUM 4 1095 1221 1096 1222 ST_FUNC TokenSym *tok_alloc(const char *str, int len); 1097 ST_FUNC char *get_tok_str(int v, CValue *cv); 1098 ST_FUNC void save_parse_state(ParseState *s); 1099 ST_FUNC void restore_parse_state(ParseState *s); 1223 ST_FUNC const char *get_tok_str(int v, CValue *cv); 1224 ST_FUNC void begin_macro(TokenString *str, int alloc); 1225 ST_FUNC void end_macro(void); 1226 ST_FUNC int set_idnum(int c, int val); 1100 1227 ST_INLN void tok_str_new(TokenString *s); 1101 ST_FUNC void tok_str_free(int *str); 1228 ST_FUNC TokenString *tok_str_alloc(void); 1229 ST_FUNC void tok_str_free(TokenString *s); 1230 ST_FUNC void tok_str_free_str(int *str); 1102 1231 ST_FUNC void tok_str_add(TokenString *s, int t); 1103 1232 ST_FUNC void tok_str_add_tok(TokenString *s); … … 1108 1237 ST_FUNC Sym *label_find(int v); 1109 1238 ST_FUNC Sym *label_push(Sym **ptop, int v, int flags); 1110 ST_FUNC void label_pop(Sym **ptop, Sym *slast );1239 ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep); 1111 1240 ST_FUNC void parse_define(void); 1112 1241 ST_FUNC void preprocess(int is_bof); … … 1114 1243 ST_FUNC void next(void); 1115 1244 ST_INLN void unget_tok(int last_tok); 1116 ST_FUNC void preprocess_init(TCCState *s1); 1117 ST_FUNC void preprocess_new(void); 1245 ST_FUNC void preprocess_start(TCCState *s1, int is_asm); 1246 ST_FUNC void preprocess_end(TCCState *s1); 1247 ST_FUNC void tccpp_new(TCCState *s); 1248 ST_FUNC void tccpp_delete(TCCState *s); 1118 1249 ST_FUNC int tcc_preprocess(TCCState *s1); 1119 1250 ST_FUNC void skip(int c); 1120 ST_FUNC void expect(const char *msg); 1251 ST_FUNC NORETURN void expect(const char *msg); 1252 1253 /* space excluding newline */ 1254 static inline int is_space(int ch) { 1255 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r'; 1256 } 1257 static inline int isid(int c) { 1258 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; 1259 } 1260 static inline int isnum(int c) { 1261 return c >= '0' && c <= '9'; 1262 } 1263 static inline int isoct(int c) { 1264 return c >= '0' && c <= '7'; 1265 } 1266 static inline int toup(int c) { 1267 return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; 1268 } 1121 1269 1122 1270 /* ------------ tccgen.c ------------ */ 1123 1124 ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */1125 ST_DATA Section *cur_text_section; /* current section where function code is generated */1126 #ifdef CONFIG_TCC_ASM1127 ST_DATA Section *last_text_section; /* to handle .previous asm directive */1128 #endif1129 #ifdef CONFIG_TCC_BCHECK1130 /* bound check related sections */1131 ST_DATA Section *bounds_section; /* contains global data bound description */1132 ST_DATA Section *lbounds_section; /* contains local data bound description */1133 #endif1134 /* symbol sections */1135 ST_DATA Section *symtab_section, *strtab_section;1136 /* debug sections */1137 ST_DATA Section *stab_section, *stabstr_section;1138 1271 1139 1272 #define SYM_POOL_NB (8192 / sizeof(Sym)) … … 1148 1281 ST_DATA Sym *define_stack; 1149 1282 ST_DATA CType char_pointer_type, func_old_type, int_type, size_type; 1150 ST_DATA SValue __vstack[1+/*to make bcheck happy*/ VSTACK_SIZE], *vtop ;1283 ST_DATA SValue __vstack[1+/*to make bcheck happy*/ VSTACK_SIZE], *vtop, *pvtop; 1151 1284 #define vstack (__vstack + 1) 1152 1285 ST_DATA int rsym, anon_sym, ind, loc; … … 1156 1289 ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ 1157 1290 ST_DATA CType func_vt; /* current function return type (used by return instruction) */ 1291 ST_DATA int func_var; /* true if current function is variadic */ 1158 1292 ST_DATA int func_vc; 1159 1293 ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ 1160 ST_DATA char *funcname; 1294 ST_DATA const char *funcname; 1295 ST_DATA int g_debug; 1296 1297 ST_FUNC void tcc_debug_start(TCCState *s1); 1298 ST_FUNC void tcc_debug_end(TCCState *s1); 1299 ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym); 1300 ST_FUNC void tcc_debug_funcend(TCCState *s1, int size); 1301 ST_FUNC void tcc_debug_line(TCCState *s1); 1302 1303 ST_FUNC int tccgen_compile(TCCState *s1); 1304 ST_FUNC void free_inline_functions(TCCState *s); 1305 ST_FUNC void check_vstack(void); 1161 1306 1162 1307 ST_INLN int is_float(int t); 1163 1308 ST_FUNC int ieee_finite(double d); 1164 1309 ST_FUNC void test_lvalue(void); 1165 ST_FUNC void swap(int *p, int *q);1166 1310 ST_FUNC void vpushi(int v); 1311 ST_FUNC ElfSym *elfsym(Sym *); 1312 ST_FUNC void update_storage(Sym *sym); 1167 1313 ST_FUNC Sym *external_global_sym(int v, CType *type, int r); 1168 1314 ST_FUNC void vset(CType *type, int r, int v); … … 1178 1324 ST_FUNC void vpushv(SValue *v); 1179 1325 ST_FUNC void save_reg(int r); 1326 ST_FUNC void save_reg_upstack(int r, int n); 1180 1327 ST_FUNC int get_reg(int rc); 1181 1328 ST_FUNC void save_regs(int n); 1329 ST_FUNC void gaddrof(void); 1182 1330 ST_FUNC int gv(int rc); 1183 1331 ST_FUNC void gv2(int rc1, int rc2); … … 1188 1336 ST_FUNC void vstore(void); 1189 1337 ST_FUNC void inc(int post, int c); 1338 ST_FUNC void parse_mult_str (CString *astr, const char *msg); 1190 1339 ST_FUNC void parse_asm_str(CString *astr); 1191 1340 ST_FUNC int lvalue_type(int t); … … 1196 1345 ST_FUNC void gexpr(void); 1197 1346 ST_FUNC int expr_const(void); 1198 ST_FUNC void gen_inline_functions(void);1199 ST_FUNC void decl(int l);1200 1347 #if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67 1201 1348 ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size); 1349 #endif 1350 #if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE 1351 ST_FUNC int classify_x86_64_va_arg(CType *ty); 1202 1352 #endif 1203 1353 … … 1218 1368 } Stab_Sym; 1219 1369 1370 ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */ 1371 ST_DATA Section *common_section; 1372 ST_DATA Section *cur_text_section; /* current section where function code is generated */ 1373 #ifdef CONFIG_TCC_ASM 1374 ST_DATA Section *last_text_section; /* to handle .previous asm directive */ 1375 #endif 1376 #ifdef CONFIG_TCC_BCHECK 1377 /* bound check related sections */ 1378 ST_DATA Section *bounds_section; /* contains global data bound description */ 1379 ST_DATA Section *lbounds_section; /* contains local data bound description */ 1380 ST_FUNC void tccelf_bounds_new(TCCState *s); 1381 #endif 1382 /* symbol sections */ 1383 ST_DATA Section *symtab_section; 1384 /* debug sections */ 1385 ST_DATA Section *stab_section, *stabstr_section; 1386 1387 ST_FUNC void tccelf_new(TCCState *s); 1388 ST_FUNC void tccelf_delete(TCCState *s); 1389 ST_FUNC void tccelf_stab_new(TCCState *s); 1390 ST_FUNC void tccelf_begin_file(TCCState *s1); 1391 ST_FUNC void tccelf_end_file(TCCState *s1); 1392 1393 ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags); 1394 ST_FUNC void section_realloc(Section *sec, unsigned long new_size); 1395 ST_FUNC size_t section_add(Section *sec, addr_t size, int align); 1396 ST_FUNC void *section_ptr_add(Section *sec, addr_t size); 1397 ST_FUNC void section_reserve(Section *sec, unsigned long size); 1398 ST_FUNC Section *find_section(TCCState *s1, const char *name); 1220 1399 ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags); 1400 1401 ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore); 1402 ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size); 1403 #if PTR_SIZE == 4 1404 ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type); 1405 #endif 1406 ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend); 1221 1407 1222 1408 ST_FUNC int put_elf_str(Section *s, const char *sym); 1223 1409 ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); 1224 ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int sh_num, const char *name);1410 ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); 1225 1411 ST_FUNC int find_elf_sym(Section *s, const char *name); 1226 1412 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol); 1413 ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, addr_t addend); 1227 1414 1228 1415 ST_FUNC void put_stabs(const char *str, int type, int other, int desc, unsigned long value); … … 1231 1418 ST_FUNC void put_stabd(int type, int other, int desc); 1232 1419 1233 ST_FUNC void re locate_common_syms(void);1234 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve);1420 ST_FUNC void resolve_common_syms(TCCState *s1); 1421 ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve); 1235 1422 ST_FUNC void relocate_section(TCCState *s1, Section *s); 1236 1423 1237 ST_FUNC void tcc_add_linker_symbols(TCCState *s1);1424 ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h); 1238 1425 ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset); 1239 1426 ST_FUNC int tcc_load_archive(TCCState *s1, int fd); 1240 1427 ST_FUNC void tcc_add_bcheck(TCCState *s1); 1428 ST_FUNC void tcc_add_runtime(TCCState *s1); 1241 1429 1242 1430 ST_FUNC void build_got_entries(TCCState *s1); 1243 ST_FUNC void tcc_add_runtime(TCCState *s1); 1431 ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc); 1432 ST_FUNC void squeeze_multi_relocs(Section *sec, size_t oldrelocoffset); 1244 1433 1245 1434 ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err); 1246 #if def TCC_IS_NATIVE1435 #if defined TCC_IS_NATIVE || defined TCC_TARGET_PE 1247 1436 ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name); 1248 1437 #endif … … 1257 1446 #endif 1258 1447 1448 /* ------------ xxx-link.c ------------ */ 1449 1450 /* Whether to generate a GOT/PLT entry and when. NO_GOTPLT_ENTRY is first so 1451 that unknown relocation don't create a GOT or PLT entry */ 1452 enum gotplt_entry { 1453 NO_GOTPLT_ENTRY, /* never generate (eg. GLOB_DAT & JMP_SLOT relocs) */ 1454 BUILD_GOT_ONLY, /* only build GOT (eg. TPOFF relocs) */ 1455 AUTO_GOTPLT_ENTRY, /* generate if sym is UNDEF */ 1456 ALWAYS_GOTPLT_ENTRY /* always generate (eg. PLTOFF relocs) */ 1457 }; 1458 1459 ST_FUNC int code_reloc (int reloc_type); 1460 ST_FUNC int gotplt_entry_type (int reloc_type); 1461 ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr); 1462 ST_FUNC void relocate_init(Section *sr); 1463 ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val); 1464 ST_FUNC void relocate_plt(TCCState *s1); 1465 1259 1466 /* ------------ xxx-gen.c ------------ */ 1260 1467 1261 #ifdef TCC_TARGET_X86_641262 ST_DATA const int reg_classes[NB_REGS+7];1263 #else1264 1468 ST_DATA const int reg_classes[NB_REGS]; 1265 #endif1266 1469 1267 1470 ST_FUNC void gsym_addr(int t, int a); … … 1269 1472 ST_FUNC void load(int r, SValue *sv); 1270 1473 ST_FUNC void store(int r, SValue *v); 1474 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize); 1271 1475 ST_FUNC void gfunc_call(int nb_args); 1272 1476 ST_FUNC void gfunc_prolog(CType *func_type); … … 1275 1479 ST_FUNC void gjmp_addr(int a); 1276 1480 ST_FUNC int gtst(int inv, int t); 1481 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 1482 ST_FUNC void gtst_addr(int inv, int a); 1483 #else 1484 #define gtst_addr(inv, a) gsym_addr(gtst(inv, 0), a) 1485 #endif 1277 1486 ST_FUNC void gen_opi(int op); 1278 1487 ST_FUNC void gen_opf(int op); … … 1286 1495 ST_FUNC void gen_cvt_itof(int t); 1287 1496 #endif 1497 ST_FUNC void gen_vla_sp_save(int addr); 1498 ST_FUNC void gen_vla_sp_restore(int addr); 1499 ST_FUNC void gen_vla_alloc(CType *type, int align); 1500 1501 static inline uint16_t read16le(unsigned char *p) { 1502 return p[0] | (uint16_t)p[1] << 8; 1503 } 1504 static inline void write16le(unsigned char *p, uint16_t x) { 1505 p[0] = x & 255; p[1] = x >> 8 & 255; 1506 } 1507 static inline uint32_t read32le(unsigned char *p) { 1508 return read16le(p) | (uint32_t)read16le(p + 2) << 16; 1509 } 1510 static inline void write32le(unsigned char *p, uint32_t x) { 1511 write16le(p, x); write16le(p + 2, x >> 16); 1512 } 1513 static inline void add32le(unsigned char *p, int32_t x) { 1514 write32le(p, read32le(p) + x); 1515 } 1516 static inline uint64_t read64le(unsigned char *p) { 1517 return read32le(p) | (uint64_t)read32le(p + 4) << 32; 1518 } 1519 static inline void write64le(unsigned char *p, uint64_t x) { 1520 write32le(p, x); write32le(p + 4, x >> 32); 1521 } 1522 static inline void add64le(unsigned char *p, int64_t x) { 1523 write64le(p, read64le(p) + x); 1524 } 1288 1525 1289 1526 /* ------------ i386-gen.c ------------ */ 1290 1527 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 1291 1528 ST_FUNC void g(int c); 1292 ST_FUNC int oad(int c, int s);1293 1529 ST_FUNC void gen_le16(int c); 1294 1530 ST_FUNC void gen_le32(int c); … … 1306 1542 ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c); 1307 1543 ST_FUNC void gen_opl(int op); 1544 #ifdef TCC_TARGET_PE 1545 ST_FUNC void gen_vla_result(int addr); 1546 #endif 1308 1547 #endif 1309 1548 1310 1549 /* ------------ arm-gen.c ------------ */ 1311 1550 #ifdef TCC_TARGET_ARM 1312 ST_FUNC void arm_init_types(void); 1313 ST_FUNC uint32_t encbranch(int pos, int addr, int fail); 1551 #if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP) 1552 PUB_FUNC const char *default_elfinterp(struct TCCState *s); 1553 #endif 1554 ST_FUNC void arm_init(struct TCCState *s); 1314 1555 ST_FUNC void gen_cvt_itof1(int t); 1556 #endif 1557 1558 /* ------------ arm64-gen.c ------------ */ 1559 #ifdef TCC_TARGET_ARM64 1560 ST_FUNC void gen_cvt_sxtw(void); 1561 ST_FUNC void gen_opl(int op); 1562 ST_FUNC void gfunc_return(CType *func_type); 1563 ST_FUNC void gen_va_start(void); 1564 ST_FUNC void gen_va_arg(CType *t); 1565 ST_FUNC void gen_clear_cache(void); 1315 1566 #endif 1316 1567 … … 1331 1582 #ifdef CONFIG_TCC_ASM 1332 1583 ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp); 1584 ST_FUNC Sym* get_asm_sym(int name, Sym *csym); 1333 1585 ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe); 1334 1586 ST_FUNC int asm_int_expr(TCCState *s1); … … 1336 1588 /* ------------ i386-asm.c ------------ */ 1337 1589 ST_FUNC void gen_expr32(ExprValue *pe); 1590 #ifdef TCC_TARGET_X86_64 1591 ST_FUNC void gen_expr64(ExprValue *pe); 1592 #endif 1338 1593 ST_FUNC void asm_opcode(TCCState *s1, int opcode); 1594 ST_FUNC int asm_parse_regvar(int t); 1339 1595 ST_FUNC void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg); 1340 1596 ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier); … … 1348 1604 ST_FUNC int pe_output_file(TCCState * s1, const char *filename); 1349 1605 ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value); 1606 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 1350 1607 ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2); 1608 #endif 1351 1609 #ifdef TCC_TARGET_X86_64 1352 1610 ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack); 1353 1611 #endif 1354 #endif 1612 PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp); 1613 /* symbol properties stored in Elf32_Sym->st_other */ 1614 # define ST_PE_EXPORT 0x10 1615 # define ST_PE_IMPORT 0x20 1616 # define ST_PE_STDCALL 0x40 1617 #endif 1618 #define ST_ASM_SET 0x04 1355 1619 1356 1620 /* ------------ tccrun.c ----------------- */ … … 1365 1629 ST_FUNC void dlclose(void *p); 1366 1630 ST_FUNC const char *dlerror(void); 1367 ST_FUNC void *resolve_sym(TCCState *s1, const char *symbol); 1368 #elif !defined _WIN32 1369 ST_FUNC void *resolve_sym(TCCState *s1, const char *symbol); 1370 #endif 1371 1631 ST_FUNC void *dlsym(void *handle, const char *symbol); 1632 #endif 1372 1633 #ifdef CONFIG_TCC_BACKTRACE 1373 1634 ST_DATA int rt_num_callers; … … 1376 1637 ST_FUNC void tcc_set_num_callers(int n); 1377 1638 #endif 1639 ST_FUNC void tcc_run_free(TCCState *s1); 1640 #endif 1641 1642 /* ------------ tcctools.c ----------------- */ 1643 #if 0 /* included in tcc.c */ 1644 ST_FUNC int tcc_tool_ar(TCCState *s, int argc, char **argv); 1645 #ifdef TCC_TARGET_PE 1646 ST_FUNC int tcc_tool_impdef(TCCState *s, int argc, char **argv); 1647 #endif 1648 ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option); 1649 ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename); 1378 1650 #endif 1379 1651 1380 1652 /********************************************************/ 1381 1653 #undef ST_DATA 1382 #if defONE_SOURCE1654 #if ONE_SOURCE 1383 1655 #define ST_DATA static 1384 1656 #else -
EcnlProtoTool/trunk/tcc-0.9.27/tccasm.c
r321 r331 32 32 } 33 33 34 ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe); 34 static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global); 35 static Sym* asm_new_label(TCCState *s1, int label, int is_local); 36 static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value); 37 38 static Sym *asm_label_find(int v) 39 { 40 Sym *sym = sym_find(v); 41 while (sym && sym->sym_scope) 42 sym = sym->prev_tok; 43 return sym; 44 } 45 46 static Sym *asm_label_push(int v) 47 { 48 /* We always add VT_EXTERN, for sym definition that's tentative 49 (for .set, removed for real defs), for mere references it's correct 50 as is. */ 51 Sym *sym = global_identifier_push(v, VT_ASM | VT_EXTERN | VT_STATIC, 0); 52 sym->r = VT_CONST | VT_SYM; 53 return sym; 54 } 55 56 /* Return a symbol we can use inside the assembler, having name NAME. 57 Symbols from asm and C source share a namespace. If we generate 58 an asm symbol it's also a (file-global) C symbol, but it's 59 either not accessible by name (like "L.123"), or its type information 60 is such that it's not usable without a proper C declaration. 61 62 Sometimes we need symbols accessible by name from asm, which 63 are anonymous in C, in this case CSYM can be used to transfer 64 all information from that symbol to the (possibly newly created) 65 asm symbol. */ 66 ST_FUNC Sym* get_asm_sym(int name, Sym *csym) 67 { 68 Sym *sym = asm_label_find(name); 69 if (!sym) { 70 sym = asm_label_push(name); 71 if (csym) 72 sym->c = csym->c; 73 } 74 return sym; 75 } 76 77 static Sym* asm_section_sym(TCCState *s1, Section *sec) 78 { 79 char buf[100]; 80 int label = tok_alloc(buf, 81 snprintf(buf, sizeof buf, "L.%s", sec->name) 82 )->tok; 83 Sym *sym = asm_label_find(label); 84 return sym ? sym : asm_new_label1(s1, label, 1, sec->sh_num, 0); 85 } 35 86 36 87 /* We do not use the C expression parser to handle symbols. Maybe the … … 40 91 { 41 92 Sym *sym; 42 int op, n, label; 93 int op, label; 94 uint64_t n; 43 95 const char *p; 44 96 45 97 switch(tok) { 46 98 case TOK_PPNUM: 47 p = tokc. cstr->data;48 n = strtoul (p, (char **)&p, 0);99 p = tokc.str.data; 100 n = strtoull(p, (char **)&p, 0); 49 101 if (*p == 'b' || *p == 'f') { 50 102 /* backward or forward label */ 51 103 label = asm_get_local_label_name(s1, n); 52 sym = label_find(label);104 sym = asm_label_find(label); 53 105 if (*p == 'b') { 54 106 /* backward : find the last corresponding defined label */ 55 if (sym && sym->r == 0)107 if (sym && (!sym->c || elfsym(sym)->st_shndx == SHN_UNDEF)) 56 108 sym = sym->prev_tok; 57 109 if (!sym) … … 59 111 } else { 60 112 /* forward */ 61 if (!sym || sym->r) {113 if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) { 62 114 /* if the last label is defined, then define a new one */ 63 sym = label_push(&s1->asm_labels, label, 0); 64 sym->type.t = VT_STATIC | VT_VOID; 115 sym = asm_label_push(label); 65 116 } 66 117 } 67 pe->v = 0; 68 pe->sym = sym; 118 pe->v = 0; 119 pe->sym = sym; 120 pe->pcrel = 0; 69 121 } else if (*p == '\0') { 70 122 pe->v = n; 71 123 pe->sym = NULL; 124 pe->pcrel = 0; 72 125 } else { 73 126 tcc_error("invalid number syntax"); … … 95 148 pe->v = tokc.i; 96 149 pe->sym = NULL; 150 pe->pcrel = 0; 97 151 next(); 98 152 break; … … 102 156 skip(')'); 103 157 break; 158 case '.': 159 pe->v = ind; 160 pe->sym = asm_section_sym(s1, cur_text_section); 161 pe->pcrel = 0; 162 next(); 163 break; 104 164 default: 105 165 if (tok >= TOK_IDENT) { 166 ElfSym *esym; 106 167 /* label case : if the label was not found, add one */ 107 sym = label_find(tok); 108 if (!sym) { 109 sym = label_push(&s1->asm_labels, tok, 0); 110 /* NOTE: by default, the symbol is global */ 111 sym->type.t = VT_VOID; 112 } 113 if (sym->r == SHN_ABS) { 168 sym = get_asm_sym(tok, NULL); 169 esym = elfsym(sym); 170 if (esym && esym->st_shndx == SHN_ABS) { 114 171 /* if absolute symbol, no need to put a symbol value */ 115 pe->v = sym->jnext;172 pe->v = esym->st_value; 116 173 pe->sym = NULL; 174 pe->pcrel = 0; 117 175 } else { 118 176 pe->v = 0; 119 177 pe->sym = sym; 178 pe->pcrel = 0; 120 179 } 121 180 next(); … … 220 279 /* NOTE: we are less powerful than gas in that case 221 280 because we store only one symbol in the expression */ 222 if (!pe->sym && !e2.sym) { 223 /* OK */ 224 } else if (pe->sym && !e2.sym) { 225 /* OK */ 226 } else if (pe->sym && e2.sym) { 227 if (pe->sym == e2.sym) { 228 /* OK */ 229 } else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) { 230 /* we also accept defined symbols in the same section */ 231 pe->v += pe->sym->jnext - e2.sym->jnext; 232 } else { 233 goto cannot_relocate; 234 } 235 pe->sym = NULL; /* same symbols can be substracted to NULL */ 236 } else { 237 cannot_relocate: 238 tcc_error("invalid operation with label"); 239 } 240 } 281 if (!e2.sym) { 282 /* OK */ 283 } else if (pe->sym == e2.sym) { 284 /* OK */ 285 pe->sym = NULL; /* same symbols can be subtracted to NULL */ 286 } else { 287 ElfSym *esym1, *esym2; 288 esym1 = elfsym(pe->sym); 289 esym2 = elfsym(e2.sym); 290 if (esym1 && esym1->st_shndx == esym2->st_shndx 291 && esym1->st_shndx != SHN_UNDEF) { 292 /* we also accept defined symbols in the same section */ 293 pe->v += esym1->st_value - esym2->st_value; 294 pe->sym = NULL; 295 } else if (esym2->st_shndx == cur_text_section->sh_num) { 296 /* When subtracting a defined symbol in current section 297 this actually makes the value PC-relative. */ 298 pe->v -= esym2->st_value - ind - 4; 299 pe->pcrel = 1; 300 e2.sym = NULL; 301 } else { 302 cannot_relocate: 303 tcc_error("invalid operation with label"); 304 } 305 } 306 } 307 } 308 } 309 310 static inline void asm_expr_cmp(TCCState *s1, ExprValue *pe) 311 { 312 int op; 313 ExprValue e2; 314 315 asm_expr_sum(s1, pe); 316 for(;;) { 317 op = tok; 318 if (op != TOK_EQ && op != TOK_NE 319 && (op > TOK_GT || op < TOK_ULE)) 320 break; 321 next(); 322 asm_expr_sum(s1, &e2); 323 if (pe->sym || e2.sym) 324 tcc_error("invalid operation with label"); 325 switch(op) { 326 case TOK_EQ: 327 pe->v = pe->v == e2.v; 328 break; 329 case TOK_NE: 330 pe->v = pe->v != e2.v; 331 break; 332 case TOK_LT: 333 pe->v = (int64_t)pe->v < (int64_t)e2.v; 334 break; 335 case TOK_GE: 336 pe->v = (int64_t)pe->v >= (int64_t)e2.v; 337 break; 338 case TOK_LE: 339 pe->v = (int64_t)pe->v <= (int64_t)e2.v; 340 break; 341 case TOK_GT: 342 pe->v = (int64_t)pe->v > (int64_t)e2.v; 343 break; 344 default: 345 break; 346 } 347 /* GAS compare results are -1/0 not 1/0. */ 348 pe->v = -(int64_t)pe->v; 241 349 } 242 350 } … … 244 352 ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe) 245 353 { 246 asm_expr_ sum(s1, pe);354 asm_expr_cmp(s1, pe); 247 355 } 248 356 … … 256 364 } 257 365 258 /* NOTE: the same name space as C labels is used to avoid using too 259 much memory when storing labels in TokenStrings */ 260 static void asm_new_label1(TCCState *s1, int label, int is_local, 366 static Sym* asm_new_label1(TCCState *s1, int label, int is_local, 261 367 int sh_num, int value) 262 368 { 263 369 Sym *sym; 264 265 sym = label_find(label); 370 ElfSym *esym; 371 372 sym = asm_label_find(label); 266 373 if (sym) { 267 if (sym->r) { 374 esym = elfsym(sym); 375 /* A VT_EXTERN symbol, even if it has a section is considered 376 overridable. This is how we "define" .set targets. Real 377 definitions won't have VT_EXTERN set. */ 378 if (esym && esym->st_shndx != SHN_UNDEF) { 268 379 /* the label is already defined */ 269 if (!is_local) { 270 tcc_error("assembler label '%s' already defined", 271 get_tok_str(label, NULL)); 272 } else { 273 /* redefinition of local labels is possible */ 380 if (IS_ASM_SYM(sym) 381 && (is_local == 1 || (sym->type.t & VT_EXTERN))) 274 382 goto new_label; 275 } 383 if (!(sym->type.t & VT_EXTERN)) 384 tcc_error("assembler label '%s' already defined", 385 get_tok_str(label, NULL)); 276 386 } 277 387 } else { 278 388 new_label: 279 sym = label_push(&s1->asm_labels, label, 0); 280 sym->type.t = VT_STATIC | VT_VOID; 281 } 282 sym->r = sh_num; 283 sym->jnext = value; 284 } 285 286 static void asm_new_label(TCCState *s1, int label, int is_local) 287 { 288 asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind); 289 } 290 291 static void asm_free_labels(TCCState *st) 292 { 293 Sym *s, *s1; 294 Section *sec; 295 296 for(s = st->asm_labels; s != NULL; s = s1) { 297 s1 = s->prev; 298 /* define symbol value in object file */ 299 if (s->r) { 300 if (s->r == SHN_ABS) 301 sec = SECTION_ABS; 302 else 303 sec = st->sections[s->r]; 304 put_extern_sym2(s, sec, s->jnext, 0, 0); 305 } 306 /* remove label */ 307 table_ident[s->v - TOK_IDENT]->sym_label = NULL; 308 sym_free(s); 309 } 310 st->asm_labels = NULL; 389 sym = asm_label_push(label); 390 } 391 if (!sym->c) 392 put_extern_sym2(sym, SHN_UNDEF, 0, 0, 0); 393 esym = elfsym(sym); 394 esym->st_shndx = sh_num; 395 esym->st_value = value; 396 if (is_local != 2) 397 sym->type.t &= ~VT_EXTERN; 398 return sym; 399 } 400 401 static Sym* asm_new_label(TCCState *s1, int label, int is_local) 402 { 403 return asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind); 404 } 405 406 /* Set the value of LABEL to that of some expression (possibly 407 involving other symbols). LABEL can be overwritten later still. */ 408 static Sym* set_symbol(TCCState *s1, int label) 409 { 410 long n; 411 ExprValue e; 412 Sym *sym; 413 ElfSym *esym; 414 next(); 415 asm_expr(s1, &e); 416 n = e.v; 417 esym = elfsym(e.sym); 418 if (esym) 419 n += esym->st_value; 420 sym = asm_new_label1(s1, label, 2, esym ? esym->st_shndx : SHN_ABS, n); 421 elfsym(sym)->st_other |= ST_ASM_SET; 422 return sym; 311 423 } 312 424 … … 325 437 } 326 438 327 static void asm_parse_directive(TCCState *s1) 439 static void push_section(TCCState *s1, const char *name) 440 { 441 Section *sec = find_section(s1, name); 442 sec->prev = cur_text_section; 443 use_section1(s1, sec); 444 } 445 446 static void pop_section(TCCState *s1) 447 { 448 Section *prev = cur_text_section->prev; 449 if (!prev) 450 tcc_error(".popsection without .pushsection"); 451 cur_text_section->prev = NULL; 452 use_section1(s1, prev); 453 } 454 455 static void asm_parse_directive(TCCState *s1, int global) 328 456 { 329 457 int n, offset, v, size, tok1; … … 332 460 333 461 /* assembler directive */ 334 next();335 462 sec = cur_text_section; 336 463 switch(tok) { 337 case TOK_ASM_align: 338 case TOK_ASM_skip: 339 case TOK_ASM_space: 464 case TOK_ASMDIR_align: 465 case TOK_ASMDIR_balign: 466 case TOK_ASMDIR_p2align: 467 case TOK_ASMDIR_skip: 468 case TOK_ASMDIR_space: 340 469 tok1 = tok; 341 470 next(); 342 471 n = asm_int_expr(s1); 343 if (tok1 == TOK_ASM_align) { 472 if (tok1 == TOK_ASMDIR_p2align) 473 { 474 if (n < 0 || n > 30) 475 tcc_error("invalid p2align, must be between 0 and 30"); 476 n = 1 << n; 477 tok1 = TOK_ASMDIR_align; 478 } 479 if (tok1 == TOK_ASMDIR_align || tok1 == TOK_ASMDIR_balign) { 344 480 if (n < 0 || (n & (n-1)) != 0) 345 481 tcc_error("alignment must be a positive power of two"); … … 350 486 sec->sh_addralign = n; 351 487 } else { 488 if (n < 0) 489 n = 0; 352 490 size = n; 353 491 } … … 365 503 ind += size; 366 504 break; 367 case TOK_ASM_quad: 505 case TOK_ASMDIR_quad: 506 #ifdef TCC_TARGET_X86_64 507 size = 8; 508 goto asm_data; 509 #else 368 510 next(); 369 511 for(;;) { … … 371 513 const char *p; 372 514 373 p = tokc. cstr->data;515 p = tokc.str.data; 374 516 if (tok != TOK_PPNUM) { 375 517 error_constant: … … 392 534 } 393 535 break; 394 case TOK_ASM_byte: 536 #endif 537 case TOK_ASMDIR_byte: 395 538 size = 1; 396 539 goto asm_data; 397 case TOK_ASM _word:398 case TOK_ SHORT:540 case TOK_ASMDIR_word: 541 case TOK_ASMDIR_short: 399 542 size = 2; 400 543 goto asm_data; 401 case TOK_ LONG:402 case TOK_ INT:544 case TOK_ASMDIR_long: 545 case TOK_ASMDIR_int: 403 546 size = 4; 404 547 asm_data: … … 410 553 if (size == 4) { 411 554 gen_expr32(&e); 555 #ifdef TCC_TARGET_X86_64 556 } else if (size == 8) { 557 gen_expr64(&e); 558 #endif 412 559 } else { 413 560 if (e.sym) … … 426 573 } 427 574 break; 428 case TOK_ASM _fill:575 case TOK_ASMDIR_fill: 429 576 { 430 577 int repeat, size, val, i, j; … … 468 615 } 469 616 break; 470 case TOK_ASM_org: 617 case TOK_ASMDIR_rept: 618 { 619 int repeat; 620 TokenString *init_str; 621 next(); 622 repeat = asm_int_expr(s1); 623 init_str = tok_str_alloc(); 624 while (next(), tok != TOK_ASMDIR_endr) { 625 if (tok == CH_EOF) 626 tcc_error("we at end of file, .endr not found"); 627 tok_str_add_tok(init_str); 628 } 629 tok_str_add(init_str, -1); 630 tok_str_add(init_str, 0); 631 begin_macro(init_str, 1); 632 while (repeat-- > 0) { 633 tcc_assemble_internal(s1, (parse_flags & PARSE_FLAG_PREPROCESS), 634 global); 635 macro_ptr = init_str->str; 636 } 637 end_macro(); 638 next(); 639 break; 640 } 641 case TOK_ASMDIR_org: 471 642 { 472 643 unsigned long n; 473 next(); 474 /* XXX: handle section symbols too */ 475 n = asm_int_expr(s1); 644 ExprValue e; 645 ElfSym *esym; 646 next(); 647 asm_expr(s1, &e); 648 n = e.v; 649 esym = elfsym(e.sym); 650 if (esym) { 651 if (esym->st_shndx != cur_text_section->sh_num) 652 expect("constant or same-section symbol"); 653 n += esym->st_value; 654 } 476 655 if (n < ind) 477 656 tcc_error("attempt to .org backwards"); … … 481 660 } 482 661 break; 483 case TOK_ASM_globl: 484 case TOK_ASM_global: 485 case TOK_ASM_weak: 486 tok1 = tok; 662 case TOK_ASMDIR_set: 663 next(); 664 tok1 = tok; 665 next(); 666 /* Also accept '.set stuff', but don't do anything with this. 667 It's used in GAS to set various features like '.set mips16'. */ 668 if (tok == ',') 669 set_symbol(s1, tok1); 670 break; 671 case TOK_ASMDIR_globl: 672 case TOK_ASMDIR_global: 673 case TOK_ASMDIR_weak: 674 case TOK_ASMDIR_hidden: 675 tok1 = tok; 487 676 do { 488 677 Sym *sym; 489 490 next(); 491 sym = label_find(tok); 492 if (!sym) { 493 sym = label_push(&s1->asm_labels, tok, 0); 494 sym->type.t = VT_VOID; 495 } 496 sym->type.t &= ~VT_STATIC; 497 if (tok1 == TOK_ASM_weak) 498 sym->type.t |= VT_WEAK; 678 next(); 679 sym = get_asm_sym(tok, NULL); 680 if (tok1 != TOK_ASMDIR_hidden) 681 sym->type.t &= ~VT_STATIC; 682 if (tok1 == TOK_ASMDIR_weak) 683 sym->a.weak = 1; 684 else if (tok1 == TOK_ASMDIR_hidden) 685 sym->a.visibility = STV_HIDDEN; 686 update_storage(sym); 499 687 next(); 500 688 } while (tok == ','); 501 689 break; 502 case TOK_ASM _string:503 case TOK_ASM _ascii:504 case TOK_ASM _asciz:690 case TOK_ASMDIR_string: 691 case TOK_ASMDIR_ascii: 692 case TOK_ASMDIR_asciz: 505 693 { 506 694 const uint8_t *p; … … 512 700 if (tok != TOK_STR) 513 701 expect("string constant"); 514 p = tokc. cstr->data;515 size = tokc. cstr->size;516 if (t == TOK_ASM _ascii && size > 0)702 p = tokc.str.data; 703 size = tokc.str.size; 704 if (t == TOK_ASMDIR_ascii && size > 0) 517 705 size--; 518 706 for(i = 0; i < size; i++) … … 527 715 } 528 716 break; 529 case TOK_ASM _text:530 case TOK_ASM _data:531 case TOK_ASM _bss:717 case TOK_ASMDIR_text: 718 case TOK_ASMDIR_data: 719 case TOK_ASMDIR_bss: 532 720 { 533 721 char sname[64]; … … 539 727 next(); 540 728 } 541 sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n); 729 if (n) 730 sprintf(sname, "%s%d", get_tok_str(tok1, NULL), n); 731 else 732 sprintf(sname, "%s", get_tok_str(tok1, NULL)); 542 733 use_section(s1, sname); 543 734 } 544 735 break; 545 case TOK_ASM _file:736 case TOK_ASMDIR_file: 546 737 { 547 738 char filename[512]; … … 551 742 552 743 if (tok == TOK_STR) 553 pstrcat(filename, sizeof(filename), tokc. cstr->data);744 pstrcat(filename, sizeof(filename), tokc.str.data); 554 745 else 555 746 pstrcat(filename, sizeof(filename), get_tok_str(tok, NULL)); … … 561 752 } 562 753 break; 563 case TOK_ASM _ident:754 case TOK_ASMDIR_ident: 564 755 { 565 756 char ident[256]; … … 569 760 570 761 if (tok == TOK_STR) 571 pstrcat(ident, sizeof(ident), tokc. cstr->data);762 pstrcat(ident, sizeof(ident), tokc.str.data); 572 763 else 573 764 pstrcat(ident, sizeof(ident), get_tok_str(tok, NULL)); … … 579 770 } 580 771 break; 581 case TOK_ASM _size:772 case TOK_ASMDIR_size: 582 773 { 583 774 Sym *sym; 584 775 585 776 next(); 586 sym = label_find(tok);777 sym = asm_label_find(tok); 587 778 if (!sym) { 588 779 tcc_error("label not found: %s", get_tok_str(tok, NULL)); 589 780 } 590 781 591 next();592 skip(',');593 782 /* XXX .size name,label2-label1 */ 594 783 if (s1->warn_unsupported) 595 784 tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL)); 596 785 597 while (tok != '\n' && tok != CH_EOF) { 786 next(); 787 skip(','); 788 while (tok != TOK_LINEFEED && tok != ';' && tok != CH_EOF) { 598 789 next(); 599 790 } 600 791 } 601 792 break; 602 case TOK_ASM _type:793 case TOK_ASMDIR_type: 603 794 { 604 795 Sym *sym; … … 606 797 607 798 next(); 608 sym = label_find(tok); 609 if (!sym) { 610 sym = label_push(&s1->asm_labels, tok, 0); 611 sym->type.t = VT_VOID; 612 } 613 799 sym = get_asm_sym(tok, NULL); 614 800 next(); 615 801 skip(','); 616 802 if (tok == TOK_STR) { 617 newtype = tokc. cstr->data;803 newtype = tokc.str.data; 618 804 } else { 619 805 if (tok == '@' || tok == '%') 620 skip(tok);806 next(); 621 807 newtype = get_tok_str(tok, NULL); 622 808 } 623 809 624 810 if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) { 625 sym->type.t = VT_FUNC;811 sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC; 626 812 } 627 813 else if (s1->warn_unsupported) … … 632 818 } 633 819 break; 634 case TOK_SECTION1: 820 case TOK_ASMDIR_pushsection: 821 case TOK_ASMDIR_section: 635 822 { 636 823 char sname[256]; 637 824 int old_nb_section = s1->nb_sections; 825 826 tok1 = tok; 638 827 /* XXX: support more options */ 639 828 next(); … … 641 830 while (tok != ';' && tok != TOK_LINEFEED && tok != ',') { 642 831 if (tok == TOK_STR) 643 pstrcat(sname, sizeof(sname), tokc. cstr->data);832 pstrcat(sname, sizeof(sname), tokc.str.data); 644 833 else 645 834 pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL)); … … 652 841 expect("string constant"); 653 842 next(); 843 if (tok == ',') { 844 next(); 845 if (tok == '@' || tok == '%') 846 next(); 847 next(); 848 } 654 849 } 655 850 last_text_section = cur_text_section; 656 use_section(s1, sname); 657 } 658 break; 659 case TOK_ASM_previous: 851 if (tok1 == TOK_ASMDIR_section) 852 use_section(s1, sname); 853 else 854 push_section(s1, sname); 855 /* If we just allocated a new section reset its alignment to 856 1. new_section normally acts for GCC compatibility and 857 sets alignment to PTR_SIZE. The assembler behaves different. */ 858 if (old_nb_section != s1->nb_sections) 859 cur_text_section->sh_addralign = 1; 860 } 861 break; 862 case TOK_ASMDIR_previous: 660 863 { 661 864 Section *sec; … … 668 871 } 669 872 break; 873 case TOK_ASMDIR_popsection: 874 next(); 875 pop_section(s1); 876 break; 670 877 #ifdef TCC_TARGET_I386 671 case TOK_ASM _code16:878 case TOK_ASMDIR_code16: 672 879 { 673 880 next(); … … 675 882 } 676 883 break; 677 case TOK_ASM _code32:884 case TOK_ASMDIR_code32: 678 885 { 679 886 next(); … … 684 891 #ifdef TCC_TARGET_X86_64 685 892 /* added for compatibility with GAS */ 686 case TOK_ASM _code64:893 case TOK_ASMDIR_code64: 687 894 next(); 688 895 break; … … 696 903 697 904 /* assemble a file */ 698 static int tcc_assemble_internal(TCCState *s1, int do_preprocess )905 static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global) 699 906 { 700 907 int opcode; 701 702 #if 0 703 /* print stats about opcodes */ 704 { 705 const ASMInstr *pa; 706 int freq[4]; 707 int op_vals[500]; 708 int nb_op_vals, i, j; 709 710 nb_op_vals = 0; 711 memset(freq, 0, sizeof(freq)); 712 for(pa = asm_instrs; pa->sym != 0; pa++) { 713 freq[pa->nb_ops]++; 714 for(i=0;i<pa->nb_ops;i++) { 715 for(j=0;j<nb_op_vals;j++) { 716 if (pa->op_type[i] == op_vals[j]) 717 goto found; 718 } 719 op_vals[nb_op_vals++] = pa->op_type[i]; 720 found: ; 721 } 722 } 723 for(i=0;i<nb_op_vals;i++) { 724 int v = op_vals[i]; 725 if ((v & (v - 1)) != 0) 726 printf("%3d: %08x\n", i, v); 727 } 728 printf("size=%d nb=%d f0=%d f1=%d f2=%d f3=%d\n", 729 sizeof(asm_instrs), sizeof(asm_instrs) / sizeof(ASMInstr), 730 freq[0], freq[1], freq[2], freq[3]); 731 } 732 #endif 733 734 /* XXX: undefine C labels */ 735 736 ch = file->buf_ptr[0]; 737 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; 738 parse_flags = PARSE_FLAG_ASM_COMMENTS; 908 int saved_parse_flags = parse_flags; 909 910 parse_flags = PARSE_FLAG_ASM_FILE | PARSE_FLAG_TOK_STR; 739 911 if (do_preprocess) 740 912 parse_flags |= PARSE_FLAG_PREPROCESS; 741 next();742 913 for(;;) { 914 next(); 743 915 if (tok == TOK_EOF) 744 916 break; 917 /* generate line number info */ 918 if (global && s1->do_debug) 919 tcc_debug_line(s1); 745 920 parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */ 746 921 redo: … … 749 924 while (tok != TOK_LINEFEED) 750 925 next(); 751 } else if (tok == '.') {752 asm_parse_directive(s1 );926 } else if (tok >= TOK_ASMDIR_FIRST && tok <= TOK_ASMDIR_LAST) { 927 asm_parse_directive(s1, global); 753 928 } else if (tok == TOK_PPNUM) { 754 929 const char *p; 755 930 int n; 756 p = tokc. cstr->data;931 p = tokc.str.data; 757 932 n = strtoul(p, (char **)&p, 10); 758 933 if (*p != '\0') … … 773 948 goto redo; 774 949 } else if (tok == '=') { 775 int n; 776 next(); 777 n = asm_int_expr(s1); 778 asm_new_label1(s1, opcode, 0, SHN_ABS, n); 950 set_symbol(s1, opcode); 779 951 goto redo; 780 952 } else { … … 783 955 } 784 956 /* end of line */ 785 if (tok != ';' && tok != TOK_LINEFEED) {957 if (tok != ';' && tok != TOK_LINEFEED) 786 958 expect("end of line"); 787 }788 959 parse_flags &= ~PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */ 789 next(); 790 } 791 792 asm_free_labels(s1); 793 960 } 961 962 parse_flags = saved_parse_flags; 794 963 return 0; 795 964 } … … 798 967 ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess) 799 968 { 800 Sym *define_start;801 969 int ret; 802 803 preprocess_init(s1); 804 970 tcc_debug_start(s1); 805 971 /* default section is text */ 806 972 cur_text_section = text_section; 807 973 ind = cur_text_section->data_offset; 808 809 define_start = define_stack; 810 811 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL 812 symbols can be safely used */ 813 put_elf_sym(symtab_section, 0, 0, 814 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, 815 SHN_ABS, file->filename); 816 817 ret = tcc_assemble_internal(s1, do_preprocess); 818 974 nocode_wanted = 0; 975 ret = tcc_assemble_internal(s1, do_preprocess, 1); 819 976 cur_text_section->data_offset = ind; 820 821 free_defines(define_start); 822 977 tcc_debug_end(s1); 823 978 return ret; 824 979 } … … 830 985 C preprocessing. NOTE: str is modified by modifying the '\0' at the 831 986 end */ 832 static void tcc_assemble_inline(TCCState *s1, char *str, int len) 833 { 834 int saved_parse_flags; 835 const int *saved_macro_ptr; 836 837 saved_parse_flags = parse_flags; 838 saved_macro_ptr = macro_ptr; 987 static void tcc_assemble_inline(TCCState *s1, char *str, int len, int global) 988 { 989 const int *saved_macro_ptr = macro_ptr; 990 int dotid = set_idnum('.', IS_ID); 839 991 840 992 tcc_open_bf(s1, ":asm:", len); 841 993 memcpy(file->buffer, str, len); 842 843 994 macro_ptr = NULL; 844 tcc_assemble_internal(s1, 0 );995 tcc_assemble_internal(s1, 0, global); 845 996 tcc_close(); 846 997 847 parse_flags = saved_parse_flags;998 set_idnum('.', dotid); 848 999 macro_ptr = saved_macro_ptr; 849 1000 } … … 891 1042 892 1043 static void subst_asm_operands(ASMOperand *operands, int nb_operands, 893 int nb_outputs,894 1044 CString *out_str, CString *in_str) 895 1045 { … … 910 1060 modifier = 0; 911 1061 if (*str == 'c' || *str == 'n' || 912 *str == 'b' || *str == 'w' || *str == 'h') 1062 *str == 'b' || *str == 'w' || *str == 'h' || *str == 'k' || 1063 *str == 'q' || 1064 /* P in GCC would add "@PLT" to symbol refs in PIC mode, 1065 and make literal operands not be decorated with '$'. */ 1066 *str == 'P') 913 1067 modifier = *str++; 914 1068 index = find_constraint(operands, nb_operands, str, &str); … … 942 1096 nb_operands = *nb_operands_ptr; 943 1097 for(;;) { 1098 CString astr; 944 1099 if (nb_operands >= MAX_ASM_OPERANDS) 945 1100 tcc_error("too many asm operands"); … … 954 1109 skip(']'); 955 1110 } 956 if (tok != TOK_STR) 957 expect("string constant"); 958 op->constraint = tcc_malloc(tokc.cstr->size); 959 strcpy(op->constraint, tokc.cstr->data); 960 next(); 1111 parse_mult_str(&astr, "string constant"); 1112 op->constraint = tcc_malloc(astr.size); 1113 strcpy(op->constraint, astr.data); 1114 cstr_free(&astr); 961 1115 skip('('); 962 1116 gexpr(); 963 1117 if (is_output) { 964 test_lvalue(); 1118 if (!(vtop->type.t & VT_ARRAY)) 1119 test_lvalue(); 965 1120 } else { 966 1121 /* we want to avoid LLOCAL case, except when the 'm' … … 1024 1179 if (tok != TOK_STR) 1025 1180 expect("string constant"); 1026 asm_clobber(clobber_regs, tokc. cstr->data);1181 asm_clobber(clobber_regs, tokc.str.data); 1027 1182 next(); 1028 1183 if (tok == ',') { … … 1055 1210 #endif 1056 1211 if (must_subst) { 1057 subst_asm_operands(operands, nb_operands, nb_outputs,&astr1, &astr);1212 subst_asm_operands(operands, nb_operands, &astr1, &astr); 1058 1213 cstr_free(&astr); 1059 1214 } else { … … 1069 1224 1070 1225 /* assemble the string with tcc internal assembler */ 1071 tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1 );1226 tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1, 0); 1072 1227 1073 1228 /* restore the current C token */ … … 1091 1246 { 1092 1247 CString astr; 1093 1248 int saved_nocode_wanted = nocode_wanted; 1249 1250 /* Global asm blocks are always emitted. */ 1251 nocode_wanted = 0; 1094 1252 next(); 1095 1253 parse_asm_str(&astr); … … 1107 1265 1108 1266 /* assemble the string with tcc internal assembler */ 1109 tcc_assemble_inline(tcc_state, astr.data, astr.size - 1 );1267 tcc_assemble_inline(tcc_state, astr.data, astr.size - 1, 1); 1110 1268 1111 1269 cur_text_section->data_offset = ind; … … 1115 1273 1116 1274 cstr_free(&astr); 1275 nocode_wanted = saved_nocode_wanted; 1117 1276 } 1118 1277 #endif /* CONFIG_TCC_ASM */ -
EcnlProtoTool/trunk/tcc-0.9.27/tccelf.c
r321 r331 1 1 /* 2 2 * ELF file handling for TCC 3 * 3 * 4 4 * Copyright (c) 2001-2004 Fabrice Bellard 5 5 * … … 21 21 #include "tcc.h" 22 22 23 /* Define this to get some debug output during relocation processing. */ 24 #undef DEBUG_RELOC 25 26 /********************************************************/ 27 /* global variables */ 28 29 ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */ 30 ST_DATA Section *common_section; 31 ST_DATA Section *cur_text_section; /* current section where function code is generated */ 32 #ifdef CONFIG_TCC_ASM 33 ST_DATA Section *last_text_section; /* to handle .previous asm directive */ 34 #endif 35 #ifdef CONFIG_TCC_BCHECK 36 /* bound check related sections */ 37 ST_DATA Section *bounds_section; /* contains global data bound description */ 38 ST_DATA Section *lbounds_section; /* contains local data bound description */ 39 #endif 40 /* symbol sections */ 41 ST_DATA Section *symtab_section; 42 /* debug sections */ 43 ST_DATA Section *stab_section, *stabstr_section; 44 45 /* XXX: avoid static variable */ 23 46 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */ 47 48 /* special flag to indicate that the section should not be linked to the other ones */ 49 #define SHF_PRIVATE 0x80000000 50 /* section is dynsymtab_section */ 51 #define SHF_DYNSYM 0x40000000 52 53 /* ------------------------------------------------------------------------- */ 54 55 ST_FUNC void tccelf_new(TCCState *s) 56 { 57 /* no section zero */ 58 dynarray_add(&s->sections, &s->nb_sections, NULL); 59 60 /* create standard sections */ 61 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); 62 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); 63 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); 64 common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); 65 common_section->sh_num = SHN_COMMON; 66 67 /* symbols are always generated for linking stage */ 68 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0, 69 ".strtab", 70 ".hashtab", SHF_PRIVATE); 71 s->symtab = symtab_section; 72 73 /* private symbol table for dynamic symbols */ 74 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE|SHF_DYNSYM, 75 ".dynstrtab", 76 ".dynhashtab", SHF_PRIVATE); 77 get_sym_attr(s, 0, 1); 78 } 79 80 #ifdef CONFIG_TCC_BCHECK 81 ST_FUNC void tccelf_bounds_new(TCCState *s) 82 { 83 /* create bounds sections */ 84 bounds_section = new_section(s, ".bounds", 85 SHT_PROGBITS, SHF_ALLOC); 86 lbounds_section = new_section(s, ".lbounds", 87 SHT_PROGBITS, SHF_ALLOC); 88 } 89 #endif 90 91 ST_FUNC void tccelf_stab_new(TCCState *s) 92 { 93 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0); 94 stab_section->sh_entsize = sizeof(Stab_Sym); 95 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0); 96 put_elf_str(stabstr_section, ""); 97 stab_section->link = stabstr_section; 98 /* put first entry */ 99 put_stabs("", 0, 0, 0, 0); 100 } 101 102 static void free_section(Section *s) 103 { 104 tcc_free(s->data); 105 } 106 107 ST_FUNC void tccelf_delete(TCCState *s1) 108 { 109 int i; 110 111 /* free all sections */ 112 for(i = 1; i < s1->nb_sections; i++) 113 free_section(s1->sections[i]); 114 dynarray_reset(&s1->sections, &s1->nb_sections); 115 116 for(i = 0; i < s1->nb_priv_sections; i++) 117 free_section(s1->priv_sections[i]); 118 dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections); 119 120 /* free any loaded DLLs */ 121 #ifdef TCC_IS_NATIVE 122 for ( i = 0; i < s1->nb_loaded_dlls; i++) { 123 DLLReference *ref = s1->loaded_dlls[i]; 124 if ( ref->handle ) 125 # ifdef _WIN32 126 FreeLibrary((HMODULE)ref->handle); 127 # else 128 dlclose(ref->handle); 129 # endif 130 } 131 #endif 132 /* free loaded dlls array */ 133 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); 134 tcc_free(s1->sym_attrs); 135 136 symtab_section = NULL; /* for tccrun.c:rt_printline() */ 137 } 138 139 /* save section data state */ 140 ST_FUNC void tccelf_begin_file(TCCState *s1) 141 { 142 Section *s; int i; 143 for (i = 1; i < s1->nb_sections; i++) { 144 s = s1->sections[i]; 145 s->sh_offset = s->data_offset; 146 } 147 /* disable symbol hashing during compilation */ 148 s = s1->symtab, s->reloc = s->hash, s->hash = NULL; 149 #if defined TCC_TARGET_X86_64 && defined TCC_TARGET_PE 150 s1->uw_sym = 0; 151 #endif 152 } 153 154 /* At the end of compilation, convert any UNDEF syms to global, and merge 155 with previously existing symbols */ 156 ST_FUNC void tccelf_end_file(TCCState *s1) 157 { 158 Section *s = s1->symtab; 159 int first_sym, nb_syms, *tr, i; 160 161 first_sym = s->sh_offset / sizeof (ElfSym); 162 nb_syms = s->data_offset / sizeof (ElfSym) - first_sym; 163 s->data_offset = s->sh_offset; 164 s->link->data_offset = s->link->sh_offset; 165 s->hash = s->reloc, s->reloc = NULL; 166 tr = tcc_mallocz(nb_syms * sizeof *tr); 167 168 for (i = 0; i < nb_syms; ++i) { 169 ElfSym *sym = (ElfSym*)s->data + first_sym + i; 170 if (sym->st_shndx == SHN_UNDEF 171 && ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) 172 sym->st_info = ELFW(ST_INFO)(STB_GLOBAL, ELFW(ST_TYPE)(sym->st_info)); 173 tr[i] = set_elf_sym(s, sym->st_value, sym->st_size, sym->st_info, 174 sym->st_other, sym->st_shndx, s->link->data + sym->st_name); 175 } 176 /* now update relocations */ 177 for (i = 1; i < s1->nb_sections; i++) { 178 Section *sr = s1->sections[i]; 179 if (sr->sh_type == SHT_RELX && sr->link == s) { 180 ElfW_Rel *rel = (ElfW_Rel*)(sr->data + sr->sh_offset); 181 ElfW_Rel *rel_end = (ElfW_Rel*)(sr->data + sr->data_offset); 182 for (; rel < rel_end; ++rel) { 183 int n = ELFW(R_SYM)(rel->r_info) - first_sym; 184 //if (n < 0) tcc_error("internal: invalid symbol index in relocation"); 185 rel->r_info = ELFW(R_INFO)(tr[n], ELFW(R_TYPE)(rel->r_info)); 186 } 187 } 188 } 189 tcc_free(tr); 190 } 191 192 ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags) 193 { 194 Section *sec; 195 196 sec = tcc_mallocz(sizeof(Section) + strlen(name)); 197 strcpy(sec->name, name); 198 sec->sh_type = sh_type; 199 sec->sh_flags = sh_flags; 200 switch(sh_type) { 201 case SHT_HASH: 202 case SHT_REL: 203 case SHT_RELA: 204 case SHT_DYNSYM: 205 case SHT_SYMTAB: 206 case SHT_DYNAMIC: 207 sec->sh_addralign = 4; 208 break; 209 case SHT_STRTAB: 210 sec->sh_addralign = 1; 211 break; 212 default: 213 sec->sh_addralign = PTR_SIZE; /* gcc/pcc default alignment */ 214 break; 215 } 216 217 if (sh_flags & SHF_PRIVATE) { 218 dynarray_add(&s1->priv_sections, &s1->nb_priv_sections, sec); 219 } else { 220 sec->sh_num = s1->nb_sections; 221 dynarray_add(&s1->sections, &s1->nb_sections, sec); 222 } 223 224 return sec; 225 } 226 227 ST_FUNC Section *new_symtab(TCCState *s1, 228 const char *symtab_name, int sh_type, int sh_flags, 229 const char *strtab_name, 230 const char *hash_name, int hash_sh_flags) 231 { 232 Section *symtab, *strtab, *hash; 233 int *ptr, nb_buckets; 234 235 symtab = new_section(s1, symtab_name, sh_type, sh_flags); 236 symtab->sh_entsize = sizeof(ElfW(Sym)); 237 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags); 238 put_elf_str(strtab, ""); 239 symtab->link = strtab; 240 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL); 241 242 nb_buckets = 1; 243 244 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags); 245 hash->sh_entsize = sizeof(int); 246 symtab->hash = hash; 247 hash->link = symtab; 248 249 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int)); 250 ptr[0] = nb_buckets; 251 ptr[1] = 1; 252 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int)); 253 return symtab; 254 } 255 256 /* realloc section and set its content to zero */ 257 ST_FUNC void section_realloc(Section *sec, unsigned long new_size) 258 { 259 unsigned long size; 260 unsigned char *data; 261 262 size = sec->data_allocated; 263 if (size == 0) 264 size = 1; 265 while (size < new_size) 266 size = size * 2; 267 data = tcc_realloc(sec->data, size); 268 memset(data + sec->data_allocated, 0, size - sec->data_allocated); 269 sec->data = data; 270 sec->data_allocated = size; 271 } 272 273 /* reserve at least 'size' bytes aligned per 'align' in section 274 'sec' from current offset, and return the aligned offset */ 275 ST_FUNC size_t section_add(Section *sec, addr_t size, int align) 276 { 277 size_t offset, offset1; 278 279 offset = (sec->data_offset + align - 1) & -align; 280 offset1 = offset + size; 281 if (sec->sh_type != SHT_NOBITS && offset1 > sec->data_allocated) 282 section_realloc(sec, offset1); 283 sec->data_offset = offset1; 284 if (align > sec->sh_addralign) 285 sec->sh_addralign = align; 286 return offset; 287 } 288 289 /* reserve at least 'size' bytes in section 'sec' from 290 sec->data_offset. */ 291 ST_FUNC void *section_ptr_add(Section *sec, addr_t size) 292 { 293 size_t offset = section_add(sec, size, 1); 294 return sec->data + offset; 295 } 296 297 /* reserve at least 'size' bytes from section start */ 298 ST_FUNC void section_reserve(Section *sec, unsigned long size) 299 { 300 if (size > sec->data_allocated) 301 section_realloc(sec, size); 302 if (size > sec->data_offset) 303 sec->data_offset = size; 304 } 305 306 /* return a reference to a section, and create it if it does not 307 exists */ 308 ST_FUNC Section *find_section(TCCState *s1, const char *name) 309 { 310 Section *sec; 311 int i; 312 for(i = 1; i < s1->nb_sections; i++) { 313 sec = s1->sections[i]; 314 if (!strcmp(name, sec->name)) 315 return sec; 316 } 317 /* sections are created as PROGBITS */ 318 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC); 319 } 320 321 /* ------------------------------------------------------------------------- */ 24 322 25 323 ST_FUNC int put_elf_str(Section *s, const char *sym) … … 31 329 offset = s->data_offset; 32 330 ptr = section_ptr_add(s, len); 33 mem cpy(ptr, sym, len);331 memmove(ptr, sym, len); 34 332 return offset; 35 333 } … … 39 337 { 40 338 unsigned long h = 0, g; 41 339 42 340 while (*name) { 43 341 h = (h << 4) + *name++; … … 56 354 ElfW(Sym) *sym; 57 355 int *ptr, *hash, nb_syms, sym_index, h; 58 char *strtab;356 unsigned char *strtab; 59 357 60 358 strtab = s->link->data; 61 359 nb_syms = s->data_offset / sizeof(ElfW(Sym)); 360 361 if (!nb_buckets) 362 nb_buckets = ((int*)s->hash->data)[0]; 62 363 63 364 s->hash->data_offset = 0; … … 92 393 ElfW(Sym) *sym; 93 394 Section *hs; 94 395 95 396 sym = section_ptr_add(s, sizeof(ElfW(Sym))); 96 if (name )397 if (name && name[0]) 97 398 name_offset = put_elf_str(s->link, name); 98 399 else … … 111 412 ptr = section_ptr_add(hs, sizeof(int)); 112 413 base = (int *)hs->data; 113 /* only add global or weak symbols */414 /* only add global or weak symbols. */ 114 415 if (ELFW(ST_BIND)(info) != STB_LOCAL) { 115 416 /* add another hashing entry */ 116 417 nbuckets = base[0]; 117 h = elf_hash( name) % nbuckets;418 h = elf_hash((unsigned char *)s->link->data + name_offset) % nbuckets; 118 419 *ptr = base[2 + h]; 119 420 base[2 + h] = sym_index; … … 132 433 } 133 434 134 /* find global ELF symbol 'name' and return its index. Return 0 if not135 found. */136 435 ST_FUNC int find_elf_sym(Section *s, const char *name) 137 436 { … … 140 439 int nbuckets, sym_index, h; 141 440 const char *name1; 142 441 143 442 hs = s->hash; 144 443 if (!hs) 145 444 return 0; 146 445 nbuckets = ((int *)hs->data)[0]; 147 h = elf_hash( name) % nbuckets;446 h = elf_hash((unsigned char *) name) % nbuckets; 148 447 sym_index = ((int *)hs->data)[2 + h]; 149 448 while (sym_index != 0) { 150 449 sym = &((ElfW(Sym) *)s->data)[sym_index]; 151 name1 = s->link->data + sym->st_name;450 name1 = (char *) s->link->data + sym->st_name; 152 451 if (!strcmp(name, name1)) 153 452 return sym_index; … … 179 478 } 180 479 181 #if def TCC_IS_NATIVE480 #if defined TCC_IS_NATIVE || defined TCC_TARGET_PE 182 481 /* return elf symbol value or error */ 183 482 ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name) 184 483 { 185 return (void*) get_elf_sym_addr(s, name, 1);484 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 1); 186 485 } 187 486 #endif … … 189 488 /* add an elf symbol : check if it is already defined and patch 190 489 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */ 191 ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,192 int info, int other, int sh _num, const char *name)490 ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, 491 int info, int other, int shndx, const char *name) 193 492 { 194 493 ElfW(Sym) *esym; … … 199 498 sym_type = ELFW(ST_TYPE)(info); 200 499 sym_vis = ELFW(ST_VISIBILITY)(other); 201 500 202 501 if (sym_bind != STB_LOCAL) { 203 502 /* we search global or weak symbols */ … … 206 505 goto do_def; 207 506 esym = &((ElfW(Sym) *)s->data)[sym_index]; 507 if (esym->st_value == value && esym->st_size == size && esym->st_info == info 508 && esym->st_other == other && esym->st_shndx == shndx) 509 return sym_index; 208 510 if (esym->st_shndx != SHN_UNDEF) { 209 511 esym_bind = ELFW(ST_BIND)(esym->st_info); … … 221 523 | new_vis; 222 524 other = esym->st_other; /* in case we have to patch esym */ 223 if (sh _num== SHN_UNDEF) {525 if (shndx == SHN_UNDEF) { 224 526 /* ignore adding of undefined symbol if the 225 527 corresponding symbol is already defined */ … … 233 535 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) { 234 536 /* ignore hidden symbols after */ 235 } else if (esym->st_shndx == SHN_COMMON 236 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) { 237 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01 238 No idea if this is the correct solution ... */ 537 } else if ((esym->st_shndx == SHN_COMMON 538 || esym->st_shndx == bss_section->sh_num) 539 && (shndx < SHN_LORESERVE 540 && shndx != bss_section->sh_num)) { 541 /* data symbol gets precedence over common/bss */ 239 542 goto do_patch; 240 } else if (s == tcc_state->dynsymtab_section) { 543 } else if (shndx == SHN_COMMON || shndx == bss_section->sh_num) { 544 /* data symbol keeps precedence over common/bss */ 545 } else if (s->sh_flags & SHF_DYNSYM) { 241 546 /* we accept that two DLL define the same symbol */ 547 } else if (esym->st_other & ST_ASM_SET) { 548 /* If the existing symbol came from an asm .set 549 we can override. */ 550 goto do_patch; 242 551 } else { 243 552 #if 0 244 553 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n", 245 sym_bind, sh _num, new_vis, esym_bind, esym->st_shndx, esym_vis);554 sym_bind, shndx, new_vis, esym_bind, esym->st_shndx, esym_vis); 246 555 #endif 247 556 tcc_error_noabort("'%s' defined twice", name); … … 250 559 do_patch: 251 560 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type); 252 esym->st_shndx = sh _num;561 esym->st_shndx = shndx; 253 562 new_undef_sym = 1; 254 563 esym->st_value = value; … … 258 567 } else { 259 568 do_def: 260 sym_index = put_elf_sym(s, value, size, 261 ELFW(ST_INFO)(sym_bind, sym_type), other, 262 sh _num, name);569 sym_index = put_elf_sym(s, value, size, 570 ELFW(ST_INFO)(sym_bind, sym_type), other, 571 shndx, name); 263 572 } 264 573 return sym_index; … … 266 575 267 576 /* put relocation */ 268 ST_FUNC void put_elf_reloc (Section *symtab, Section *s, unsigned long offset,269 int type, int symbol)577 ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, 578 int type, int symbol, addr_t addend) 270 579 { 271 580 char buf[256]; … … 288 597 rel->r_offset = offset; 289 598 rel->r_info = ELFW(R_INFO)(symbol, type); 290 #ifdef TCC_TARGET_X86_64 291 rel->r_addend = 0; 292 #endif 599 #if SHT_RELX == SHT_RELA 600 rel->r_addend = addend; 601 #else 602 if (addend) 603 tcc_error("non-zero addend on REL architecture"); 604 #endif 605 } 606 607 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, 608 int type, int symbol) 609 { 610 put_elf_reloca(symtab, s, offset, type, symbol, 0); 611 } 612 613 /* Remove relocations for section S->reloc starting at oldrelocoffset 614 that are to the same place, retaining the last of them. As side effect 615 the relocations are sorted. Possibly reduces the number of relocs. */ 616 ST_FUNC void squeeze_multi_relocs(Section *s, size_t oldrelocoffset) 617 { 618 Section *sr = s->reloc; 619 ElfW_Rel *r, *dest; 620 ssize_t a; 621 ElfW(Addr) addr; 622 623 if (oldrelocoffset + sizeof(*r) >= sr->data_offset) 624 return; 625 /* The relocs we're dealing with are the result of initializer parsing. 626 So they will be mostly in order and there aren't many of them. 627 Secondly we need a stable sort (which qsort isn't). We use 628 a simple insertion sort. */ 629 for (a = oldrelocoffset + sizeof(*r); a < sr->data_offset; a += sizeof(*r)) { 630 ssize_t i = a - sizeof(*r); 631 addr = ((ElfW_Rel*)(sr->data + a))->r_offset; 632 for (; i >= (ssize_t)oldrelocoffset && 633 ((ElfW_Rel*)(sr->data + i))->r_offset > addr; i -= sizeof(*r)) { 634 ElfW_Rel tmp = *(ElfW_Rel*)(sr->data + a); 635 *(ElfW_Rel*)(sr->data + a) = *(ElfW_Rel*)(sr->data + i); 636 *(ElfW_Rel*)(sr->data + i) = tmp; 637 } 638 } 639 640 r = (ElfW_Rel*)(sr->data + oldrelocoffset); 641 dest = r; 642 for (; r < (ElfW_Rel*)(sr->data + sr->data_offset); r++) { 643 if (dest->r_offset != r->r_offset) 644 dest++; 645 *dest = *r; 646 } 647 sr->data_offset = (unsigned char*)dest - sr->data + sizeof(*r); 293 648 } 294 649 … … 312 667 } 313 668 314 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc, 669 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc, 315 670 unsigned long value, Section *sec, int sym_index) 316 671 { 317 672 put_stabs(str, type, other, desc, value); 318 put_elf_reloc(symtab_section, stab_section, 673 put_elf_reloc(symtab_section, stab_section, 319 674 stab_section->data_offset - sizeof(unsigned int), 320 675 R_DATA_32, sym_index); … … 331 686 } 332 687 333 /* In an ELF file symbol table, the local symbols must appear below 334 the global and weak ones. Since TCC cannot sort it while generating 335 the code, we must do it after. All the relocation tables are also 336 modified to take into account the symbol table sorting */ 337 static void sort_syms(TCCState *s1, Section *s) 338 { 339 int *old_to_new_syms; 340 ElfW(Sym) *new_syms; 341 int nb_syms, i; 342 ElfW(Sym) *p, *q; 343 ElfW_Rel *rel, *rel_end; 344 Section *sr; 345 int type, sym_index; 346 347 nb_syms = s->data_offset / sizeof(ElfW(Sym)); 348 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym))); 349 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int)); 350 351 /* first pass for local symbols */ 352 p = (ElfW(Sym) *)s->data; 353 q = new_syms; 354 for(i = 0; i < nb_syms; i++) { 355 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) { 356 old_to_new_syms[i] = q - new_syms; 357 *q++ = *p; 358 } 359 p++; 360 } 361 /* save the number of local symbols in section header */ 362 s->sh_info = q - new_syms; 363 364 /* then second pass for non local symbols */ 365 p = (ElfW(Sym) *)s->data; 366 for(i = 0; i < nb_syms; i++) { 367 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) { 368 old_to_new_syms[i] = q - new_syms; 369 *q++ = *p; 370 } 371 p++; 372 } 373 374 /* we copy the new symbols to the old */ 375 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym))); 376 tcc_free(new_syms); 377 378 /* now we modify all the relocations */ 379 for(i = 1; i < s1->nb_sections; i++) { 380 sr = s1->sections[i]; 381 if (sr->sh_type == SHT_RELX && sr->link == s) { 382 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset); 383 for(rel = (ElfW_Rel *)sr->data; 384 rel < rel_end; 385 rel++) { 386 sym_index = ELFW(R_SYM)(rel->r_info); 387 type = ELFW(R_TYPE)(rel->r_info); 388 sym_index = old_to_new_syms[sym_index]; 389 rel->r_info = ELFW(R_INFO)(sym_index, type); 390 } 391 } 392 } 393 394 tcc_free(old_to_new_syms); 395 } 396 397 /* relocate common symbols in the .bss section */ 398 ST_FUNC void relocate_common_syms(void) 399 { 400 ElfW(Sym) *sym, *sym_end; 401 unsigned long offset, align; 402 403 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset); 404 for(sym = (ElfW(Sym) *)symtab_section->data + 1; 405 sym < sym_end; 406 sym++) { 407 if (sym->st_shndx == SHN_COMMON) { 408 /* align symbol */ 409 align = sym->st_value; 410 offset = bss_section->data_offset; 411 offset = (offset + align - 1) & -align; 412 sym->st_value = offset; 413 sym->st_shndx = bss_section->sh_num; 414 offset += sym->st_size; 415 bss_section->data_offset = offset; 416 } 417 } 418 } 419 420 /* relocate symbol table, resolve undefined symbols if do_resolve is 421 true and output error if undefined symbol. */ 422 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve) 423 { 424 ElfW(Sym) *sym, *esym, *sym_end; 425 int sym_bind, sh_num, sym_index; 426 const char *name; 427 428 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset); 429 for(sym = (ElfW(Sym) *)symtab_section->data + 1; 430 sym < sym_end; 431 sym++) { 432 sh_num = sym->st_shndx; 433 if (sh_num == SHN_UNDEF) { 434 name = strtab_section->data + sym->st_name; 435 if (do_resolve) { 436 #if defined TCC_IS_NATIVE && !defined _WIN32 437 void *addr; 438 name = symtab_section->link->data + sym->st_name; 439 addr = resolve_sym(s1, name); 440 if (addr) { 441 sym->st_value = (addr_t)addr; 442 goto found; 443 } 444 #endif 445 } else if (s1->dynsym) { 446 /* if dynamic symbol exist, then use it */ 447 sym_index = find_elf_sym(s1->dynsym, name); 448 if (sym_index) { 449 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index]; 450 sym->st_value = esym->st_value; 451 goto found; 452 } 453 } 454 /* XXX: _fp_hw seems to be part of the ABI, so we ignore 455 it */ 456 if (!strcmp(name, "_fp_hw")) 457 goto found; 458 /* only weak symbols are accepted to be undefined. Their 459 value is zero */ 460 sym_bind = ELFW(ST_BIND)(sym->st_info); 461 if (sym_bind == STB_WEAK) { 462 sym->st_value = 0; 463 } else { 464 tcc_error_noabort("undefined symbol '%s'", name); 465 } 466 } else if (sh_num < SHN_LORESERVE) { 467 /* add section base */ 468 sym->st_value += s1->sections[sym->st_shndx]->sh_addr; 469 } 470 found: ; 471 } 472 } 473 474 #ifdef TCC_HAS_RUNTIME_PLTGOT 475 #ifdef TCC_TARGET_X86_64 476 #define JMP_TABLE_ENTRY_SIZE 14 477 static addr_t add_jmp_table(TCCState *s1, addr_t val) 478 { 479 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset; 480 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE; 481 /* jmp *0x0(%rip) */ 482 p[0] = 0xff; 483 p[1] = 0x25; 484 *(int *)(p + 2) = 0; 485 *(addr_t *)(p + 6) = val; 486 return (addr_t)p; 487 } 488 489 static addr_t add_got_table(TCCState *s1, addr_t val) 490 { 491 addr_t *p = (addr_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset); 492 s1->runtime_plt_and_got_offset += sizeof(addr_t); 493 *p = val; 494 return (addr_t)p; 495 } 496 #elif defined TCC_TARGET_ARM 497 #define JMP_TABLE_ENTRY_SIZE 8 498 static addr_t add_jmp_table(TCCState *s1, int val) 499 { 500 uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset); 501 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE; 502 /* ldr pc, [pc, #-4] */ 503 p[0] = 0xE51FF004; 504 p[1] = val; 505 return (addr_t)p; 506 } 507 #endif 508 #endif /* def TCC_HAS_RUNTIME_PLTGOT */ 509 510 /* relocate a given section (CPU dependent) */ 511 ST_FUNC void relocate_section(TCCState *s1, Section *s) 512 { 513 Section *sr; 514 ElfW_Rel *rel, *rel_end, *qrel; 515 ElfW(Sym) *sym; 516 int type, sym_index; 517 unsigned char *ptr; 518 addr_t val, addr; 519 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 520 int esym_index; 521 #endif 522 523 sr = s->reloc; 524 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset); 525 qrel = (ElfW_Rel *)sr->data; 526 for(rel = qrel; 527 rel < rel_end; 528 rel++) { 529 ptr = s->data + rel->r_offset; 530 531 sym_index = ELFW(R_SYM)(rel->r_info); 532 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; 533 val = sym->st_value; 534 #ifdef TCC_TARGET_X86_64 535 val += rel->r_addend; 536 #endif 537 type = ELFW(R_TYPE)(rel->r_info); 538 addr = s->sh_addr + rel->r_offset; 539 540 /* CPU specific */ 541 switch(type) { 542 #if defined(TCC_TARGET_I386) 543 case R_386_32: 544 if (s1->output_type == TCC_OUTPUT_DLL) { 545 esym_index = s1->symtab_to_dynsym[sym_index]; 546 qrel->r_offset = rel->r_offset; 547 if (esym_index) { 548 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32); 549 qrel++; 550 break; 551 } else { 552 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE); 553 qrel++; 554 } 555 } 556 *(int *)ptr += val; 557 break; 558 case R_386_PC32: 559 if (s1->output_type == TCC_OUTPUT_DLL) { 560 /* DLL relocation */ 561 esym_index = s1->symtab_to_dynsym[sym_index]; 562 if (esym_index) { 563 qrel->r_offset = rel->r_offset; 564 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32); 565 qrel++; 566 break; 567 } 568 } 569 *(int *)ptr += val - addr; 570 break; 571 case R_386_PLT32: 572 *(int *)ptr += val - addr; 573 break; 574 case R_386_GLOB_DAT: 575 case R_386_JMP_SLOT: 576 *(int *)ptr = val; 577 break; 578 case R_386_GOTPC: 579 *(int *)ptr += s1->got->sh_addr - addr; 580 break; 581 case R_386_GOTOFF: 582 *(int *)ptr += val - s1->got->sh_addr; 583 break; 584 case R_386_GOT32: 585 /* we load the got offset */ 586 *(int *)ptr += s1->sym_attrs[sym_index].got_offset; 587 break; 588 case R_386_16: 589 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) { 590 output_file: 591 tcc_error("can only produce 16-bit binary files"); 592 } 593 *(short *)ptr += val; 594 break; 595 case R_386_PC16: 596 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) 597 goto output_file; 598 *(short *)ptr += val - addr; 599 break; 600 #elif defined(TCC_TARGET_ARM) 601 case R_ARM_PC24: 602 case R_ARM_CALL: 603 case R_ARM_JUMP24: 604 case R_ARM_PLT32: 605 { 606 int x, is_thumb, is_call, h, blx_avail; 607 x = (*(int *)ptr)&0xffffff; 608 (*(int *)ptr) &= 0xff000000; 609 if (x & 0x800000) 610 x -= 0x1000000; 611 x <<= 2; 612 blx_avail = (TCC_ARM_VERSION >= 5); 613 is_thumb = val & 1; 614 is_call = (type == R_ARM_CALL); 615 x += val - addr; 616 h = x & 2; 617 #ifdef TCC_HAS_RUNTIME_PLTGOT 618 if (s1->output_type == TCC_OUTPUT_MEMORY) { 619 if ((x & 3) || x >= 0x2000000 || x < -0x2000000) 620 if (!(x & 3) || !blx_avail || !is_call) { 621 x += add_jmp_table(s1, val) - val; /* add veneer */ 622 is_thumb = 0; /* Veneer uses ARM instructions */ 623 } 624 } 625 #endif 626 if ((x & 3) || x >= 0x2000000 || x < -0x2000000) 627 if (!(x & 3) || !blx_avail || !is_call) 628 tcc_error("can't relocate value at %x",addr); 629 x >>= 2; 630 x &= 0xffffff; 631 /* Only reached if blx is avail and it is a call */ 632 if (is_thumb) { 633 x |= h << 24; 634 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */ 635 } 636 (*(int *)ptr) |= x; 637 } 638 break; 639 /* Since these relocations only concern Thumb-2 and blx instruction was 640 introduced before Thumb-2, we can assume blx is available and not 641 guard its use */ 642 case R_ARM_THM_CALL: 643 case R_ARM_THM_JUMP24: 644 { 645 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11; 646 int to_thumb, is_call, to_plt, blx_bit = 1 << 12; 647 Section *plt; 648 649 /* weak reference */ 650 if (sym->st_shndx == SHN_UNDEF && 651 ELFW(ST_BIND)(sym->st_info) == STB_WEAK) 652 break; 653 654 /* Get initial offset */ 655 hi = (*(uint16_t *)ptr); 656 lo = (*(uint16_t *)(ptr+2)); 657 s = (hi >> 10) & 1; 658 j1 = (lo >> 13) & 1; 659 j2 = (lo >> 11) & 1; 660 i1 = (j1 ^ s) ^ 1; 661 i2 = (j2 ^ s) ^ 1; 662 imm10 = hi & 0x3ff; 663 imm11 = lo & 0x7ff; 664 x = (s << 24) | (i1 << 23) | (i2 << 22) | 665 (imm10 << 12) | (imm11 << 1); 666 if (x & 0x01000000) 667 x -= 0x02000000; 668 669 /* Relocation infos */ 670 to_thumb = val & 1; 671 plt = s1->plt; 672 to_plt = (val >= plt->sh_addr) && 673 (val < plt->sh_addr + plt->data_offset); 674 is_call = (type == R_ARM_THM_CALL); 675 676 /* Compute final offset */ 677 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */ 678 x -= 4; 679 x += val - addr; 680 if (!to_thumb && is_call) { 681 blx_bit = 0; /* bl -> blx */ 682 x = (x + 3) & -4; /* Compute offset from aligned PC */ 683 } 684 685 /* Check that relocation is possible 686 * offset must not be out of range 687 * if target is to be entered in arm mode: 688 - bit 1 must not set 689 - instruction must be a call (bl) or a jump to PLT */ 690 if (!to_thumb || x >= 0x1000000 || x < -0x1000000) 691 if (to_thumb || (val & 2) || (!is_call && !to_plt)) 692 tcc_error("can't relocate value at %x",addr); 693 694 /* Compute and store final offset */ 695 s = (x >> 24) & 1; 696 i1 = (x >> 23) & 1; 697 i2 = (x >> 22) & 1; 698 j1 = s ^ (i1 ^ 1); 699 j2 = s ^ (i2 ^ 1); 700 imm10 = (x >> 12) & 0x3ff; 701 imm11 = (x >> 1) & 0x7ff; 702 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) | 703 (s << 10) | imm10); 704 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) | 705 (j1 << 13) | blx_bit | (j2 << 11) | 706 imm11); 707 } 708 break; 709 case R_ARM_MOVT_ABS: 710 case R_ARM_MOVW_ABS_NC: 711 { 712 int x, imm4, imm12; 713 if (type == R_ARM_MOVT_ABS) 714 val >>= 16; 715 imm12 = val & 0xfff; 716 imm4 = (val >> 12) & 0xf; 717 x = (imm4 << 16) | imm12; 718 if (type == R_ARM_THM_MOVT_ABS) 719 *(int *)ptr |= x; 720 else 721 *(int *)ptr += x; 722 } 723 break; 724 case R_ARM_THM_MOVT_ABS: 725 case R_ARM_THM_MOVW_ABS_NC: 726 { 727 int x, i, imm4, imm3, imm8; 728 if (type == R_ARM_THM_MOVT_ABS) 729 val >>= 16; 730 imm8 = val & 0xff; 731 imm3 = (val >> 8) & 0x7; 732 i = (val >> 11) & 1; 733 imm4 = (val >> 12) & 0xf; 734 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4; 735 if (type == R_ARM_THM_MOVT_ABS) 736 *(int *)ptr |= x; 737 else 738 *(int *)ptr += x; 739 } 740 break; 741 case R_ARM_PREL31: 742 { 743 int x; 744 x = (*(int *)ptr) & 0x7fffffff; 745 (*(int *)ptr) &= 0x80000000; 746 x = (x * 2) / 2; 747 x += val - addr; 748 if((x^(x>>1))&0x40000000) 749 tcc_error("can't relocate value at %x",addr); 750 (*(int *)ptr) |= x & 0x7fffffff; 751 } 752 case R_ARM_ABS32: 753 *(int *)ptr += val; 754 break; 755 case R_ARM_REL32: 756 *(int *)ptr += val - addr; 757 break; 758 case R_ARM_BASE_PREL: 759 *(int *)ptr += s1->got->sh_addr - addr; 760 break; 761 case R_ARM_GOTOFF32: 762 *(int *)ptr += val - s1->got->sh_addr; 763 break; 764 case R_ARM_GOT_BREL: 765 /* we load the got offset */ 766 *(int *)ptr += s1->sym_attrs[sym_index].got_offset; 767 break; 768 case R_ARM_COPY: 769 break; 770 case R_ARM_V4BX: 771 /* trade Thumb support for ARMv4 support */ 772 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10) 773 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */ 774 break; 775 default: 776 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n", 777 type, (unsigned)addr, ptr, (unsigned)val); 778 break; 779 #elif defined(TCC_TARGET_C67) 780 case R_C60_32: 781 *(int *)ptr += val; 782 break; 783 case R_C60LO16: 784 { 785 uint32_t orig; 786 787 /* put the low 16 bits of the absolute address */ 788 // add to what is already there 789 790 orig = ((*(int *)(ptr )) >> 7) & 0xffff; 791 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16; 792 793 //patch both at once - assumes always in pairs Low - High 794 795 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7); 796 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7); 797 } 798 break; 799 case R_C60HI16: 800 break; 801 default: 802 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n", 803 type, (unsigned)addr, ptr, (unsigned)val); 804 break; 805 #elif defined(TCC_TARGET_X86_64) 806 case R_X86_64_64: 807 if (s1->output_type == TCC_OUTPUT_DLL) { 808 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE); 809 qrel->r_addend = *(long long *)ptr + val; 810 qrel++; 811 } 812 *(long long *)ptr += val; 813 break; 814 case R_X86_64_32: 815 case R_X86_64_32S: 816 if (s1->output_type == TCC_OUTPUT_DLL) { 817 /* XXX: this logic may depend on TCC's codegen 818 now TCC uses R_X86_64_32 even for a 64bit pointer */ 819 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE); 820 qrel->r_addend = *(int *)ptr + val; 821 qrel++; 822 } 823 *(int *)ptr += val; 824 break; 825 826 case R_X86_64_PC32: 827 if (s1->output_type == TCC_OUTPUT_DLL) { 828 /* DLL relocation */ 829 esym_index = s1->symtab_to_dynsym[sym_index]; 830 if (esym_index) { 831 qrel->r_offset = rel->r_offset; 832 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32); 833 qrel->r_addend = *(int *)ptr; 834 qrel++; 835 break; 836 } 837 } 838 /* fall through */ 839 case R_X86_64_PLT32: { 840 long long diff; 841 diff = (long long)val - addr; 842 if (diff <= -2147483647 || diff > 2147483647) { 843 #ifdef TCC_HAS_RUNTIME_PLTGOT 844 /* XXX: naive support for over 32bit jump */ 845 if (s1->output_type == TCC_OUTPUT_MEMORY) { 846 val = (add_jmp_table(s1, val - rel->r_addend) + 847 rel->r_addend); 848 diff = val - addr; 849 } 850 #endif 851 if (diff <= -2147483647 || diff > 2147483647) { 852 tcc_error("internal error: relocation failed"); 853 } 854 } 855 *(int *)ptr += diff; 856 } 857 break; 858 case R_X86_64_GLOB_DAT: 859 case R_X86_64_JUMP_SLOT: 860 /* They don't need addend */ 861 *(int *)ptr = val - rel->r_addend; 862 break; 863 case R_X86_64_GOTPCREL: 864 #ifdef TCC_HAS_RUNTIME_PLTGOT 865 if (s1->output_type == TCC_OUTPUT_MEMORY) { 866 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend; 867 *(int *)ptr += val - addr; 868 break; 869 } 870 #endif 871 *(int *)ptr += (s1->got->sh_addr - addr + 872 s1->sym_attrs[sym_index].got_offset - 4); 873 break; 874 case R_X86_64_GOTTPOFF: 875 *(int *)ptr += val - s1->got->sh_addr; 876 break; 877 case R_X86_64_GOT32: 878 /* we load the got offset */ 879 *(int *)ptr += s1->sym_attrs[sym_index].got_offset; 880 break; 881 #elif defined(TCC_TARGET_IL) 882 #else 883 #error unsupported processor 884 #endif 885 } 886 } 887 /* if the relocation is allocated, we change its symbol table */ 888 if (sr->sh_flags & SHF_ALLOC) 889 sr->link = s1->dynsym; 890 } 891 892 /* relocate relocation table in 'sr' */ 893 static void relocate_rel(TCCState *s1, Section *sr) 894 { 895 Section *s; 896 ElfW_Rel *rel, *rel_end; 897 898 s = s1->sections[sr->sh_info]; 899 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset); 900 for(rel = (ElfW_Rel *)sr->data; 901 rel < rel_end; 902 rel++) { 903 rel->r_offset += s->sh_addr; 904 } 905 } 906 907 /* count the number of dynamic relocations so that we can reserve 908 their space */ 909 static int prepare_dynamic_rel(TCCState *s1, Section *sr) 910 { 911 ElfW_Rel *rel, *rel_end; 912 int sym_index, esym_index, type, count; 913 914 count = 0; 915 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset); 916 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) { 917 sym_index = ELFW(R_SYM)(rel->r_info); 918 type = ELFW(R_TYPE)(rel->r_info); 919 switch(type) { 920 #if defined(TCC_TARGET_I386) 921 case R_386_32: 922 #elif defined(TCC_TARGET_X86_64) 923 case R_X86_64_32: 924 case R_X86_64_32S: 925 case R_X86_64_64: 926 #endif 927 count++; 928 break; 929 #if defined(TCC_TARGET_I386) 930 case R_386_PC32: 931 #elif defined(TCC_TARGET_X86_64) 932 case R_X86_64_PC32: 933 #endif 934 esym_index = s1->symtab_to_dynsym[sym_index]; 935 if (esym_index) 936 count++; 937 break; 938 default: 939 break; 940 } 941 } 942 if (count) { 943 /* allocate the section */ 944 sr->sh_flags |= SHF_ALLOC; 945 sr->sh_size = count * sizeof(ElfW_Rel); 946 } 947 return count; 948 } 949 950 static struct sym_attr *alloc_sym_attr(TCCState *s1, int index) 688 ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc) 951 689 { 952 690 int n; … … 954 692 955 693 if (index >= s1->nb_sym_attrs) { 694 if (!alloc) 695 return s1->sym_attrs; 956 696 /* find immediately bigger power of 2 and reallocate array */ 957 697 n = 1; … … 967 707 } 968 708 969 /* XXX: suppress that */ 970 static void put32(unsigned char *p, uint32_t val) 971 { 972 p[0] = val; 973 p[1] = val >> 8; 974 p[2] = val >> 16; 975 p[3] = val >> 24; 976 } 977 978 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \ 979 defined(TCC_TARGET_X86_64) 980 static uint32_t get32(unsigned char *p) 981 { 982 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 983 } 984 #endif 709 /* Browse each elem of type <type> in section <sec> starting at elem <startoff> 710 using variable <elem> */ 711 #define for_each_elem(sec, startoff, elem, type) \ 712 for (elem = (type *) sec->data + startoff; \ 713 elem < (type *) (sec->data + sec->data_offset); elem++) 714 715 /* In an ELF file symbol table, the local symbols must appear below 716 the global and weak ones. Since TCC cannot sort it while generating 717 the code, we must do it after. All the relocation tables are also 718 modified to take into account the symbol table sorting */ 719 static void sort_syms(TCCState *s1, Section *s) 720 { 721 int *old_to_new_syms; 722 ElfW(Sym) *new_syms; 723 int nb_syms, i; 724 ElfW(Sym) *p, *q; 725 ElfW_Rel *rel; 726 Section *sr; 727 int type, sym_index; 728 729 nb_syms = s->data_offset / sizeof(ElfW(Sym)); 730 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym))); 731 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int)); 732 733 /* first pass for local symbols */ 734 p = (ElfW(Sym) *)s->data; 735 q = new_syms; 736 for(i = 0; i < nb_syms; i++) { 737 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) { 738 old_to_new_syms[i] = q - new_syms; 739 *q++ = *p; 740 } 741 p++; 742 } 743 /* save the number of local symbols in section header */ 744 if( s->sh_size ) /* this 'if' makes IDA happy */ 745 s->sh_info = q - new_syms; 746 747 /* then second pass for non local symbols */ 748 p = (ElfW(Sym) *)s->data; 749 for(i = 0; i < nb_syms; i++) { 750 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) { 751 old_to_new_syms[i] = q - new_syms; 752 *q++ = *p; 753 } 754 p++; 755 } 756 757 /* we copy the new symbols to the old */ 758 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym))); 759 tcc_free(new_syms); 760 761 /* now we modify all the relocations */ 762 for(i = 1; i < s1->nb_sections; i++) { 763 sr = s1->sections[i]; 764 if (sr->sh_type == SHT_RELX && sr->link == s) { 765 for_each_elem(sr, 0, rel, ElfW_Rel) { 766 sym_index = ELFW(R_SYM)(rel->r_info); 767 type = ELFW(R_TYPE)(rel->r_info); 768 sym_index = old_to_new_syms[sym_index]; 769 rel->r_info = ELFW(R_INFO)(sym_index, type); 770 } 771 } 772 } 773 774 tcc_free(old_to_new_syms); 775 } 776 777 /* relocate symbol table, resolve undefined symbols if do_resolve is 778 true and output error if undefined symbol. */ 779 ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve) 780 { 781 ElfW(Sym) *sym; 782 int sym_bind, sh_num; 783 const char *name; 784 785 for_each_elem(symtab, 1, sym, ElfW(Sym)) { 786 sh_num = sym->st_shndx; 787 if (sh_num == SHN_UNDEF) { 788 name = (char *) s1->symtab->link->data + sym->st_name; 789 /* Use ld.so to resolve symbol for us (for tcc -run) */ 790 if (do_resolve) { 791 #if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE 792 void *addr = dlsym(RTLD_DEFAULT, name); 793 if (addr) { 794 sym->st_value = (addr_t) addr; 795 #ifdef DEBUG_RELOC 796 printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value); 797 #endif 798 goto found; 799 } 800 #endif 801 /* if dynamic symbol exist, it will be used in relocate_section */ 802 } else if (s1->dynsym && find_elf_sym(s1->dynsym, name)) 803 goto found; 804 /* XXX: _fp_hw seems to be part of the ABI, so we ignore 805 it */ 806 if (!strcmp(name, "_fp_hw")) 807 goto found; 808 /* only weak symbols are accepted to be undefined. Their 809 value is zero */ 810 sym_bind = ELFW(ST_BIND)(sym->st_info); 811 if (sym_bind == STB_WEAK) 812 sym->st_value = 0; 813 else 814 tcc_error_noabort("undefined symbol '%s'", name); 815 } else if (sh_num < SHN_LORESERVE) { 816 /* add section base */ 817 sym->st_value += s1->sections[sym->st_shndx]->sh_addr; 818 } 819 found: ; 820 } 821 } 822 823 /* relocate a given section (CPU dependent) by applying the relocations 824 in the associated relocation section */ 825 ST_FUNC void relocate_section(TCCState *s1, Section *s) 826 { 827 Section *sr = s->reloc; 828 ElfW_Rel *rel; 829 ElfW(Sym) *sym; 830 int type, sym_index; 831 unsigned char *ptr; 832 addr_t tgt, addr; 833 834 relocate_init(sr); 835 836 for_each_elem(sr, 0, rel, ElfW_Rel) { 837 ptr = s->data + rel->r_offset; 838 sym_index = ELFW(R_SYM)(rel->r_info); 839 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; 840 type = ELFW(R_TYPE)(rel->r_info); 841 tgt = sym->st_value; 842 #if SHT_RELX == SHT_RELA 843 tgt += rel->r_addend; 844 #endif 845 addr = s->sh_addr + rel->r_offset; 846 relocate(s1, rel, type, ptr, addr, tgt); 847 } 848 /* if the relocation is allocated, we change its symbol table */ 849 if (sr->sh_flags & SHF_ALLOC) 850 sr->link = s1->dynsym; 851 } 852 853 /* relocate relocation table in 'sr' */ 854 static void relocate_rel(TCCState *s1, Section *sr) 855 { 856 Section *s; 857 ElfW_Rel *rel; 858 859 s = s1->sections[sr->sh_info]; 860 for_each_elem(sr, 0, rel, ElfW_Rel) 861 rel->r_offset += s->sh_addr; 862 } 863 864 /* count the number of dynamic relocations so that we can reserve 865 their space */ 866 static int prepare_dynamic_rel(TCCState *s1, Section *sr) 867 { 868 ElfW_Rel *rel; 869 int sym_index, type, count; 870 871 count = 0; 872 for_each_elem(sr, 0, rel, ElfW_Rel) { 873 sym_index = ELFW(R_SYM)(rel->r_info); 874 type = ELFW(R_TYPE)(rel->r_info); 875 switch(type) { 876 #if defined(TCC_TARGET_I386) 877 case R_386_32: 878 if (!get_sym_attr(s1, sym_index, 0)->dyn_index 879 && ((ElfW(Sym)*)symtab_section->data + sym_index)->st_shndx == SHN_UNDEF) { 880 /* don't fixup unresolved (weak) symbols */ 881 rel->r_info = ELFW(R_INFO)(sym_index, R_386_RELATIVE); 882 break; 883 } 884 #elif defined(TCC_TARGET_X86_64) 885 case R_X86_64_32: 886 case R_X86_64_32S: 887 case R_X86_64_64: 888 #endif 889 count++; 890 break; 891 #if defined(TCC_TARGET_I386) 892 case R_386_PC32: 893 #elif defined(TCC_TARGET_X86_64) 894 case R_X86_64_PC32: 895 #endif 896 if (get_sym_attr(s1, sym_index, 0)->dyn_index) 897 count++; 898 break; 899 default: 900 break; 901 } 902 } 903 if (count) { 904 /* allocate the section */ 905 sr->sh_flags |= SHF_ALLOC; 906 sr->sh_size = count * sizeof(ElfW_Rel); 907 } 908 return count; 909 } 985 910 986 911 static void build_got(TCCState *s1) 987 912 { 988 unsigned char *ptr;989 990 913 /* if no got, then create it */ 991 914 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); 992 915 s1->got->sh_entsize = 4; 993 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),916 set_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT), 994 917 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_"); 995 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE); 996 #if PTR_SIZE == 4 997 /* keep space for _DYNAMIC pointer, if present */ 998 put32(ptr, 0); 999 /* two dummy got entries */ 1000 put32(ptr + 4, 0); 1001 put32(ptr + 8, 0); 1002 #else 1003 /* keep space for _DYNAMIC pointer, if present */ 1004 put32(ptr, 0); 1005 put32(ptr + 4, 0); 1006 /* two dummy got entries */ 1007 put32(ptr + 8, 0); 1008 put32(ptr + 12, 0); 1009 put32(ptr + 16, 0); 1010 put32(ptr + 20, 0); 1011 #endif 1012 } 1013 1014 /* put a got entry corresponding to a symbol in symtab_section. 'size' 1015 and 'info' can be modifed if more precise info comes from the DLL */ 1016 static void put_got_entry(TCCState *s1, 1017 int reloc_type, unsigned long size, int info, 1018 int sym_index) 1019 { 1020 int index; 918 /* keep space for _DYNAMIC pointer and two dummy got entries */ 919 section_ptr_add(s1->got, 3 * PTR_SIZE); 920 } 921 922 /* Create a GOT and (for function call) a PLT entry corresponding to a symbol 923 in s1->symtab. When creating the dynamic symbol table entry for the GOT 924 relocation, use 'size' and 'info' for the corresponding symbol metadata. 925 Returns the offset of the GOT or (if any) PLT entry. */ 926 static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type, 927 unsigned long size, 928 int info, int sym_index) 929 { 930 int need_plt_entry; 1021 931 const char *name; 1022 932 ElfW(Sym) *sym; 1023 unsigned long offset; 1024 int *ptr; 1025 1026 if (!s1->got) 1027 build_got(s1); 1028 1029 /* if a got entry already exists for that symbol, no need to add one */ 1030 if (sym_index < s1->nb_sym_attrs && 1031 s1->sym_attrs[sym_index].got_offset) 1032 return; 1033 1034 alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset; 933 struct sym_attr *attr; 934 unsigned got_offset; 935 char plt_name[100]; 936 int len; 937 938 need_plt_entry = (dyn_reloc_type == R_JMP_SLOT); 939 attr = get_sym_attr(s1, sym_index, 1); 940 941 /* In case a function is both called and its address taken 2 GOT entries 942 are created, one for taking the address (GOT) and the other for the PLT 943 entry (PLTGOT). */ 944 if (need_plt_entry ? attr->plt_offset : attr->got_offset) 945 return attr; 946 947 /* create the GOT entry */ 948 got_offset = s1->got->data_offset; 949 section_ptr_add(s1->got, PTR_SIZE); 950 951 /* Create the GOT relocation that will insert the address of the object or 952 function of interest in the GOT entry. This is a static relocation for 953 memory output (dlsym will give us the address of symbols) and dynamic 954 relocation otherwise (executable and DLLs). The relocation should be 955 done lazily for GOT entry with *_JUMP_SLOT relocation type (the one 956 associated to a PLT entry) but is currently done at load time for an 957 unknown reason. */ 958 959 sym = &((ElfW(Sym) *) symtab_section->data)[sym_index]; 960 name = (char *) symtab_section->link->data + sym->st_name; 1035 961 1036 962 if (s1->dynsym) { 1037 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; 1038 name = symtab_section->link->data + sym->st_name; 1039 offset = sym->st_value; 1040 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) 1041 if (reloc_type == 1042 #ifdef TCC_TARGET_X86_64 1043 R_X86_64_JUMP_SLOT 1044 #else 1045 R_386_JMP_SLOT 1046 #endif 1047 ) { 1048 Section *plt; 1049 uint8_t *p; 1050 int modrm; 1051 1052 #if defined(TCC_OUTPUT_DLL_WITH_PLT) 1053 modrm = 0x25; 1054 #else 1055 /* if we build a DLL, we add a %ebx offset */ 1056 if (s1->output_type == TCC_OUTPUT_DLL) 1057 modrm = 0xa3; 1058 else 1059 modrm = 0x25; 1060 #endif 1061 1062 /* add a PLT entry */ 1063 plt = s1->plt; 1064 if (plt->data_offset == 0) { 1065 /* first plt entry */ 1066 p = section_ptr_add(plt, 16); 1067 p[0] = 0xff; /* pushl got + PTR_SIZE */ 1068 p[1] = modrm + 0x10; 1069 put32(p + 2, PTR_SIZE); 1070 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */ 1071 p[7] = modrm; 1072 put32(p + 8, PTR_SIZE * 2); 1073 } 1074 1075 p = section_ptr_add(plt, 16); 1076 p[0] = 0xff; /* jmp *(got + x) */ 1077 p[1] = modrm; 1078 put32(p + 2, s1->got->data_offset); 1079 p[6] = 0x68; /* push $xxx */ 1080 put32(p + 7, (plt->data_offset - 32) >> 1); 1081 p[11] = 0xe9; /* jmp plt_start */ 1082 put32(p + 12, -(plt->data_offset)); 1083 1084 /* the symbol is modified so that it will be relocated to 1085 the PLT */ 1086 #if !defined(TCC_OUTPUT_DLL_WITH_PLT) 1087 if (s1->output_type == TCC_OUTPUT_EXE) 1088 #endif 1089 offset = plt->data_offset - 16; 1090 } 1091 #elif defined(TCC_TARGET_ARM) 1092 if (reloc_type == R_ARM_JUMP_SLOT) { 1093 Section *plt; 1094 uint8_t *p; 1095 1096 /* if we build a DLL, we add a %ebx offset */ 1097 if (s1->output_type == TCC_OUTPUT_DLL) 1098 tcc_error("DLLs unimplemented!"); 1099 1100 /* add a PLT entry */ 1101 plt = s1->plt; 1102 if (plt->data_offset == 0) { 1103 /* first plt entry */ 1104 p = section_ptr_add(plt, 16); 1105 put32(p , 0xe52de004); 1106 put32(p + 4, 0xe59fe010); 1107 put32(p + 8, 0xe08fe00e); 1108 put32(p + 12, 0xe5bef008); 1109 } 1110 1111 if (s1->sym_attrs[sym_index].plt_thumb_stub) { 1112 p = section_ptr_add(plt, 20); 1113 put32(p , 0x4778); // bx pc 1114 put32(p+2, 0x46c0); // nop 1115 p += 4; 1116 } else 1117 p = section_ptr_add(plt, 16); 1118 put32(p , 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT 1119 put32(p+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset 1120 put32(p+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset 1121 put32(p+12, s1->got->data_offset); 1122 1123 /* the symbol is modified so that it will be relocated to 1124 the PLT */ 1125 if (s1->output_type == TCC_OUTPUT_EXE) 1126 offset = plt->data_offset - 16; 1127 } 1128 #elif defined(TCC_TARGET_C67) 1129 tcc_error("C67 got not implemented"); 1130 #elif defined(TCC_TARGET_IL) 1131 tcc_error("IL got not implemented"); 1132 #else 1133 #error unsupported CPU 1134 #endif 1135 index = put_elf_sym(s1->dynsym, offset, 1136 size, info, 0, sym->st_shndx, name); 1137 /* put a got entry */ 1138 put_elf_reloc(s1->dynsym, s1->got, 1139 s1->got->data_offset, 1140 reloc_type, index); 1141 } 1142 ptr = section_ptr_add(s1->got, PTR_SIZE); 1143 *ptr = 0; 963 if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) { 964 /* Hack alarm. We don't want to emit dynamic symbols 965 and symbol based relocs for STB_LOCAL symbols, but rather 966 want to resolve them directly. At this point the symbol 967 values aren't final yet, so we must defer this. We will later 968 have to create a RELATIVE reloc anyway, so we misuse the 969 relocation slot to smuggle the symbol reference until 970 fill_local_got_entries. Not that the sym_index is 971 relative to symtab_section, not s1->dynsym! Nevertheless 972 we use s1->dyn_sym so that if this is the first call 973 that got->reloc is correctly created. Also note that 974 RELATIVE relocs are not normally created for the .got, 975 so the types serves as a marker for later (and is retained 976 also for the final output, which is okay because then the 977 got is just normal data). */ 978 put_elf_reloc(s1->dynsym, s1->got, got_offset, R_RELATIVE, 979 sym_index); 980 } else { 981 if (0 == attr->dyn_index) 982 attr->dyn_index = set_elf_sym(s1->dynsym, sym->st_value, size, 983 info, 0, sym->st_shndx, name); 984 put_elf_reloc(s1->dynsym, s1->got, got_offset, dyn_reloc_type, 985 attr->dyn_index); 986 } 987 } else { 988 put_elf_reloc(symtab_section, s1->got, got_offset, dyn_reloc_type, 989 sym_index); 990 } 991 992 if (need_plt_entry) { 993 if (!s1->plt) { 994 s1->plt = new_section(s1, ".plt", SHT_PROGBITS, 995 SHF_ALLOC | SHF_EXECINSTR); 996 s1->plt->sh_entsize = 4; 997 } 998 999 attr->plt_offset = create_plt_entry(s1, got_offset, attr); 1000 1001 /* create a symbol 'sym@plt' for the PLT jump vector */ 1002 len = strlen(name); 1003 if (len > sizeof plt_name - 5) 1004 len = sizeof plt_name - 5; 1005 memcpy(plt_name, name, len); 1006 strcpy(plt_name + len, "@plt"); 1007 attr->plt_sym = put_elf_sym(s1->symtab, attr->plt_offset, sym->st_size, 1008 ELFW(ST_INFO)(STB_GLOBAL, STT_FUNC), 0, s1->plt->sh_num, plt_name); 1009 1010 } else { 1011 attr->got_offset = got_offset; 1012 } 1013 1014 return attr; 1144 1015 } 1145 1016 … … 1148 1019 { 1149 1020 Section *s; 1150 ElfW_Rel *rel , *rel_end;1021 ElfW_Rel *rel; 1151 1022 ElfW(Sym) *sym; 1152 int i, type, reloc_type, sym_index; 1023 int i, type, gotplt_entry, reloc_type, sym_index; 1024 struct sym_attr *attr; 1153 1025 1154 1026 for(i = 1; i < s1->nb_sections; i++) { … … 1159 1031 if (s->link != symtab_section) 1160 1032 continue; 1161 rel_end = (ElfW_Rel *)(s->data + s->data_offset); 1162 for(rel = (ElfW_Rel *)s->data; 1163 rel < rel_end; 1164 rel++) { 1033 for_each_elem(s, 0, rel, ElfW_Rel) { 1165 1034 type = ELFW(R_TYPE)(rel->r_info); 1166 switch(type) { 1167 #if defined(TCC_TARGET_I386) 1168 case R_386_GOT32: 1169 case R_386_GOTOFF: 1170 case R_386_GOTPC: 1171 case R_386_PLT32: 1172 if (!s1->got) 1173 build_got(s1); 1174 if (type == R_386_GOT32 || type == R_386_PLT32) { 1175 sym_index = ELFW(R_SYM)(rel->r_info); 1176 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; 1177 /* look at the symbol got offset. If none, then add one */ 1178 if (type == R_386_GOT32) 1179 reloc_type = R_386_GLOB_DAT; 1180 else 1181 reloc_type = R_386_JMP_SLOT; 1182 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, 1183 sym_index); 1184 } 1185 break; 1186 #elif defined(TCC_TARGET_ARM) 1187 case R_ARM_GOT_BREL: 1188 case R_ARM_GOTOFF32: 1189 case R_ARM_BASE_PREL: 1190 case R_ARM_PLT32: 1191 if (!s1->got) 1192 build_got(s1); 1193 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) { 1194 sym_index = ELFW(R_SYM)(rel->r_info); 1195 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; 1196 /* look at the symbol got offset. If none, then add one */ 1197 if (type == R_ARM_GOT_BREL) 1198 reloc_type = R_ARM_GLOB_DAT; 1199 else 1200 reloc_type = R_ARM_JUMP_SLOT; 1201 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, 1202 sym_index); 1203 } 1204 break; 1205 #elif defined(TCC_TARGET_C67) 1206 case R_C60_GOT32: 1207 case R_C60_GOTOFF: 1208 case R_C60_GOTPC: 1209 case R_C60_PLT32: 1210 if (!s1->got) 1211 build_got(s1); 1212 if (type == R_C60_GOT32 || type == R_C60_PLT32) { 1213 sym_index = ELFW(R_SYM)(rel->r_info); 1214 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; 1215 /* look at the symbol got offset. If none, then add one */ 1216 if (type == R_C60_GOT32) 1217 reloc_type = R_C60_GLOB_DAT; 1218 else 1219 reloc_type = R_C60_JMP_SLOT; 1220 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, 1221 sym_index); 1222 } 1223 break; 1224 #elif defined(TCC_TARGET_X86_64) 1225 case R_X86_64_GOT32: 1226 case R_X86_64_GOTTPOFF: 1227 case R_X86_64_GOTPCREL: 1228 case R_X86_64_PLT32: 1229 if (!s1->got) 1230 build_got(s1); 1231 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL || 1232 type == R_X86_64_PLT32) { 1233 sym_index = ELFW(R_SYM)(rel->r_info); 1234 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; 1235 /* look at the symbol got offset. If none, then add one */ 1236 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL) 1237 reloc_type = R_X86_64_GLOB_DAT; 1238 else 1239 reloc_type = R_X86_64_JUMP_SLOT; 1240 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, 1241 sym_index); 1242 } 1243 break; 1244 #elif defined(TCC_TARGET_IL) 1245 #else 1246 #error unsupported CPU 1247 #endif 1248 default: 1249 break; 1250 } 1251 } 1252 } 1253 } 1254 1255 ST_FUNC Section *new_symtab(TCCState *s1, 1256 const char *symtab_name, int sh_type, int sh_flags, 1257 const char *strtab_name, 1258 const char *hash_name, int hash_sh_flags) 1259 { 1260 Section *symtab, *strtab, *hash; 1261 int *ptr, nb_buckets; 1262 1263 symtab = new_section(s1, symtab_name, sh_type, sh_flags); 1264 symtab->sh_entsize = sizeof(ElfW(Sym)); 1265 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags); 1266 put_elf_str(strtab, ""); 1267 symtab->link = strtab; 1268 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL); 1269 1270 nb_buckets = 1; 1271 1272 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags); 1273 hash->sh_entsize = sizeof(int); 1274 symtab->hash = hash; 1275 hash->link = symtab; 1276 1277 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int)); 1278 ptr[0] = nb_buckets; 1279 ptr[1] = 1; 1280 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int)); 1281 return symtab; 1035 gotplt_entry = gotplt_entry_type(type); 1036 sym_index = ELFW(R_SYM)(rel->r_info); 1037 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; 1038 1039 if (gotplt_entry == NO_GOTPLT_ENTRY) { 1040 continue; 1041 } 1042 1043 /* Automatically create PLT/GOT [entry] if it is an undefined 1044 reference (resolved at runtime), or the symbol is absolute, 1045 probably created by tcc_add_symbol, and thus on 64-bit 1046 targets might be too far from application code. */ 1047 if (gotplt_entry == AUTO_GOTPLT_ENTRY) { 1048 if (sym->st_shndx == SHN_UNDEF) { 1049 ElfW(Sym) *esym; 1050 int dynindex; 1051 if (s1->output_type == TCC_OUTPUT_DLL && ! PCRELATIVE_DLLPLT) 1052 continue; 1053 /* Relocations for UNDEF symbols would normally need 1054 to be transferred into the executable or shared object. 1055 If that were done AUTO_GOTPLT_ENTRY wouldn't exist. 1056 But TCC doesn't do that (at least for exes), so we 1057 need to resolve all such relocs locally. And that 1058 means PLT slots for functions in DLLs and COPY relocs for 1059 data symbols. COPY relocs were generated in 1060 bind_exe_dynsyms (and the symbol adjusted to be defined), 1061 and for functions we were generated a dynamic symbol 1062 of function type. */ 1063 if (s1->dynsym) { 1064 /* dynsym isn't set for -run :-/ */ 1065 dynindex = get_sym_attr(s1, sym_index, 0)->dyn_index; 1066 esym = (ElfW(Sym) *)s1->dynsym->data + dynindex; 1067 if (dynindex 1068 && (ELFW(ST_TYPE)(esym->st_info) == STT_FUNC 1069 || (ELFW(ST_TYPE)(esym->st_info) == STT_NOTYPE 1070 && ELFW(ST_TYPE)(sym->st_info) == STT_FUNC))) 1071 goto jmp_slot; 1072 } 1073 } else if (!(sym->st_shndx == SHN_ABS 1074 #ifndef TCC_TARGET_ARM 1075 && PTR_SIZE == 8 1076 #endif 1077 )) 1078 continue; 1079 } 1080 1081 #ifdef TCC_TARGET_X86_64 1082 if ((type == R_X86_64_PLT32 || type == R_X86_64_PC32) && 1083 (ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT || 1084 ELFW(ST_BIND)(sym->st_info) == STB_LOCAL)) { 1085 rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32); 1086 continue; 1087 } 1088 #endif 1089 if (code_reloc(type)) { 1090 jmp_slot: 1091 reloc_type = R_JMP_SLOT; 1092 } else 1093 reloc_type = R_GLOB_DAT; 1094 1095 if (!s1->got) 1096 build_got(s1); 1097 1098 if (gotplt_entry == BUILD_GOT_ONLY) 1099 continue; 1100 1101 attr = put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, 1102 sym_index); 1103 1104 if (reloc_type == R_JMP_SLOT) 1105 rel->r_info = ELFW(R_INFO)(attr->plt_sym, type); 1106 } 1107 } 1282 1108 } 1283 1109 … … 1291 1117 } 1292 1118 1119 #ifndef TCC_TARGET_PE 1293 1120 static void add_init_array_defines(TCCState *s1, const char *section_name) 1294 1121 { … … 1297 1124 char sym_start[1024]; 1298 1125 char sym_end[1024]; 1299 1126 1300 1127 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1); 1301 1128 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1); … … 1309 1136 } 1310 1137 1311 add_elf_sym(symtab_section,1138 set_elf_sym(symtab_section, 1312 1139 0, 0, 1313 1140 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1314 1141 s->sh_num, sym_start); 1315 add_elf_sym(symtab_section,1142 set_elf_sym(symtab_section, 1316 1143 end_offset, 0, 1317 1144 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1318 1145 s->sh_num, sym_end); 1319 1146 } 1320 1321 ST_FUNC void tcc_add_bcheck(TCCState *s1) 1322 { 1323 #ifdef CONFIG_TCC_BCHECK 1324 unsigned long *ptr; 1325 Section *init_section; 1326 unsigned char *pinit; 1327 int sym_index; 1328 1329 if (0 == s1->do_bounds_check) 1330 return; 1331 1332 /* XXX: add an object file to do that */ 1333 ptr = section_ptr_add(bounds_section, sizeof(unsigned long)); 1334 *ptr = 0; 1335 add_elf_sym(symtab_section, 0, 0, 1336 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1337 bounds_section->sh_num, "__bounds_start"); 1338 #ifdef TCC_TARGET_I386 1339 if (s1->output_type != TCC_OUTPUT_MEMORY) { 1340 /* add 'call __bound_init()' in .init section */ 1341 init_section = find_section(s1, ".init"); 1342 pinit = section_ptr_add(init_section, 5); 1343 pinit[0] = 0xe8; 1344 put32(pinit + 1, -4); 1345 sym_index = find_elf_sym(symtab_section, "__bound_init"); 1346 put_elf_reloc(symtab_section, init_section, 1347 init_section->data_offset - 4, R_386_PC32, sym_index); 1348 } 1349 #endif 1350 #endif 1351 } 1352 1353 static inline int tcc_add_support(TCCState *s1, const char *filename) 1147 #endif 1148 1149 static int tcc_add_support(TCCState *s1, const char *filename) 1354 1150 { 1355 1151 char buf[1024]; … … 1358 1154 } 1359 1155 1156 ST_FUNC void tcc_add_bcheck(TCCState *s1) 1157 { 1158 #ifdef CONFIG_TCC_BCHECK 1159 addr_t *ptr; 1160 int sym_index; 1161 1162 if (0 == s1->do_bounds_check) 1163 return; 1164 /* XXX: add an object file to do that */ 1165 ptr = section_ptr_add(bounds_section, sizeof(*ptr)); 1166 *ptr = 0; 1167 set_elf_sym(symtab_section, 0, 0, 1168 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1169 bounds_section->sh_num, "__bounds_start"); 1170 /* pull bcheck.o from libtcc1.a */ 1171 sym_index = set_elf_sym(symtab_section, 0, 0, 1172 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1173 SHN_UNDEF, "__bound_init"); 1174 if (s1->output_type != TCC_OUTPUT_MEMORY) { 1175 /* add 'call __bound_init()' in .init section */ 1176 Section *init_section = find_section(s1, ".init"); 1177 unsigned char *pinit = section_ptr_add(init_section, 5); 1178 pinit[0] = 0xe8; 1179 write32le(pinit + 1, -4); 1180 put_elf_reloc(symtab_section, init_section, 1181 init_section->data_offset - 4, R_386_PC32, sym_index); 1182 /* R_386_PC32 = R_X86_64_PC32 = 2 */ 1183 } 1184 #endif 1185 } 1186 1360 1187 /* add tcc runtime libraries */ 1361 1188 ST_FUNC void tcc_add_runtime(TCCState *s1) 1362 1189 { 1363 1190 tcc_add_bcheck(s1); 1364 1191 tcc_add_pragma_libs(s1); 1365 1192 /* add libc */ 1366 1193 if (!s1->nostdlib) { 1367 tcc_add_library(s1, "c"); 1368 #ifdef CONFIG_USE_LIBGCC 1369 tcc_add_file(s1, TCC_LIBGCC); 1370 #elif !defined WITHOUT_LIBTCC 1371 tcc_add_support(s1, "libtcc1.a"); 1372 #endif 1194 tcc_add_library_err(s1, "c"); 1195 #ifdef TCC_LIBGCC 1196 if (!s1->static_link) { 1197 if (TCC_LIBGCC[0] == '/') 1198 tcc_add_file(s1, TCC_LIBGCC); 1199 else 1200 tcc_add_dll(s1, TCC_LIBGCC, 0); 1201 } 1202 #endif 1203 tcc_add_support(s1, TCC_LIBTCC1); 1373 1204 /* add crt end if not memory output */ 1374 1205 if (s1->output_type != TCC_OUTPUT_MEMORY) … … 1380 1211 sections are filled (for example after allocating common 1381 1212 symbols)) */ 1382 ST_FUNCvoid tcc_add_linker_symbols(TCCState *s1)1213 static void tcc_add_linker_symbols(TCCState *s1) 1383 1214 { 1384 1215 char buf[1024]; … … 1386 1217 Section *s; 1387 1218 1388 add_elf_sym(symtab_section,1219 set_elf_sym(symtab_section, 1389 1220 text_section->data_offset, 0, 1390 1221 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1391 1222 text_section->sh_num, "_etext"); 1392 add_elf_sym(symtab_section,1223 set_elf_sym(symtab_section, 1393 1224 data_section->data_offset, 0, 1394 1225 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1395 1226 data_section->sh_num, "_edata"); 1396 add_elf_sym(symtab_section,1227 set_elf_sym(symtab_section, 1397 1228 bss_section->data_offset, 0, 1398 1229 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1399 1230 bss_section->sh_num, "_end"); 1231 #ifndef TCC_TARGET_PE 1400 1232 /* horrible new standard ldscript defines */ 1401 1233 add_init_array_defines(s1, ".preinit_array"); 1402 1234 add_init_array_defines(s1, ".init_array"); 1403 1235 add_init_array_defines(s1, ".fini_array"); 1404 1236 #endif 1237 1405 1238 /* add start and stop symbols for sections whose name can be 1406 1239 expressed in C */ … … 1423 1256 } 1424 1257 snprintf(buf, sizeof(buf), "__start_%s", s->name); 1425 add_elf_sym(symtab_section,1258 set_elf_sym(symtab_section, 1426 1259 0, 0, 1427 1260 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1428 1261 s->sh_num, buf); 1429 1262 snprintf(buf, sizeof(buf), "__stop_%s", s->name); 1430 add_elf_sym(symtab_section,1263 set_elf_sym(symtab_section, 1431 1264 s->data_offset, 0, 1432 1265 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, … … 1437 1270 } 1438 1271 1272 ST_FUNC void resolve_common_syms(TCCState *s1) 1273 { 1274 ElfW(Sym) *sym; 1275 1276 /* Allocate common symbols in BSS. */ 1277 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { 1278 if (sym->st_shndx == SHN_COMMON) { 1279 /* symbol alignment is in st_value for SHN_COMMONs */ 1280 sym->st_value = section_add(bss_section, sym->st_size, 1281 sym->st_value); 1282 sym->st_shndx = bss_section->sh_num; 1283 } 1284 } 1285 1286 /* Now assign linker provided symbols their value. */ 1287 tcc_add_linker_symbols(s1); 1288 } 1289 1439 1290 static void tcc_output_binary(TCCState *s1, FILE *f, 1440 const int *sec tion_order)1291 const int *sec_order) 1441 1292 { 1442 1293 Section *s; … … 1445 1296 offset = 0; 1446 1297 for(i=1;i<s1->nb_sections;i++) { 1447 s = s1->sections[sec tion_order[i]];1298 s = s1->sections[sec_order[i]]; 1448 1299 if (s->sh_type != SHT_NOBITS && 1449 1300 (s->sh_flags & SHF_ALLOC)) { … … 1459 1310 } 1460 1311 1461 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 1462 #define HAVE_PHDR 1 1463 #define EXTRA_RELITEMS 14 1464 1465 /* move the relocation value from .dynsym to .got */ 1466 void patch_dynsym_undef(TCCState *s1, Section *s) 1467 { 1468 uint32_t *gotd = (void *)s1->got->data; 1469 ElfW(Sym) *sym, *sym_end; 1470 1471 gotd += 3; // dummy entries in .got 1472 /* relocate symbols in .dynsym */ 1473 sym_end = (ElfW(Sym) *)(s->data + s->data_offset); 1474 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) { 1475 if (sym->st_shndx == SHN_UNDEF) { 1476 *gotd++ = sym->st_value + 6; // XXX 6 is magic ? 1477 sym->st_value = 0; 1312 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) 1313 { 1314 int sym_index = ELFW(R_SYM) (rel->r_info); 1315 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index]; 1316 struct sym_attr *attr = get_sym_attr(s1, sym_index, 0); 1317 unsigned offset = attr->got_offset; 1318 1319 if (0 == offset) 1320 return; 1321 section_reserve(s1->got, offset + PTR_SIZE); 1322 #ifdef TCC_TARGET_X86_64 1323 write64le(s1->got->data + offset, sym->st_value); 1324 #else 1325 write32le(s1->got->data + offset, sym->st_value); 1326 #endif 1327 } 1328 1329 /* Perform relocation to GOT or PLT entries */ 1330 ST_FUNC void fill_got(TCCState *s1) 1331 { 1332 Section *s; 1333 ElfW_Rel *rel; 1334 int i; 1335 1336 for(i = 1; i < s1->nb_sections; i++) { 1337 s = s1->sections[i]; 1338 if (s->sh_type != SHT_RELX) 1339 continue; 1340 /* no need to handle got relocations */ 1341 if (s->link != symtab_section) 1342 continue; 1343 for_each_elem(s, 0, rel, ElfW_Rel) { 1344 switch (ELFW(R_TYPE) (rel->r_info)) { 1345 case R_X86_64_GOT32: 1346 case R_X86_64_GOTPCREL: 1347 case R_X86_64_GOTPCRELX: 1348 case R_X86_64_REX_GOTPCRELX: 1349 case R_X86_64_PLT32: 1350 fill_got_entry(s1, rel); 1351 break; 1352 } 1353 } 1354 } 1355 } 1356 1357 /* See put_got_entry for a description. This is the second stage 1358 where GOT references to local defined symbols are rewritten. */ 1359 static void fill_local_got_entries(TCCState *s1) 1360 { 1361 ElfW_Rel *rel; 1362 for_each_elem(s1->got->reloc, 0, rel, ElfW_Rel) { 1363 if (ELFW(R_TYPE)(rel->r_info) == R_RELATIVE) { 1364 int sym_index = ELFW(R_SYM) (rel->r_info); 1365 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index]; 1366 struct sym_attr *attr = get_sym_attr(s1, sym_index, 0); 1367 unsigned offset = attr->got_offset; 1368 if (offset != rel->r_offset - s1->got->sh_addr) 1369 tcc_error_noabort("huh"); 1370 rel->r_info = ELFW(R_INFO)(0, R_RELATIVE); 1371 #if SHT_RELX == SHT_RELA 1372 rel->r_addend = sym->st_value; 1373 #else 1374 /* All our REL architectures also happen to be 32bit LE. */ 1375 write32le(s1->got->data + offset, sym->st_value); 1376 #endif 1478 1377 } 1479 1378 } 1480 1379 } 1481 #else 1482 #define HAVE_PHDR 0 1483 #define EXTRA_RELITEMS 9 1484 1485 /* zero plt offsets of weak symbols in .dynsym */ 1486 void patch_dynsym_undef(TCCState *s1, Section *s) 1487 { 1488 ElfW(Sym) *sym, *sym_end; 1489 1490 sym_end = (ElfW(Sym) *)(s->data + s->data_offset); 1491 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) 1492 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK) 1493 sym->st_value = 0; 1494 } 1495 #endif 1496 1497 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) 1498 { 1499 int sym_index = ELFW(R_SYM) (rel->r_info); 1500 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index]; 1501 unsigned long offset; 1502 1503 if (sym_index >= s1->nb_sym_attrs) 1504 return; 1505 offset = s1->sym_attrs[sym_index].got_offset; 1506 section_reserve(s1->got, offset + PTR_SIZE); 1507 #ifdef TCC_TARGET_X86_64 1508 /* only works for x86-64 */ 1509 put32(s1->got->data + offset + 4, sym->st_value >> 32); 1510 #endif 1511 put32(s1->got->data + offset, sym->st_value & 0xffffffff); 1512 } 1513 1514 ST_FUNC void fill_got(TCCState *s1) 1515 { 1516 Section *s; 1517 ElfW_Rel *rel, *rel_end; 1518 int i; 1519 1520 for(i = 1; i < s1->nb_sections; i++) { 1521 s = s1->sections[i]; 1522 if (s->sh_type != SHT_RELX) 1523 continue; 1524 /* no need to handle got relocations */ 1525 if (s->link != symtab_section) 1526 continue; 1527 rel_end = (ElfW_Rel *) (s->data + s->data_offset); 1528 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) { 1529 switch (ELFW(R_TYPE) (rel->r_info)) { 1530 case R_X86_64_GOT32: 1531 case R_X86_64_GOTPCREL: 1532 case R_X86_64_PLT32: 1533 fill_got_entry(s1, rel); 1534 break; 1535 } 1536 } 1537 } 1538 } 1539 1540 1541 /* output an ELF file */ 1542 /* XXX: suppress unneeded sections */ 1543 static int elf_output_file(TCCState *s1, const char *filename) 1544 { 1545 ElfW(Ehdr) ehdr; 1546 FILE *f; 1547 int fd, mode, ret; 1548 int *section_order; 1549 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k; 1550 long long tmp; 1551 addr_t addr; 1552 Section *strsec, *s; 1553 ElfW(Shdr) shdr, *sh; 1554 ElfW(Phdr) *phdr, *ph; 1555 Section *interp, *dynamic, *dynstr; 1556 unsigned long saved_dynamic_data_offset; 1557 ElfW(Sym) *sym; 1558 int type, file_type; 1559 addr_t rel_addr, rel_size; 1560 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 1561 addr_t bss_addr, bss_size; 1562 #endif 1563 1564 file_type = s1->output_type; 1565 s1->nb_errors = 0; 1566 1567 if (file_type != TCC_OUTPUT_OBJ) { 1568 tcc_add_runtime(s1); 1569 } 1570 1571 phdr = NULL; 1572 section_order = NULL; 1573 interp = NULL; 1574 dynamic = NULL; 1575 dynstr = NULL; /* avoid warning */ 1576 saved_dynamic_data_offset = 0; /* avoid warning */ 1577 1578 if (file_type != TCC_OUTPUT_OBJ) { 1579 relocate_common_syms(); 1580 1581 tcc_add_linker_symbols(s1); 1582 1583 if (!s1->static_link) { 1584 const char *name; 1585 int sym_index, index; 1586 ElfW(Sym) *esym, *sym_end; 1587 1588 if (file_type == TCC_OUTPUT_EXE) { 1589 char *ptr; 1590 /* allow override the dynamic loader */ 1591 const char *elfint = getenv("LD_SO"); 1592 if (elfint == NULL) 1593 elfint = CONFIG_TCC_ELFINTERP; 1594 /* add interpreter section only if executable */ 1595 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC); 1596 interp->sh_addralign = 1; 1597 ptr = section_ptr_add(interp, 1+strlen(elfint)); 1598 strcpy(ptr, elfint); 1599 } 1600 1601 /* add dynamic symbol table */ 1602 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC, 1603 ".dynstr", 1604 ".hash", SHF_ALLOC); 1605 dynstr = s1->dynsym->link; 1606 1607 /* add dynamic section */ 1608 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC, 1609 SHF_ALLOC | SHF_WRITE); 1610 dynamic->link = dynstr; 1611 dynamic->sh_entsize = sizeof(ElfW(Dyn)); 1612 1613 /* add PLT */ 1614 s1->plt = new_section(s1, ".plt", SHT_PROGBITS, 1615 SHF_ALLOC | SHF_EXECINSTR); 1616 s1->plt->sh_entsize = 4; 1617 1618 build_got(s1); 1619 1620 /* scan for undefined symbols and see if they are in the 1621 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC 1622 is found, then we add it in the PLT. If a symbol 1623 STT_OBJECT is found, we add it in the .bss section with 1624 a suitable relocation */ 1625 sym_end = (ElfW(Sym) *)(symtab_section->data + 1626 symtab_section->data_offset); 1627 if (file_type == TCC_OUTPUT_EXE) { 1628 for(sym = (ElfW(Sym) *)symtab_section->data + 1; 1629 sym < sym_end; 1630 sym++) { 1631 if (sym->st_shndx == SHN_UNDEF) { 1632 name = symtab_section->link->data + sym->st_name; 1633 sym_index = find_elf_sym(s1->dynsymtab_section, name); 1634 if (sym_index) { 1635 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index]; 1636 type = ELFW(ST_TYPE)(esym->st_info); 1637 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) { 1638 /* Indirect functions shall have STT_FUNC type 1639 * in executable dynsym section. Indeed, a dlsym 1640 * call following a lazy resolution would pick 1641 * the symbol value from the executable dynsym 1642 * entry which would contain the address of the 1643 * function wanted by the caller of dlsym 1644 * instead of the address of the function that 1645 * would return that address */ 1646 put_got_entry(s1, R_JMP_SLOT, esym->st_size, 1647 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), 1648 sym - (ElfW(Sym) *)symtab_section->data); 1649 } else if (type == STT_OBJECT) { 1650 unsigned long offset; 1651 ElfW(Sym) *dynsym, *dynsym_end; 1652 offset = bss_section->data_offset; 1653 /* XXX: which alignment ? */ 1654 offset = (offset + 16 - 1) & -16; 1655 index = put_elf_sym(s1->dynsym, offset, esym->st_size, 1656 esym->st_info, 0, 1657 bss_section->sh_num, name); 1658 // Ensure R_COPY works for weak symbol aliases 1659 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) { 1660 dynsym_end = (ElfW(Sym) *) 1661 (s1->dynsymtab_section->data + 1662 s1->dynsymtab_section->data_offset); 1663 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1; 1664 dynsym < dynsym_end; dynsym++) { 1665 if ((dynsym->st_value == esym->st_value) 1666 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) { 1667 char *dynname; 1668 dynname = s1->dynsymtab_section->link->data 1669 + dynsym->st_name; 1670 put_elf_sym(s1->dynsym, offset, 1671 dynsym->st_size, 1672 dynsym->st_info, 0, 1673 bss_section->sh_num, 1674 dynname); 1675 break; 1676 } 1677 } 1678 } 1679 put_elf_reloc(s1->dynsym, bss_section, 1680 offset, R_COPY, index); 1681 offset += esym->st_size; 1682 bss_section->data_offset = offset; 1683 } 1684 } else { 1685 /* STB_WEAK undefined symbols are accepted */ 1686 /* XXX: _fp_hw seems to be part of the ABI, so we ignore 1687 it */ 1688 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK || 1689 !strcmp(name, "_fp_hw")) { 1690 } else { 1691 tcc_error_noabort("undefined symbol '%s'", name); 1692 } 1693 } 1694 } else if (s1->rdynamic && 1695 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { 1696 /* if -rdynamic option, then export all non 1697 local symbols */ 1698 name = symtab_section->link->data + sym->st_name; 1699 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, 1700 sym->st_info, 0, 1701 sym->st_shndx, name); 1702 } 1703 } 1704 1705 if (s1->nb_errors) 1706 goto fail; 1707 1708 /* now look at unresolved dynamic symbols and export 1709 corresponding symbol */ 1710 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data + 1711 s1->dynsymtab_section->data_offset); 1712 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1; 1713 esym < sym_end; 1714 esym++) { 1715 if (esym->st_shndx == SHN_UNDEF) { 1716 name = s1->dynsymtab_section->link->data + esym->st_name; 1717 sym_index = find_elf_sym(symtab_section, name); 1718 if (sym_index) { 1719 /* XXX: avoid adding a symbol if already 1720 present because of -rdynamic ? */ 1721 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; 1722 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, 1723 sym->st_info, 0, 1724 sym->st_shndx, name); 1725 } else { 1726 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) { 1727 /* weak symbols can stay undefined */ 1728 } else { 1729 tcc_warning("undefined dynamic symbol '%s'", name); 1380 1381 /* Bind symbols of executable: resolve undefined symbols from exported symbols 1382 in shared libraries and export non local defined symbols to shared libraries 1383 if -rdynamic switch was given on command line */ 1384 static void bind_exe_dynsyms(TCCState *s1) 1385 { 1386 const char *name; 1387 int sym_index, index; 1388 ElfW(Sym) *sym, *esym; 1389 int type; 1390 1391 /* Resolve undefined symbols from dynamic symbols. When there is a match: 1392 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT 1393 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */ 1394 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { 1395 if (sym->st_shndx == SHN_UNDEF) { 1396 name = (char *) symtab_section->link->data + sym->st_name; 1397 sym_index = find_elf_sym(s1->dynsymtab_section, name); 1398 if (sym_index) { 1399 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index]; 1400 type = ELFW(ST_TYPE)(esym->st_info); 1401 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) { 1402 /* Indirect functions shall have STT_FUNC type in executable 1403 * dynsym section. Indeed, a dlsym call following a lazy 1404 * resolution would pick the symbol value from the 1405 * executable dynsym entry which would contain the address 1406 * of the function wanted by the caller of dlsym instead of 1407 * the address of the function that would return that 1408 * address */ 1409 int dynindex 1410 = put_elf_sym(s1->dynsym, 0, esym->st_size, 1411 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), 0, 0, 1412 name); 1413 int index = sym - (ElfW(Sym) *) symtab_section->data; 1414 get_sym_attr(s1, index, 1)->dyn_index = dynindex; 1415 } else if (type == STT_OBJECT) { 1416 unsigned long offset; 1417 ElfW(Sym) *dynsym; 1418 offset = bss_section->data_offset; 1419 /* XXX: which alignment ? */ 1420 offset = (offset + 16 - 1) & -16; 1421 set_elf_sym (s1->symtab, offset, esym->st_size, 1422 esym->st_info, 0, bss_section->sh_num, name); 1423 index = put_elf_sym(s1->dynsym, offset, esym->st_size, 1424 esym->st_info, 0, bss_section->sh_num, 1425 name); 1426 1427 /* Ensure R_COPY works for weak symbol aliases */ 1428 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) { 1429 for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) { 1430 if ((dynsym->st_value == esym->st_value) 1431 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) { 1432 char *dynname = (char *) s1->dynsymtab_section->link->data 1433 + dynsym->st_name; 1434 put_elf_sym(s1->dynsym, offset, dynsym->st_size, 1435 dynsym->st_info, 0, 1436 bss_section->sh_num, dynname); 1437 break; 1730 1438 } 1731 1439 } 1732 1440 } 1441 1442 put_elf_reloc(s1->dynsym, bss_section, 1443 offset, R_COPY, index); 1444 offset += esym->st_size; 1445 bss_section->data_offset = offset; 1733 1446 } 1734 1447 } else { 1735 int nb_syms; 1736 /* shared library case : we simply export all the global symbols */ 1737 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym)); 1738 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms); 1739 for(sym = (ElfW(Sym) *)symtab_section->data + 1; 1740 sym < sym_end; 1741 sym++) { 1742 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { 1743 #if defined(TCC_OUTPUT_DLL_WITH_PLT) 1744 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC || 1745 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC) 1746 && sym->st_shndx == SHN_UNDEF) { 1747 int visibility = ELFW(ST_BIND)(sym->st_info); 1748 put_got_entry(s1, R_JMP_SLOT, sym->st_size, 1749 ELFW(ST_INFO)(visibility,STT_FUNC), 1750 sym - (ElfW(Sym) *)symtab_section->data); 1751 } 1752 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) { 1753 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size, 1754 sym->st_info, 1755 sym - (ElfW(Sym) *)symtab_section->data); 1756 } 1757 else 1758 #endif 1759 { 1760 name = symtab_section->link->data + sym->st_name; 1761 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, 1762 sym->st_info, 0, 1763 sym->st_shndx, name); 1764 s1->symtab_to_dynsym[sym - 1765 (ElfW(Sym) *)symtab_section->data] = 1766 index; 1767 } 1768 } 1448 /* STB_WEAK undefined symbols are accepted */ 1449 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */ 1450 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK || 1451 !strcmp(name, "_fp_hw")) { 1452 } else { 1453 tcc_error_noabort("undefined symbol '%s'", name); 1769 1454 } 1770 1455 } 1771 1772 build_got_entries(s1); 1773 1774 /* add a list of needed dlls */ 1775 for(i = 0; i < s1->nb_loaded_dlls; i++) { 1776 DLLReference *dllref = s1->loaded_dlls[i]; 1777 if (dllref->level == 0) 1778 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name)); 1779 } 1780 1781 if (s1->rpath) 1782 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath)); 1783 1784 /* XXX: currently, since we do not handle PIC code, we 1785 must relocate the readonly segments */ 1786 if (file_type == TCC_OUTPUT_DLL) { 1787 if (s1->soname) 1788 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname)); 1789 put_dt(dynamic, DT_TEXTREL, 0); 1790 } 1791 1792 if (s1->symbolic) 1793 put_dt(dynamic, DT_SYMBOLIC, 0); 1794 1795 /* add necessary space for other entries */ 1796 saved_dynamic_data_offset = dynamic->data_offset; 1797 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS; 1798 } else { 1799 /* still need to build got entries in case of static link */ 1800 build_got_entries(s1); 1801 } 1802 } 1803 1804 memset(&ehdr, 0, sizeof(ehdr)); 1805 1806 /* we add a section for symbols */ 1807 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0); 1808 put_elf_str(strsec, ""); 1809 1810 /* compute number of sections */ 1811 shnum = s1->nb_sections; 1812 1813 /* this array is used to reorder sections in the output file */ 1814 section_order = tcc_malloc(sizeof(int) * shnum); 1815 section_order[0] = 0; 1816 sh_order_index = 1; 1817 1818 /* compute number of program headers */ 1819 switch(file_type) { 1820 default: 1821 case TCC_OUTPUT_OBJ: 1822 phnum = 0; 1823 break; 1824 case TCC_OUTPUT_EXE: 1825 if (!s1->static_link) 1826 phnum = 4 + HAVE_PHDR; 1827 else 1828 phnum = 2; 1829 break; 1830 case TCC_OUTPUT_DLL: 1831 phnum = 3; 1832 break; 1833 } 1834 1835 /* allocate strings for section names and decide if an unallocated 1836 section should be output */ 1837 /* NOTE: the strsec section comes last, so its size is also 1838 correct ! */ 1456 } else if (s1->rdynamic && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { 1457 /* if -rdynamic option, then export all non local symbols */ 1458 name = (char *) symtab_section->link->data + sym->st_name; 1459 set_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info, 1460 0, sym->st_shndx, name); 1461 } 1462 } 1463 } 1464 1465 /* Bind symbols of libraries: export all non local symbols of executable that 1466 are referenced by shared libraries. The reason is that the dynamic loader 1467 search symbol first in executable and then in libraries. Therefore a 1468 reference to a symbol already defined by a library can still be resolved by 1469 a symbol in the executable. */ 1470 static void bind_libs_dynsyms(TCCState *s1) 1471 { 1472 const char *name; 1473 int sym_index; 1474 ElfW(Sym) *sym, *esym; 1475 1476 for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) { 1477 name = (char *) s1->dynsymtab_section->link->data + esym->st_name; 1478 sym_index = find_elf_sym(symtab_section, name); 1479 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; 1480 if (sym_index && sym->st_shndx != SHN_UNDEF 1481 && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { 1482 set_elf_sym(s1->dynsym, sym->st_value, sym->st_size, 1483 sym->st_info, 0, sym->st_shndx, name); 1484 } else if (esym->st_shndx == SHN_UNDEF) { 1485 /* weak symbols can stay undefined */ 1486 if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK) 1487 tcc_warning("undefined dynamic symbol '%s'", name); 1488 } 1489 } 1490 } 1491 1492 /* Export all non local symbols. This is used by shared libraries so that the 1493 non local symbols they define can resolve a reference in another shared 1494 library or in the executable. Correspondingly, it allows undefined local 1495 symbols to be resolved by other shared libraries or by the executable. */ 1496 static void export_global_syms(TCCState *s1) 1497 { 1498 int dynindex, index; 1499 const char *name; 1500 ElfW(Sym) *sym; 1501 1502 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { 1503 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { 1504 name = (char *) symtab_section->link->data + sym->st_name; 1505 dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, 1506 sym->st_info, 0, sym->st_shndx, name); 1507 index = sym - (ElfW(Sym) *) symtab_section->data; 1508 get_sym_attr(s1, index, 1)->dyn_index = dynindex; 1509 } 1510 } 1511 } 1512 1513 /* Allocate strings for section names and decide if an unallocated section 1514 should be output. 1515 NOTE: the strsec section comes last, so its size is also correct ! */ 1516 static int alloc_sec_names(TCCState *s1, int file_type, Section *strsec) 1517 { 1518 int i; 1519 Section *s; 1520 int textrel = 0; 1521 1522 /* Allocate strings for section names */ 1839 1523 for(i = 1; i < s1->nb_sections; i++) { 1840 1524 s = s1->sections[i]; 1841 s->sh_name = put_elf_str(strsec, s->name);1842 #if 0 //gr1843 printf("section: f=%08x t=%08x i=%08x %s %s\n",1844 s->sh_flags,1845 s->sh_type,1846 s->sh_info,1847 s->name,1848 s->reloc ? s->reloc->name : "n"1849 );1850 #endif1851 1525 /* when generating a DLL, we include relocations but we may 1852 1526 patch them */ 1853 if (file_type == TCC_OUTPUT_DLL && 1854 s->sh_type == SHT_RELX && 1855 !(s->sh_flags & SHF_ALLOC)) { 1856 /* //gr: avoid bogus relocs for empty (debug) sections */ 1857 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC) 1858 prepare_dynamic_rel(s1, s); 1859 else if (s1->do_debug) 1860 s->sh_size = s->data_offset; 1527 if (file_type == TCC_OUTPUT_DLL && 1528 s->sh_type == SHT_RELX && 1529 !(s->sh_flags & SHF_ALLOC) && 1530 (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC) && 1531 prepare_dynamic_rel(s1, s)) { 1532 if (s1->sections[s->sh_info]->sh_flags & SHF_EXECINSTR) 1533 textrel = 1; 1861 1534 } else if (s1->do_debug || 1862 file_type == TCC_OUTPUT_OBJ || 1535 file_type == TCC_OUTPUT_OBJ || 1863 1536 (s->sh_flags & SHF_ALLOC) || 1864 1537 i == (s1->nb_sections - 1)) { 1865 1538 /* we output all sections if debug or object file */ 1866 1539 s->sh_size = s->data_offset; 1867 1540 } 1868 } 1869 1870 /* allocate program segment headers */ 1871 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr))); 1872 1873 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { 1541 if (s->sh_size || (s->sh_flags & SHF_ALLOC)) 1542 s->sh_name = put_elf_str(strsec, s->name); 1543 } 1544 strsec->sh_size = strsec->data_offset; 1545 return textrel; 1546 } 1547 1548 /* Info to be copied in dynamic section */ 1549 struct dyn_inf { 1550 Section *dynamic; 1551 Section *dynstr; 1552 unsigned long data_offset; 1553 addr_t rel_addr; 1554 addr_t rel_size; 1555 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 1556 addr_t bss_addr; 1557 addr_t bss_size; 1558 #endif 1559 }; 1560 1561 /* Assign sections to segments and decide how are sections laid out when loaded 1562 in memory. This function also fills corresponding program headers. */ 1563 static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, 1564 Section *interp, Section* strsec, 1565 struct dyn_inf *dyninf, int *sec_order) 1566 { 1567 int i, j, k, file_type, sh_order_index, file_offset; 1568 unsigned long s_align; 1569 long long tmp; 1570 addr_t addr; 1571 ElfW(Phdr) *ph; 1572 Section *s; 1573 1574 file_type = s1->output_type; 1575 sh_order_index = 1; 1576 file_offset = 0; 1577 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) 1874 1578 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr)); 1875 } else { 1876 file_offset = 0; 1877 } 1579 s_align = ELF_PAGE_SIZE; 1580 if (s1->section_align) 1581 s_align = s1->section_align; 1582 1878 1583 if (phnum > 0) { 1879 /* compute section to program header mapping */ 1880 if (s1->has_text_addr) { 1584 if (s1->has_text_addr) { 1881 1585 int a_offset, p_offset; 1882 1586 addr = s1->text_addr; 1883 1587 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset % 1884 1588 ELF_PAGE_SIZE */ 1885 a_offset = (int) (addr & (s 1->section_align - 1));1886 p_offset = file_offset & (s 1->section_align - 1);1887 if (a_offset < p_offset) 1888 a_offset += s 1->section_align;1589 a_offset = (int) (addr & (s_align - 1)); 1590 p_offset = file_offset & (s_align - 1); 1591 if (a_offset < p_offset) 1592 a_offset += s_align; 1889 1593 file_offset += (a_offset - p_offset); 1890 1594 } else { … … 1894 1598 addr = ELF_START_ADDR; 1895 1599 /* compute address after headers */ 1896 addr += (file_offset & (s1->section_align - 1)); 1897 } 1898 1600 addr += (file_offset & (s_align - 1)); 1601 } 1602 1603 ph = &phdr[0]; 1604 /* Leave one program headers for the program interpreter and one for 1605 the program header table itself if needed. These are done later as 1606 they require section layout to be done first. */ 1607 if (interp) 1608 ph += 2; 1609 1899 1610 /* dynamic relocation table information, for .dynamic section */ 1900 rel_size = 0; 1901 rel_addr = 0; 1902 1611 dyninf->rel_addr = dyninf->rel_size = 0; 1903 1612 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 1904 bss_addr = bss_size = 0; 1905 #endif 1906 /* leave one program header for the program interpreter */ 1907 ph = &phdr[0]; 1908 if (interp) 1909 ph += 1 + HAVE_PHDR; 1613 dyninf->bss_addr = dyninf->bss_size = 0; 1614 #endif 1910 1615 1911 1616 for(j = 0; j < 2; j++) { … … 1915 1620 else 1916 1621 ph->p_flags = PF_R | PF_W; 1917 ph->p_align = s1->section_align; 1918 1919 /* we do the following ordering: interp, symbol tables, 1920 relocations, progbits, nobits */ 1622 ph->p_align = s_align; 1623 1624 /* Decide the layout of sections loaded in memory. This must 1625 be done before program headers are filled since they contain 1626 info about the layout. We do the following ordering: interp, 1627 symbol tables, relocations, progbits, nobits */ 1921 1628 /* XXX: do faster and simpler sorting */ 1922 1629 for(k = 0; k < 5; k++) { … … 1925 1632 /* compute if section should be included */ 1926 1633 if (j == 0) { 1927 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != 1634 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != 1928 1635 SHF_ALLOC) 1929 1636 continue; 1930 1637 } else { 1931 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != 1638 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != 1932 1639 (SHF_ALLOC | SHF_WRITE)) 1933 1640 continue; … … 1951 1658 continue; 1952 1659 } 1953 sec tion_order[sh_order_index++] = i;1660 sec_order[sh_order_index++] = i; 1954 1661 1955 1662 /* section matches: we align it and add its size */ 1956 1663 tmp = addr; 1957 addr = (addr + s->sh_addralign - 1) & 1664 addr = (addr + s->sh_addralign - 1) & 1958 1665 ~(s->sh_addralign - 1); 1959 1666 file_offset += (int) ( addr - tmp ); 1960 1667 s->sh_offset = file_offset; 1961 1668 s->sh_addr = addr; 1962 1669 1963 1670 /* update program header infos */ 1964 1671 if (ph->p_offset == 0) { … … 1970 1677 if (s->sh_type == SHT_RELX) { 1971 1678 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 1972 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {1973 rel_addr = addr;1974 rel_size += s->sh_size; // XXX only first rel. 1975 1976 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {1977 bss_addr = addr;1978 bss_size = s->sh_size; // XXX only first rel. 1979 1679 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { 1680 dyninf->rel_addr = addr; 1681 dyninf->rel_size += s->sh_size; /* XXX only first rel. */ 1682 } 1683 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { 1684 dyninf->bss_addr = addr; 1685 dyninf->bss_size = s->sh_size; /* XXX only first rel. */ 1686 } 1980 1687 #else 1981 if ( rel_size == 0)1982 rel_addr = addr;1983 rel_size += s->sh_size;1688 if (dyninf->rel_size == 0) 1689 dyninf->rel_addr = addr; 1690 dyninf->rel_size += s->sh_size; 1984 1691 #endif 1985 1692 } … … 1989 1696 } 1990 1697 } 1698 if (j == 0) { 1699 /* Make the first PT_LOAD segment include the program 1700 headers itself (and the ELF header as well), it'll 1701 come out with same memory use but will make various 1702 tools like binutils strip work better. */ 1703 ph->p_offset &= ~(ph->p_align - 1); 1704 ph->p_vaddr &= ~(ph->p_align - 1); 1705 ph->p_paddr &= ~(ph->p_align - 1); 1706 } 1991 1707 ph->p_filesz = file_offset - ph->p_offset; 1992 1708 ph->p_memsz = addr - ph->p_vaddr; … … 1996 1712 /* if in the middle of a page, we duplicate the page in 1997 1713 memory so that one copy is RX and the other is RW */ 1998 if ((addr & (s 1->section_align - 1)) != 0)1999 addr += s 1->section_align;1714 if ((addr & (s_align - 1)) != 0) 1715 addr += s_align; 2000 1716 } else { 2001 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1); 2002 file_offset = (file_offset + s1->section_align - 1) & 2003 ~(s1->section_align - 1); 1717 addr = (addr + s_align - 1) & ~(s_align - 1); 1718 file_offset = (file_offset + s_align - 1) & ~(s_align - 1); 2004 1719 } 2005 1720 } 2006 1721 } 2007 2008 /* if interpreter, then add corresponing program header */2009 if (interp) {2010 ph = &phdr[0];2011 2012 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)2013 {2014 int len = phnum * sizeof(ElfW(Phdr));2015 2016 ph->p_type = PT_PHDR;2017 ph->p_offset = sizeof(ElfW(Ehdr));2018 ph->p_vaddr = interp->sh_addr - len;2019 ph->p_paddr = ph->p_vaddr;2020 ph->p_filesz = ph->p_memsz = len;2021 ph->p_flags = PF_R | PF_X;2022 ph->p_align = 4; // interp->sh_addralign;2023 ph++;2024 }2025 #endif2026 2027 ph->p_type = PT_INTERP;2028 ph->p_offset = interp->sh_offset;2029 ph->p_vaddr = interp->sh_addr;2030 ph->p_paddr = ph->p_vaddr;2031 ph->p_filesz = interp->sh_size;2032 ph->p_memsz = interp->sh_size;2033 ph->p_flags = PF_R;2034 ph->p_align = interp->sh_addralign;2035 }2036 2037 /* if dynamic section, then add corresponing program header */2038 if (dynamic) {2039 ElfW(Sym) *sym_end;2040 2041 ph = &phdr[phnum - 1];2042 2043 ph->p_type = PT_DYNAMIC;2044 ph->p_offset = dynamic->sh_offset;2045 ph->p_vaddr = dynamic->sh_addr;2046 ph->p_paddr = ph->p_vaddr;2047 ph->p_filesz = dynamic->sh_size;2048 ph->p_memsz = dynamic->sh_size;2049 ph->p_flags = PF_R | PF_W;2050 ph->p_align = dynamic->sh_addralign;2051 2052 /* put GOT dynamic section address */2053 put32(s1->got->data, dynamic->sh_addr);2054 2055 /* relocate the PLT */2056 if (file_type == TCC_OUTPUT_EXE2057 #if defined(TCC_OUTPUT_DLL_WITH_PLT)2058 || file_type == TCC_OUTPUT_DLL2059 #endif2060 ) {2061 uint8_t *p, *p_end;2062 2063 p = s1->plt->data;2064 p_end = p + s1->plt->data_offset;2065 if (p < p_end) {2066 #if defined(TCC_TARGET_I386)2067 put32(p + 2, get32(p + 2) + s1->got->sh_addr);2068 put32(p + 8, get32(p + 8) + s1->got->sh_addr);2069 p += 16;2070 while (p < p_end) {2071 put32(p + 2, get32(p + 2) + s1->got->sh_addr);2072 p += 16;2073 }2074 #elif defined(TCC_TARGET_X86_64)2075 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;2076 put32(p + 2, get32(p + 2) + x);2077 put32(p + 8, get32(p + 8) + x - 6);2078 p += 16;2079 while (p < p_end) {2080 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);2081 p += 16;2082 }2083 #elif defined(TCC_TARGET_ARM)2084 int x;2085 x=s1->got->sh_addr - s1->plt->sh_addr - 12;2086 p += 16;2087 while (p < p_end) {2088 if (get32(p) == 0x46c04778) /* PLT Thumb stub present */2089 p += 4;2090 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);2091 p += 16;2092 }2093 #elif defined(TCC_TARGET_C67)2094 /* XXX: TODO */2095 #elif defined(TCC_TARGET_IL)2096 #else2097 #error unsupported CPU2098 #endif2099 }2100 }2101 2102 /* relocate symbols in .dynsym */2103 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);2104 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;2105 sym < sym_end;2106 sym++) {2107 if (sym->st_shndx == SHN_UNDEF) {2108 /* relocate to the PLT if the symbol corresponds2109 to a PLT entry */2110 if (sym->st_value)2111 sym->st_value += s1->plt->sh_addr;2112 } else if (sym->st_shndx < SHN_LORESERVE) {2113 /* do symbol relocation */2114 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;2115 }2116 }2117 2118 /* put dynamic section entries */2119 dynamic->data_offset = saved_dynamic_data_offset;2120 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);2121 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);2122 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);2123 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);2124 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));2125 #ifdef TCC_TARGET_X86_642126 put_dt(dynamic, DT_RELA, rel_addr);2127 put_dt(dynamic, DT_RELASZ, rel_size);2128 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));2129 #else2130 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)2131 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);2132 put_dt(dynamic, DT_PLTRELSZ, rel_size);2133 put_dt(dynamic, DT_JMPREL, rel_addr);2134 put_dt(dynamic, DT_PLTREL, DT_REL);2135 put_dt(dynamic, DT_REL, bss_addr);2136 put_dt(dynamic, DT_RELSZ, bss_size);2137 #else2138 put_dt(dynamic, DT_REL, rel_addr);2139 put_dt(dynamic, DT_RELSZ, rel_size);2140 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));2141 #endif2142 #endif2143 if (s1->do_debug)2144 put_dt(dynamic, DT_DEBUG, 0);2145 put_dt(dynamic, DT_NULL, 0);2146 }2147 2148 ehdr.e_phentsize = sizeof(ElfW(Phdr));2149 ehdr.e_phnum = phnum;2150 ehdr.e_phoff = sizeof(ElfW(Ehdr));2151 1722 } 2152 1723 … … 2156 1727 if (phnum > 0 && (s->sh_flags & SHF_ALLOC)) 2157 1728 continue; 2158 sec tion_order[sh_order_index++] = i;2159 2160 file_offset = (file_offset + s->sh_addralign - 1) & 1729 sec_order[sh_order_index++] = i; 1730 1731 file_offset = (file_offset + s->sh_addralign - 1) & 2161 1732 ~(s->sh_addralign - 1); 2162 1733 s->sh_offset = file_offset; … … 2164 1735 file_offset += s->sh_size; 2165 1736 } 2166 2167 /* if building executable or DLL, then relocate each section 2168 except the GOT which is already relocated */ 2169 if (file_type != TCC_OUTPUT_OBJ) { 2170 relocate_syms(s1, 0); 2171 2172 if (s1->nb_errors != 0) { 2173 fail: 2174 ret = -1; 2175 goto the_end; 2176 } 2177 2178 /* relocate sections */ 2179 /* XXX: ignore sections with allocated relocations ? */ 2180 for(i = 1; i < s1->nb_sections; i++) { 2181 s = s1->sections[i]; 2182 if (s->reloc && s != s1->got) 2183 relocate_section(s1, s); 2184 } 2185 2186 /* relocate relocation entries if the relocation tables are 2187 allocated in the executable */ 2188 for(i = 1; i < s1->nb_sections; i++) { 2189 s = s1->sections[i]; 2190 if ((s->sh_flags & SHF_ALLOC) && 2191 s->sh_type == SHT_RELX) { 2192 relocate_rel(s1, s); 2193 } 2194 } 2195 2196 /* get entry point address */ 2197 if (file_type == TCC_OUTPUT_EXE) 2198 ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1); 2199 else 2200 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */ 2201 } 2202 if (file_type == TCC_OUTPUT_EXE && s1->static_link) 2203 fill_got(s1); 2204 2205 /* write elf file */ 1737 1738 return file_offset; 1739 } 1740 1741 static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, 1742 Section *dynamic) 1743 { 1744 ElfW(Phdr) *ph; 1745 1746 /* if interpreter, then add corresponding program header */ 1747 if (interp) { 1748 ph = &phdr[0]; 1749 1750 ph->p_type = PT_PHDR; 1751 ph->p_offset = sizeof(ElfW(Ehdr)); 1752 ph->p_filesz = ph->p_memsz = phnum * sizeof(ElfW(Phdr)); 1753 ph->p_vaddr = interp->sh_addr - ph->p_filesz; 1754 ph->p_paddr = ph->p_vaddr; 1755 ph->p_flags = PF_R | PF_X; 1756 ph->p_align = 4; /* interp->sh_addralign; */ 1757 ph++; 1758 1759 ph->p_type = PT_INTERP; 1760 ph->p_offset = interp->sh_offset; 1761 ph->p_vaddr = interp->sh_addr; 1762 ph->p_paddr = ph->p_vaddr; 1763 ph->p_filesz = interp->sh_size; 1764 ph->p_memsz = interp->sh_size; 1765 ph->p_flags = PF_R; 1766 ph->p_align = interp->sh_addralign; 1767 } 1768 1769 /* if dynamic section, then add corresponding program header */ 1770 if (dynamic) { 1771 ph = &phdr[phnum - 1]; 1772 1773 ph->p_type = PT_DYNAMIC; 1774 ph->p_offset = dynamic->sh_offset; 1775 ph->p_vaddr = dynamic->sh_addr; 1776 ph->p_paddr = ph->p_vaddr; 1777 ph->p_filesz = dynamic->sh_size; 1778 ph->p_memsz = dynamic->sh_size; 1779 ph->p_flags = PF_R | PF_W; 1780 ph->p_align = dynamic->sh_addralign; 1781 } 1782 } 1783 1784 /* Fill the dynamic section with tags describing the address and size of 1785 sections */ 1786 static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf) 1787 { 1788 Section *dynamic = dyninf->dynamic; 1789 1790 /* put dynamic section entries */ 1791 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr); 1792 put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr); 1793 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr); 1794 put_dt(dynamic, DT_STRSZ, dyninf->dynstr->data_offset); 1795 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym))); 1796 #if PTR_SIZE == 8 1797 put_dt(dynamic, DT_RELA, dyninf->rel_addr); 1798 put_dt(dynamic, DT_RELASZ, dyninf->rel_size); 1799 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel)); 1800 #else 1801 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 1802 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr); 1803 put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size); 1804 put_dt(dynamic, DT_JMPREL, dyninf->rel_addr); 1805 put_dt(dynamic, DT_PLTREL, DT_REL); 1806 put_dt(dynamic, DT_REL, dyninf->bss_addr); 1807 put_dt(dynamic, DT_RELSZ, dyninf->bss_size); 1808 #else 1809 put_dt(dynamic, DT_REL, dyninf->rel_addr); 1810 put_dt(dynamic, DT_RELSZ, dyninf->rel_size); 1811 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel)); 1812 #endif 1813 #endif 1814 if (s1->do_debug) 1815 put_dt(dynamic, DT_DEBUG, 0); 1816 put_dt(dynamic, DT_NULL, 0); 1817 } 1818 1819 /* Relocate remaining sections and symbols (that is those not related to 1820 dynamic linking) */ 1821 static int final_sections_reloc(TCCState *s1) 1822 { 1823 int i; 1824 Section *s; 1825 1826 relocate_syms(s1, s1->symtab, 0); 1827 1828 if (s1->nb_errors != 0) 1829 return -1; 1830 1831 /* relocate sections */ 1832 /* XXX: ignore sections with allocated relocations ? */ 1833 for(i = 1; i < s1->nb_sections; i++) { 1834 s = s1->sections[i]; 1835 #if defined(TCC_TARGET_I386) || defined(TCC_MUSL) 1836 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr 1837 /* On X86 gdb 7.3 works in any case but gdb 6.6 will crash if SHF_ALLOC 1838 checking is removed */ 1839 #else 1840 if (s->reloc && s != s1->got) 1841 /* On X86_64 gdb 7.3 will crash if SHF_ALLOC checking is present */ 1842 #endif 1843 relocate_section(s1, s); 1844 } 1845 1846 /* relocate relocation entries if the relocation tables are 1847 allocated in the executable */ 1848 for(i = 1; i < s1->nb_sections; i++) { 1849 s = s1->sections[i]; 1850 if ((s->sh_flags & SHF_ALLOC) && 1851 s->sh_type == SHT_RELX) { 1852 relocate_rel(s1, s); 1853 } 1854 } 1855 return 0; 1856 } 1857 1858 /* Create an ELF file on disk. 1859 This function handle ELF specific layout requirements */ 1860 static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, 1861 int file_offset, int *sec_order) 1862 { 1863 int i, shnum, offset, size, file_type; 1864 Section *s; 1865 ElfW(Ehdr) ehdr; 1866 ElfW(Shdr) shdr, *sh; 1867 1868 file_type = s1->output_type; 1869 shnum = s1->nb_sections; 1870 1871 memset(&ehdr, 0, sizeof(ehdr)); 1872 1873 if (phnum > 0) { 1874 ehdr.e_phentsize = sizeof(ElfW(Phdr)); 1875 ehdr.e_phnum = phnum; 1876 ehdr.e_phoff = sizeof(ElfW(Ehdr)); 1877 } 1878 1879 /* align to 4 */ 1880 file_offset = (file_offset + 3) & -4; 1881 1882 /* fill header */ 1883 ehdr.e_ident[0] = ELFMAG0; 1884 ehdr.e_ident[1] = ELFMAG1; 1885 ehdr.e_ident[2] = ELFMAG2; 1886 ehdr.e_ident[3] = ELFMAG3; 1887 ehdr.e_ident[4] = ELFCLASSW; 1888 ehdr.e_ident[5] = ELFDATA2LSB; 1889 ehdr.e_ident[6] = EV_CURRENT; 1890 #if !defined(TCC_TARGET_PE) && (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) 1891 /* FIXME: should set only for freebsd _target_, but we exclude only PE target */ 1892 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD; 1893 #endif 1894 #ifdef TCC_TARGET_ARM 1895 #ifdef TCC_ARM_EABI 1896 ehdr.e_ident[EI_OSABI] = 0; 1897 ehdr.e_flags = EF_ARM_EABI_VER4; 1898 if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL) 1899 ehdr.e_flags |= EF_ARM_HASENTRY; 1900 if (s1->float_abi == ARM_HARD_FLOAT) 1901 ehdr.e_flags |= EF_ARM_VFP_FLOAT; 1902 else 1903 ehdr.e_flags |= EF_ARM_SOFT_FLOAT; 1904 #else 1905 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM; 1906 #endif 1907 #endif 1908 switch(file_type) { 1909 default: 1910 case TCC_OUTPUT_EXE: 1911 ehdr.e_type = ET_EXEC; 1912 ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1); 1913 break; 1914 case TCC_OUTPUT_DLL: 1915 ehdr.e_type = ET_DYN; 1916 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */ 1917 break; 1918 case TCC_OUTPUT_OBJ: 1919 ehdr.e_type = ET_REL; 1920 break; 1921 } 1922 ehdr.e_machine = EM_TCC_TARGET; 1923 ehdr.e_version = EV_CURRENT; 1924 ehdr.e_shoff = file_offset; 1925 ehdr.e_ehsize = sizeof(ElfW(Ehdr)); 1926 ehdr.e_shentsize = sizeof(ElfW(Shdr)); 1927 ehdr.e_shnum = shnum; 1928 ehdr.e_shstrndx = shnum - 1; 1929 1930 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f); 1931 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f); 1932 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr)); 1933 1934 sort_syms(s1, symtab_section); 1935 for(i = 1; i < s1->nb_sections; i++) { 1936 s = s1->sections[sec_order[i]]; 1937 if (s->sh_type != SHT_NOBITS) { 1938 while (offset < s->sh_offset) { 1939 fputc(0, f); 1940 offset++; 1941 } 1942 size = s->sh_size; 1943 if (size) 1944 fwrite(s->data, 1, size, f); 1945 offset += size; 1946 } 1947 } 1948 1949 /* output section headers */ 1950 while (offset < ehdr.e_shoff) { 1951 fputc(0, f); 1952 offset++; 1953 } 1954 1955 for(i = 0; i < s1->nb_sections; i++) { 1956 sh = &shdr; 1957 memset(sh, 0, sizeof(ElfW(Shdr))); 1958 s = s1->sections[i]; 1959 if (s) { 1960 sh->sh_name = s->sh_name; 1961 sh->sh_type = s->sh_type; 1962 sh->sh_flags = s->sh_flags; 1963 sh->sh_entsize = s->sh_entsize; 1964 sh->sh_info = s->sh_info; 1965 if (s->link) 1966 sh->sh_link = s->link->sh_num; 1967 sh->sh_addralign = s->sh_addralign; 1968 sh->sh_addr = s->sh_addr; 1969 sh->sh_offset = s->sh_offset; 1970 sh->sh_size = s->sh_size; 1971 } 1972 fwrite(sh, 1, sizeof(ElfW(Shdr)), f); 1973 } 1974 } 1975 1976 /* Write an elf, coff or "binary" file */ 1977 static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum, 1978 ElfW(Phdr) *phdr, int file_offset, int *sec_order) 1979 { 1980 int fd, mode, file_type; 1981 FILE *f; 1982 1983 file_type = s1->output_type; 2206 1984 if (file_type == TCC_OUTPUT_OBJ) 2207 1985 mode = 0666; … … 2209 1987 mode = 0777; 2210 1988 unlink(filename); 2211 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode); 1989 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode); 2212 1990 if (fd < 0) { 2213 1991 tcc_error_noabort("could not write '%s'", filename); 2214 goto fail;1992 return -1; 2215 1993 } 2216 1994 f = fdopen(fd, "wb"); … … 2219 1997 2220 1998 #ifdef TCC_TARGET_COFF 2221 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {1999 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) 2222 2000 tcc_output_coff(s1, f); 2223 } else 2224 #endif 2225 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { 2226 sort_syms(s1, symtab_section); 2227 2228 /* align to 4 */ 2229 file_offset = (file_offset + 3) & -4; 2230 2231 /* fill header */ 2232 ehdr.e_ident[0] = ELFMAG0; 2233 ehdr.e_ident[1] = ELFMAG1; 2234 ehdr.e_ident[2] = ELFMAG2; 2235 ehdr.e_ident[3] = ELFMAG3; 2236 ehdr.e_ident[4] = ELFCLASSW; 2237 ehdr.e_ident[5] = ELFDATA2LSB; 2238 ehdr.e_ident[6] = EV_CURRENT; 2239 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 2240 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD; 2241 #endif 2242 #ifdef TCC_TARGET_ARM 2243 #ifdef TCC_ARM_EABI 2244 ehdr.e_ident[EI_OSABI] = 0; 2245 ehdr.e_flags = 4 << 24; 2246 #else 2247 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM; 2248 #endif 2249 #endif 2250 switch(file_type) { 2251 default: 2252 case TCC_OUTPUT_EXE: 2253 ehdr.e_type = ET_EXEC; 2254 break; 2255 case TCC_OUTPUT_DLL: 2256 ehdr.e_type = ET_DYN; 2257 break; 2258 case TCC_OUTPUT_OBJ: 2259 ehdr.e_type = ET_REL; 2260 break; 2261 } 2262 ehdr.e_machine = EM_TCC_TARGET; 2263 ehdr.e_version = EV_CURRENT; 2264 ehdr.e_shoff = file_offset; 2265 ehdr.e_ehsize = sizeof(ElfW(Ehdr)); 2266 ehdr.e_shentsize = sizeof(ElfW(Shdr)); 2267 ehdr.e_shnum = shnum; 2268 ehdr.e_shstrndx = shnum - 1; 2269 2270 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f); 2271 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f); 2272 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr)); 2273 2274 for(i=1;i<s1->nb_sections;i++) { 2275 s = s1->sections[section_order[i]]; 2276 if (s->sh_type != SHT_NOBITS) { 2277 if (s->sh_type == SHT_DYNSYM) 2278 patch_dynsym_undef(s1, s); 2279 while (offset < s->sh_offset) { 2280 fputc(0, f); 2281 offset++; 2001 else 2002 #endif 2003 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) 2004 tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order); 2005 else 2006 tcc_output_binary(s1, f, sec_order); 2007 fclose(f); 2008 2009 return 0; 2010 } 2011 2012 /* Sort section headers by assigned sh_addr, remove sections 2013 that we aren't going to output. */ 2014 static void tidy_section_headers(TCCState *s1, int *sec_order) 2015 { 2016 int i, nnew, l, *backmap; 2017 Section **snew, *s; 2018 ElfW(Sym) *sym; 2019 2020 snew = tcc_malloc(s1->nb_sections * sizeof(snew[0])); 2021 backmap = tcc_malloc(s1->nb_sections * sizeof(backmap[0])); 2022 for (i = 0, nnew = 0, l = s1->nb_sections; i < s1->nb_sections; i++) { 2023 s = s1->sections[sec_order[i]]; 2024 if (!i || s->sh_name) { 2025 backmap[sec_order[i]] = nnew; 2026 snew[nnew] = s; 2027 ++nnew; 2028 } else { 2029 backmap[sec_order[i]] = 0; 2030 snew[--l] = s; 2031 } 2032 } 2033 for (i = 0; i < nnew; i++) { 2034 s = snew[i]; 2035 if (s) { 2036 s->sh_num = i; 2037 if (s->sh_type == SHT_RELX) 2038 s->sh_info = backmap[s->sh_info]; 2039 } 2040 } 2041 2042 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) 2043 if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE) 2044 sym->st_shndx = backmap[sym->st_shndx]; 2045 if( !s1->static_link ) { 2046 for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) 2047 if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE) 2048 sym->st_shndx = backmap[sym->st_shndx]; 2049 } 2050 for (i = 0; i < s1->nb_sections; i++) 2051 sec_order[i] = i; 2052 tcc_free(s1->sections); 2053 s1->sections = snew; 2054 s1->nb_sections = nnew; 2055 tcc_free(backmap); 2056 } 2057 2058 /* Output an elf, coff or binary file */ 2059 /* XXX: suppress unneeded sections */ 2060 static int elf_output_file(TCCState *s1, const char *filename) 2061 { 2062 int i, ret, phnum, shnum, file_type, file_offset, *sec_order; 2063 struct dyn_inf dyninf = {0}; 2064 ElfW(Phdr) *phdr; 2065 ElfW(Sym) *sym; 2066 Section *strsec, *interp, *dynamic, *dynstr; 2067 int textrel; 2068 2069 file_type = s1->output_type; 2070 s1->nb_errors = 0; 2071 ret = -1; 2072 phdr = NULL; 2073 sec_order = NULL; 2074 interp = dynamic = dynstr = NULL; /* avoid warning */ 2075 textrel = 0; 2076 2077 if (file_type != TCC_OUTPUT_OBJ) { 2078 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */ 2079 tcc_add_runtime(s1); 2080 resolve_common_syms(s1); 2081 2082 if (!s1->static_link) { 2083 if (file_type == TCC_OUTPUT_EXE) { 2084 char *ptr; 2085 /* allow override the dynamic loader */ 2086 const char *elfint = getenv("LD_SO"); 2087 if (elfint == NULL) 2088 elfint = DEFAULT_ELFINTERP(s1); 2089 /* add interpreter section only if executable */ 2090 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC); 2091 interp->sh_addralign = 1; 2092 ptr = section_ptr_add(interp, 1 + strlen(elfint)); 2093 strcpy(ptr, elfint); 2094 } 2095 2096 /* add dynamic symbol table */ 2097 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC, 2098 ".dynstr", 2099 ".hash", SHF_ALLOC); 2100 dynstr = s1->dynsym->link; 2101 2102 /* add dynamic section */ 2103 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC, 2104 SHF_ALLOC | SHF_WRITE); 2105 dynamic->link = dynstr; 2106 dynamic->sh_entsize = sizeof(ElfW(Dyn)); 2107 2108 build_got(s1); 2109 2110 if (file_type == TCC_OUTPUT_EXE) { 2111 bind_exe_dynsyms(s1); 2112 if (s1->nb_errors) 2113 goto the_end; 2114 bind_libs_dynsyms(s1); 2115 } else { 2116 /* shared library case: simply export all global symbols */ 2117 export_global_syms(s1); 2118 } 2119 } 2120 build_got_entries(s1); 2121 } 2122 2123 /* we add a section for symbols */ 2124 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0); 2125 put_elf_str(strsec, ""); 2126 2127 /* Allocate strings for section names */ 2128 textrel = alloc_sec_names(s1, file_type, strsec); 2129 2130 if (dynamic) { 2131 /* add a list of needed dlls */ 2132 for(i = 0; i < s1->nb_loaded_dlls; i++) { 2133 DLLReference *dllref = s1->loaded_dlls[i]; 2134 if (dllref->level == 0) 2135 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name)); 2136 } 2137 2138 if (s1->rpath) 2139 put_dt(dynamic, s1->enable_new_dtags ? DT_RUNPATH : DT_RPATH, 2140 put_elf_str(dynstr, s1->rpath)); 2141 2142 if (file_type == TCC_OUTPUT_DLL) { 2143 if (s1->soname) 2144 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname)); 2145 /* XXX: currently, since we do not handle PIC code, we 2146 must relocate the readonly segments */ 2147 if (textrel) 2148 put_dt(dynamic, DT_TEXTREL, 0); 2149 } 2150 2151 if (s1->symbolic) 2152 put_dt(dynamic, DT_SYMBOLIC, 0); 2153 2154 dyninf.dynamic = dynamic; 2155 dyninf.dynstr = dynstr; 2156 /* remember offset and reserve space for 2nd call below */ 2157 dyninf.data_offset = dynamic->data_offset; 2158 fill_dynamic(s1, &dyninf); 2159 dynamic->sh_size = dynamic->data_offset; 2160 dynstr->sh_size = dynstr->data_offset; 2161 } 2162 2163 /* compute number of program headers */ 2164 if (file_type == TCC_OUTPUT_OBJ) 2165 phnum = 0; 2166 else if (file_type == TCC_OUTPUT_DLL) 2167 phnum = 3; 2168 else if (s1->static_link) 2169 phnum = 2; 2170 else 2171 phnum = 5; 2172 2173 /* allocate program segment headers */ 2174 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr))); 2175 2176 /* compute number of sections */ 2177 shnum = s1->nb_sections; 2178 2179 /* this array is used to reorder sections in the output file */ 2180 sec_order = tcc_malloc(sizeof(int) * shnum); 2181 sec_order[0] = 0; 2182 2183 /* compute section to program header mapping */ 2184 file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf, 2185 sec_order); 2186 2187 /* Fill remaining program header and finalize relocation related to dynamic 2188 linking. */ 2189 if (file_type != TCC_OUTPUT_OBJ) { 2190 fill_unloadable_phdr(phdr, phnum, interp, dynamic); 2191 if (dynamic) { 2192 dynamic->data_offset = dyninf.data_offset; 2193 fill_dynamic(s1, &dyninf); 2194 2195 /* put in GOT the dynamic section address and relocate PLT */ 2196 write32le(s1->got->data, dynamic->sh_addr); 2197 if (file_type == TCC_OUTPUT_EXE 2198 || (RELOCATE_DLLPLT && file_type == TCC_OUTPUT_DLL)) 2199 relocate_plt(s1); 2200 2201 /* relocate symbols in .dynsym now that final addresses are known */ 2202 for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) { 2203 if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE) { 2204 /* do symbol relocation */ 2205 sym->st_value += s1->sections[sym->st_shndx]->sh_addr; 2282 2206 } 2283 size = s->sh_size; 2284 fwrite(s->data, 1, size, f); 2285 offset += size; 2286 } 2287 } 2288 2289 /* output section headers */ 2290 while (offset < ehdr.e_shoff) { 2291 fputc(0, f); 2292 offset++; 2293 } 2294 2295 for(i=0;i<s1->nb_sections;i++) { 2296 sh = &shdr; 2297 memset(sh, 0, sizeof(ElfW(Shdr))); 2298 s = s1->sections[i]; 2299 if (s) { 2300 sh->sh_name = s->sh_name; 2301 sh->sh_type = s->sh_type; 2302 sh->sh_flags = s->sh_flags; 2303 sh->sh_entsize = s->sh_entsize; 2304 sh->sh_info = s->sh_info; 2305 if (s->link) 2306 sh->sh_link = s->link->sh_num; 2307 sh->sh_addralign = s->sh_addralign; 2308 sh->sh_addr = s->sh_addr; 2309 sh->sh_offset = s->sh_offset; 2310 sh->sh_size = s->sh_size; 2311 } 2312 fwrite(sh, 1, sizeof(ElfW(Shdr)), f); 2313 } 2314 } else { 2315 tcc_output_binary(s1, f, section_order); 2316 } 2317 fclose(f); 2318 2319 ret = 0; 2207 } 2208 } 2209 2210 /* if building executable or DLL, then relocate each section 2211 except the GOT which is already relocated */ 2212 ret = final_sections_reloc(s1); 2213 if (ret) 2214 goto the_end; 2215 tidy_section_headers(s1, sec_order); 2216 2217 /* Perform relocation to GOT or PLT entries */ 2218 if (file_type == TCC_OUTPUT_EXE && s1->static_link) 2219 fill_got(s1); 2220 else if (s1->got) 2221 fill_local_got_entries(s1); 2222 } 2223 2224 /* Create the ELF file with name 'filename' */ 2225 ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order); 2226 s1->nb_sections = shnum; 2320 2227 the_end: 2321 tcc_free(s1->symtab_to_dynsym); 2322 tcc_free(section_order); 2228 tcc_free(sec_order); 2323 2229 tcc_free(phdr); 2324 tcc_free(s1->sym_attrs);2325 2230 return ret; 2326 2231 } … … 2334 2239 } else 2335 2240 #endif 2336 {2337 2241 ret = elf_output_file(s, filename); 2338 }2339 2242 return ret; 2340 2243 } … … 2357 2260 } SectionMergeInfo; 2358 2261 2262 ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h) 2263 { 2264 int size = read(fd, h, sizeof *h); 2265 if (size == sizeof *h && 0 == memcmp(h, ELFMAG, 4)) { 2266 if (h->e_type == ET_REL) 2267 return AFF_BINTYPE_REL; 2268 if (h->e_type == ET_DYN) 2269 return AFF_BINTYPE_DYN; 2270 } else if (size >= 8) { 2271 if (0 == memcmp(h, ARMAG, 8)) 2272 return AFF_BINTYPE_AR; 2273 #ifdef TCC_TARGET_COFF 2274 if (((struct filehdr*)h)->f_magic == COFF_C67_MAGIC) 2275 return AFF_BINTYPE_C67; 2276 #endif 2277 } 2278 return 0; 2279 } 2280 2359 2281 /* load an object file and merge it with current files */ 2360 2282 /* XXX: handle correctly stab (debug) info */ 2361 ST_FUNC int tcc_load_object_file(TCCState *s1, 2283 ST_FUNC int tcc_load_object_file(TCCState *s1, 2362 2284 int fd, unsigned long file_offset) 2363 { 2285 { 2364 2286 ElfW(Ehdr) ehdr; 2365 2287 ElfW(Shdr) *shdr, *sh; 2366 int size, i, j, offset, offseti, nb_syms, sym_index, ret ;2288 int size, i, j, offset, offseti, nb_syms, sym_index, ret, seencompressed; 2367 2289 unsigned char *strsec, *strtab; 2368 2290 int *old_to_new_syms; … … 2370 2292 SectionMergeInfo *sm_table, *sm; 2371 2293 ElfW(Sym) *sym, *symtab; 2372 ElfW_Rel *rel , *rel_end;2294 ElfW_Rel *rel; 2373 2295 Section *s; 2374 2296 … … 2378 2300 stab_index = stabstr_index = 0; 2379 2301 2380 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) 2381 goto fail1; 2382 if (ehdr.e_ident[0] != ELFMAG0 || 2383 ehdr.e_ident[1] != ELFMAG1 || 2384 ehdr.e_ident[2] != ELFMAG2 || 2385 ehdr.e_ident[3] != ELFMAG3) 2386 goto fail1; 2387 /* test if object file */ 2388 if (ehdr.e_type != ET_REL) 2302 lseek(fd, file_offset, SEEK_SET); 2303 if (tcc_object_type(fd, &ehdr) != AFF_BINTYPE_REL) 2389 2304 goto fail1; 2390 2305 /* test CPU specific stuff */ … … 2396 2311 } 2397 2312 /* read sections */ 2398 shdr = load_data(fd, file_offset + ehdr.e_shoff, 2313 shdr = load_data(fd, file_offset + ehdr.e_shoff, 2399 2314 sizeof(ElfW(Shdr)) * ehdr.e_shnum); 2400 2315 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum); 2401 2316 2402 2317 /* load section names */ 2403 2318 sh = &shdr[ehdr.e_shstrndx]; … … 2409 2324 strtab = NULL; 2410 2325 nb_syms = 0; 2326 seencompressed = 0; 2411 2327 for(i = 1; i < ehdr.e_shnum; i++) { 2412 2328 sh = &shdr[i]; … … 2426 2342 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size); 2427 2343 } 2428 } 2429 2344 if (sh->sh_flags & SHF_COMPRESSED) 2345 seencompressed = 1; 2346 } 2347 2430 2348 /* now examine each section and try to merge its content with the 2431 2349 ones in memory */ … … 2435 2353 continue; 2436 2354 sh = &shdr[i]; 2437 sh_name = strsec + sh->sh_name;2355 sh_name = (char *) strsec + sh->sh_name; 2438 2356 /* ignore sections types we do not handle */ 2439 2357 if (sh->sh_type != SHT_PROGBITS && 2440 sh->sh_type != SHT_RELX && 2358 sh->sh_type != SHT_RELX && 2441 2359 #ifdef TCC_ARM_EABI 2442 2360 sh->sh_type != SHT_ARM_EXIDX && 2443 2361 #endif 2444 sh->sh_type != SHT_NOBITS && 2362 sh->sh_type != SHT_NOBITS && 2445 2363 sh->sh_type != SHT_PREINIT_ARRAY && 2446 2364 sh->sh_type != SHT_INIT_ARRAY && … … 2449 2367 ) 2450 2368 continue; 2369 if (seencompressed 2370 && (!strncmp(sh_name, ".debug_", sizeof(".debug_")-1) 2371 || (sh->sh_type == SHT_RELX 2372 && !strncmp((char*)strsec + shdr[sh->sh_info].sh_name, 2373 ".debug_", sizeof(".debug_")-1)))) 2374 continue; 2451 2375 if (sh->sh_addralign < 1) 2452 2376 sh->sh_addralign = 1; … … 2455 2379 s = s1->sections[j]; 2456 2380 if (!strcmp(s->name, sh_name)) { 2457 if (!strncmp(sh_name, ".gnu.linkonce", 2381 if (!strncmp(sh_name, ".gnu.linkonce", 2458 2382 sizeof(".gnu.linkonce") - 1)) { 2459 2383 /* if a 'linkonce' section is already present, we … … 2469 2393 } 2470 2394 /* not found: create new section */ 2471 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags );2395 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags & ~SHF_GROUP); 2472 2396 /* take as much info as possible from the section. sh_link and 2473 2397 sh_info will be updated later */ … … 2514 2438 } 2515 2439 2516 /* //gr relocate stab strings */2440 /* gr relocate stab strings */ 2517 2441 if (stab_index && stabstr_index) { 2518 2442 Stab_Sym *a, *b; … … 2522 2446 b = (Stab_Sym *)(s->data + s->data_offset); 2523 2447 o = sm_table[stabstr_index].offset; 2524 while (a < b) 2448 while (a < b) 2525 2449 a->n_strx += o, a++; 2526 2450 } … … 2556 2480 correct relocations */ 2557 2481 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { 2558 name = strtab + sym->st_name;2482 name = (char *) strtab + sym->st_name; 2559 2483 sym_index = find_elf_sym(symtab_section, name); 2560 2484 if (sym_index) … … 2572 2496 } 2573 2497 /* add symbol */ 2574 name = strtab + sym->st_name;2575 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,2576 sym->st_info, sym->st_other, 2498 name = (char *) strtab + sym->st_name; 2499 sym_index = set_elf_sym(symtab_section, sym->st_value, sym->st_size, 2500 sym->st_info, sym->st_other, 2577 2501 sym->st_shndx, name); 2578 2502 old_to_new_syms[i] = sym_index; … … 2590 2514 /* take relocation offset information */ 2591 2515 offseti = sm_table[sh->sh_info].offset; 2592 rel_end = (ElfW_Rel *)(s->data + s->data_offset); 2593 for(rel = (ElfW_Rel *)(s->data + offset); 2594 rel < rel_end; 2595 rel++) { 2516 for_each_elem(s, (offset / sizeof(*rel)), rel, ElfW_Rel) { 2596 2517 int type; 2597 2518 unsigned sym_index; … … 2624 2545 instructions. Other case of instructions referencing a PLT 2625 2546 entry require to add a Thumb stub before the PLT entry to 2626 switch to ARM mode. We set bit 0 of the got offset of a2627 symbol to indicate such a case. */2547 switch to ARM mode. We set bit plt_thumb_stub of the 2548 attribute of a symbol to indicate such a case. */ 2628 2549 if (type == R_ARM_THM_JUMP24) 2629 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;2550 get_sym_attr(s1, sym_index, 1)->plt_thumb_stub = 1; 2630 2551 #endif 2631 2552 } … … 2635 2556 } 2636 2557 } 2637 2558 2638 2559 ret = 0; 2639 2560 the_end: … … 2662 2583 } 2663 2584 2585 static long get_be64(const uint8_t *b) 2586 { 2587 long long ret = get_be32(b); 2588 ret = (ret << 32) | (unsigned)get_be32(b+4); 2589 return (long)ret; 2590 } 2591 2664 2592 /* load only the objects which resolve undefined symbols */ 2665 static int tcc_load_alacarte(TCCState *s1, int fd, int size )2666 { 2667 inti, bound, nsyms, sym_index, off, ret;2593 static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize) 2594 { 2595 long i, bound, nsyms, sym_index, off, ret; 2668 2596 uint8_t *data; 2669 2597 const char *ar_names, *p; … … 2674 2602 if (read(fd, data, size) != size) 2675 2603 goto fail; 2676 nsyms = get_be32(data);2677 ar_index = data + 4;2678 ar_names = ar_index + nsyms * 4;2604 nsyms = entrysize == 4 ? get_be32(data) : get_be64(data); 2605 ar_index = data + entrysize; 2606 ar_names = (char *) ar_index + nsyms * entrysize; 2679 2607 2680 2608 do { … … 2685 2613 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; 2686 2614 if(sym->st_shndx == SHN_UNDEF) { 2687 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);2688 #if 0 2689 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx); 2690 #endif 2615 off = (entrysize == 4 2616 ? get_be32(ar_index + i * 4) 2617 : get_be64(ar_index + i * 8)) 2618 + sizeof(ArchiveHeader); 2691 2619 ++bound; 2692 lseek(fd, off, SEEK_SET);2693 2620 if(tcc_load_object_file(s1, fd, off) < 0) { 2694 2621 fail: … … 2718 2645 /* skip magic which was already checked */ 2719 2646 read(fd, magic, sizeof(magic)); 2720 2647 2721 2648 for(;;) { 2722 2649 len = read(fd, &hdr, sizeof(hdr)); … … 2736 2663 } 2737 2664 ar_name[i + 1] = '\0'; 2738 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);2739 2665 file_offset = lseek(fd, 0, SEEK_CUR); 2740 2666 /* align to even */ … … 2743 2669 /* coff symbol table : we handle it */ 2744 2670 if(s1->alacarte_link) 2745 return tcc_load_alacarte(s1, fd, size); 2746 } else if (!strcmp(ar_name, "//") || 2747 !strcmp(ar_name, "__.SYMDEF") || 2748 !strcmp(ar_name, "__.SYMDEF/") || 2749 !strcmp(ar_name, "ARFILENAMES/")) { 2750 /* skip symbol table or archive names */ 2671 return tcc_load_alacarte(s1, fd, size, 4); 2672 } else if (!strcmp(ar_name, "/SYM64/")) { 2673 if(s1->alacarte_link) 2674 return tcc_load_alacarte(s1, fd, size, 8); 2751 2675 } else { 2752 if (tcc_load_object_file(s1, fd, file_offset) < 0) 2753 return -1; 2676 ElfW(Ehdr) ehdr; 2677 if (tcc_object_type(fd, &ehdr) == AFF_BINTYPE_REL) { 2678 if (tcc_load_object_file(s1, fd, file_offset) < 0) 2679 return -1; 2680 } 2754 2681 } 2755 2682 lseek(fd, file_offset + size, SEEK_SET); … … 2763 2690 the generated ELF file) */ 2764 2691 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) 2765 { 2692 { 2766 2693 ElfW(Ehdr) ehdr; 2767 2694 ElfW(Shdr) *shdr, *sh, *sh1; … … 2772 2699 const char *name, *soname; 2773 2700 DLLReference *dllref; 2774 2701 2775 2702 read(fd, &ehdr, sizeof(ehdr)); 2776 2703 … … 2807 2734 } 2808 2735 } 2809 2736 2810 2737 /* compute the real library name */ 2811 2738 soname = tcc_basename(filename); 2812 2739 2813 2740 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { 2814 2741 if (dt->d_tag == DT_SONAME) { 2815 soname = dynstr + dt->d_un.d_val;2742 soname = (char *) dynstr + dt->d_un.d_val; 2816 2743 } 2817 2744 } … … 2828 2755 } 2829 2756 } 2830 2831 // printf("loading dll '%s'\n", soname);2832 2757 2833 2758 /* add the dll and its level */ … … 2835 2760 dllref->level = level; 2836 2761 strcpy(dllref->name, soname); 2837 dynarray_add( (void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);2762 dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); 2838 2763 2839 2764 /* add dynamic symbols in dynsym_section */ … … 2842 2767 if (sym_bind == STB_LOCAL) 2843 2768 continue; 2844 name = dynstr + sym->st_name;2845 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,2769 name = (char *) dynstr + sym->st_name; 2770 set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, 2846 2771 sym->st_info, sym->st_other, sym->st_shndx, name); 2847 2772 } … … 2851 2776 switch(dt->d_tag) { 2852 2777 case DT_NEEDED: 2853 name = dynstr + dt->d_un.d_val;2778 name = (char *) dynstr + dt->d_un.d_val; 2854 2779 for(j = 0; j < s1->nb_loaded_dlls; j++) { 2855 2780 dllref = s1->loaded_dlls[j]; … … 2906 2831 } 2907 2832 break; 2833 case '\\': 2834 ch = handle_eob(); 2835 if (ch != '\\') 2836 goto redo; 2837 /* fall through */ 2908 2838 /* case 'a' ... 'z': */ 2909 2839 case 'a': … … 2961 2891 case 'Z': 2962 2892 case '_': 2963 case '\\':2964 2893 case '.': 2965 2894 case '$': … … 2989 2918 break; 2990 2919 } 2991 #if 02992 printf("tok=%c %d\n", c, c);2993 if (c == LD_TOK_NAME)2994 printf(" name=%s\n", name);2995 #endif2996 2920 return c; 2997 2921 } … … 2999 2923 static int ld_add_file(TCCState *s1, const char filename[]) 3000 2924 { 3001 int ret; 3002 3003 ret = tcc_add_file_internal(s1, filename, 0); 3004 if (ret) 3005 ret = tcc_add_dll(s1, filename, 0); 3006 return ret; 2925 if (filename[0] == '/') { 2926 if (CONFIG_SYSROOT[0] == '\0' 2927 && tcc_add_file_internal(s1, filename, AFF_TYPE_BIN) == 0) 2928 return 0; 2929 filename = tcc_basename(filename); 2930 } 2931 return tcc_add_dll(s1, filename, 0); 3007 2932 } 3008 2933 … … 3066 2991 if (group) { 3067 2992 /* Add the filename *and* the libname to avoid future conversions */ 3068 dynarray_add( (void ***)&libs, &nblibs, tcc_strdup(filename));2993 dynarray_add(&libs, &nblibs, tcc_strdup(filename)); 3069 2994 if (libname[0] != '\0') 3070 dynarray_add( (void ***)&libs, &nblibs, tcc_strdup(libname));2995 dynarray_add(&libs, &nblibs, tcc_strdup(libname)); 3071 2996 } 3072 2997 } … … 3097 3022 char filename[1024]; 3098 3023 int t, ret; 3099 3100 ch = file->buf_ptr[0]; 3024 3101 3025 ch = handle_eob(); 3102 3026 for(;;) { … … 3132 3056 return 0; 3133 3057 } 3134 #endif /* ndefTCC_TARGET_PE */3058 #endif /* !TCC_TARGET_PE */ -
EcnlProtoTool/trunk/tcc-0.9.27/tccgen.c
r321 r331 31 31 ST_DATA int rsym, anon_sym, ind, loc; 32 32 33 ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */34 ST_DATA Section *cur_text_section; /* current section where function code is generated */35 #ifdef CONFIG_TCC_ASM36 ST_DATA Section *last_text_section; /* to handle .previous asm directive */37 #endif38 #ifdef CONFIG_TCC_BCHECK39 /* bound check related sections */40 ST_DATA Section *bounds_section; /* contains global data bound description */41 ST_DATA Section *lbounds_section; /* contains local data bound description */42 #endif43 /* symbol sections */44 ST_DATA Section *symtab_section, *strtab_section;45 /* debug sections */46 ST_DATA Section *stab_section, *stabstr_section;47 33 ST_DATA Sym *sym_free_first; 48 34 ST_DATA void **sym_pools; … … 51 37 ST_DATA Sym *global_stack; 52 38 ST_DATA Sym *local_stack; 53 ST_DATA Sym *scope_stack_bottom;54 39 ST_DATA Sym *define_stack; 55 40 ST_DATA Sym *global_label_stack; 56 41 ST_DATA Sym *local_label_stack; 57 58 ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop; 42 static int local_scope; 43 static int in_sizeof; 44 static int section_sym; 45 46 ST_DATA int vlas_in_scope; /* number of VLAs that are currently in scope */ 47 ST_DATA int vla_sp_root_loc; /* vla_sp_loc for SP before any VLAs were pushed */ 48 ST_DATA int vla_sp_loc; /* Pointer to variable holding location to store stack pointer on the stack when modifying stack pointer */ 49 50 ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop, *pvtop; 59 51 60 52 ST_DATA int const_wanted; /* true if constant wanted */ 61 ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */ 53 ST_DATA int nocode_wanted; /* no code generation wanted */ 54 #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */ 55 #define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data output */ 62 56 ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ 63 57 ST_DATA CType func_vt; /* current function return type (used by return instruction) */ 58 ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */ 64 59 ST_DATA int func_vc; 65 60 ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ 66 ST_DATA char *funcname; 67 68 ST_DATA CType char_pointer_type, func_old_type, int_type, size_type; 61 ST_DATA const char *funcname; 62 ST_DATA int g_debug; 63 64 ST_DATA CType char_pointer_type, func_old_type, int_type, size_type, ptrdiff_type; 65 66 ST_DATA struct switch_t { 67 struct case_t { 68 int64_t v1, v2; 69 int sym; 70 } **p; int n; /* list of case ranges */ 71 int def_sym; /* default symbol */ 72 } *cur_switch; /* current switch */ 69 73 70 74 /* ------------------------------------------------------------------------- */ 75 71 76 static void gen_cast(CType *type); 77 static void gen_cast_s(int t); 72 78 static inline CType *pointed_type(CType *type); 73 79 static int is_compatible_types(CType *type1, CType *type2); 74 80 static int parse_btype(CType *type, AttributeDef *ad); 75 static voidtype_decl(CType *type, AttributeDef *ad, int *v, int td);81 static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td); 76 82 static void parse_expr_type(CType *type); 83 static void init_putv(CType *type, Section *sec, unsigned long c); 77 84 static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only); 78 static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg, int is_expr); 79 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, char *asm_label, int scope); 80 static int decl0(int l, int is_for_loop_init); 85 static void block(int *bsym, int *csym, int is_expr); 86 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope); 87 static void decl(int l); 88 static int decl0(int l, int is_for_loop_init, Sym *); 81 89 static void expr_eq(void); 82 static void unary_type(CType *type);83 90 static void vla_runtime_type_size(CType *type, int *a); 84 static int is_compatible_parameter_types(CType *type1, CType *type2); 85 static void expr_type(CType *type); 91 static void vla_sp_restore(void); 92 static void vla_sp_restore_root(void); 93 static int is_compatible_unqualified_types(CType *type1, CType *type2); 94 static inline int64_t expr_const64(void); 95 static void vpush64(int ty, unsigned long long v); 96 static void vpush(CType *type); 97 static int gvtst(int inv, int t); 98 static void gen_inline_functions(TCCState *s); 99 static void skip_or_save_block(TokenString **str); 100 static void gv_dup(void); 86 101 87 102 ST_INLN int is_float(int t) … … 89 104 int bt; 90 105 bt = t & VT_BTYPE; 91 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT ;106 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT || bt == VT_QFLOAT; 92 107 } 93 108 … … 97 112 ST_FUNC int ieee_finite(double d) 98 113 { 99 int *p = (int *)&d; 114 int p[4]; 115 memcpy(p, &d, sizeof(double)); 100 116 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31; 101 117 } 118 119 /* compiling intel long double natively */ 120 #if (defined __i386__ || defined __x86_64__) \ 121 && (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64) 122 # define TCC_IS_NATIVE_387 123 #endif 102 124 103 125 ST_FUNC void test_lvalue(void) … … 106 128 expect("lvalue"); 107 129 } 130 131 ST_FUNC void check_vstack(void) 132 { 133 if (pvtop != vtop) 134 tcc_error("internal compiler error: vstack leak (%d)", vtop - pvtop); 135 } 136 137 /* ------------------------------------------------------------------------- */ 138 /* vstack debugging aid */ 139 140 #if 0 141 void pv (const char *lbl, int a, int b) 142 { 143 int i; 144 for (i = a; i < a + b; ++i) { 145 SValue *p = &vtop[-i]; 146 printf("%s vtop[-%d] : type.t:%04x r:%04x r2:%04x c.i:%d\n", 147 lbl, i, p->type.t, p->r, p->r2, (int)p->c.i); 148 } 149 } 150 #endif 151 152 /* ------------------------------------------------------------------------- */ 153 /* start of translation unit info */ 154 ST_FUNC void tcc_debug_start(TCCState *s1) 155 { 156 if (s1->do_debug) { 157 char buf[512]; 158 159 /* file info: full path + filename */ 160 section_sym = put_elf_sym(symtab_section, 0, 0, 161 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0, 162 text_section->sh_num, NULL); 163 getcwd(buf, sizeof(buf)); 164 #ifdef _WIN32 165 normalize_slashes(buf); 166 #endif 167 pstrcat(buf, sizeof(buf), "/"); 168 put_stabs_r(buf, N_SO, 0, 0, 169 text_section->data_offset, text_section, section_sym); 170 put_stabs_r(file->filename, N_SO, 0, 0, 171 text_section->data_offset, text_section, section_sym); 172 last_ind = 0; 173 last_line_num = 0; 174 } 175 176 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL 177 symbols can be safely used */ 178 put_elf_sym(symtab_section, 0, 0, 179 ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, 180 SHN_ABS, file->filename); 181 } 182 183 /* put end of translation unit info */ 184 ST_FUNC void tcc_debug_end(TCCState *s1) 185 { 186 if (!s1->do_debug) 187 return; 188 put_stabs_r(NULL, N_SO, 0, 0, 189 text_section->data_offset, text_section, section_sym); 190 191 } 192 193 /* generate line number info */ 194 ST_FUNC void tcc_debug_line(TCCState *s1) 195 { 196 if (!s1->do_debug) 197 return; 198 if ((last_line_num != file->line_num || last_ind != ind)) { 199 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind); 200 last_ind = ind; 201 last_line_num = file->line_num; 202 } 203 } 204 205 /* put function symbol */ 206 ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym) 207 { 208 char buf[512]; 209 210 if (!s1->do_debug) 211 return; 212 213 /* stabs info */ 214 /* XXX: we put here a dummy type */ 215 snprintf(buf, sizeof(buf), "%s:%c1", 216 funcname, sym->type.t & VT_STATIC ? 'f' : 'F'); 217 put_stabs_r(buf, N_FUN, 0, file->line_num, 0, 218 cur_text_section, sym->c); 219 /* //gr gdb wants a line at the function */ 220 put_stabn(N_SLINE, 0, file->line_num, 0); 221 222 last_ind = 0; 223 last_line_num = 0; 224 } 225 226 /* put function size */ 227 ST_FUNC void tcc_debug_funcend(TCCState *s1, int size) 228 { 229 if (!s1->do_debug) 230 return; 231 put_stabn(N_FUN, 0, 0, size); 232 } 233 234 /* ------------------------------------------------------------------------- */ 235 ST_FUNC int tccgen_compile(TCCState *s1) 236 { 237 cur_text_section = NULL; 238 funcname = ""; 239 anon_sym = SYM_FIRST_ANOM; 240 section_sym = 0; 241 const_wanted = 0; 242 nocode_wanted = 0x80000000; 243 244 /* define some often used types */ 245 int_type.t = VT_INT; 246 char_pointer_type.t = VT_BYTE; 247 mk_pointer(&char_pointer_type); 248 #if PTR_SIZE == 4 249 size_type.t = VT_INT | VT_UNSIGNED; 250 ptrdiff_type.t = VT_INT; 251 #elif LONG_SIZE == 4 252 size_type.t = VT_LLONG | VT_UNSIGNED; 253 ptrdiff_type.t = VT_LLONG; 254 #else 255 size_type.t = VT_LONG | VT_LLONG | VT_UNSIGNED; 256 ptrdiff_type.t = VT_LONG | VT_LLONG; 257 #endif 258 func_old_type.t = VT_FUNC; 259 func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0); 260 func_old_type.ref->f.func_call = FUNC_CDECL; 261 func_old_type.ref->f.func_type = FUNC_OLD; 262 263 tcc_debug_start(s1); 264 265 #ifdef TCC_TARGET_ARM 266 arm_init(s1); 267 #endif 268 269 #ifdef INC_DEBUG 270 printf("%s: **** new file\n", file->filename); 271 #endif 272 273 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_TOK_STR; 274 next(); 275 decl(VT_CONST); 276 gen_inline_functions(s1); 277 check_vstack(); 278 /* end of translation unit info */ 279 tcc_debug_end(s1); 280 return 0; 281 } 282 283 /* ------------------------------------------------------------------------- */ 284 ST_FUNC ElfSym *elfsym(Sym *s) 285 { 286 if (!s || !s->c) 287 return NULL; 288 return &((ElfSym *)symtab_section->data)[s->c]; 289 } 290 291 /* apply storage attributes to Elf symbol */ 292 ST_FUNC void update_storage(Sym *sym) 293 { 294 ElfSym *esym; 295 int sym_bind, old_sym_bind; 296 297 esym = elfsym(sym); 298 if (!esym) 299 return; 300 301 if (sym->a.visibility) 302 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1)) 303 | sym->a.visibility; 304 305 if (sym->type.t & VT_STATIC) 306 sym_bind = STB_LOCAL; 307 else if (sym->a.weak) 308 sym_bind = STB_WEAK; 309 else 310 sym_bind = STB_GLOBAL; 311 old_sym_bind = ELFW(ST_BIND)(esym->st_info); 312 if (sym_bind != old_sym_bind) { 313 esym->st_info = ELFW(ST_INFO)(sym_bind, ELFW(ST_TYPE)(esym->st_info)); 314 } 315 316 #ifdef TCC_TARGET_PE 317 if (sym->a.dllimport) 318 esym->st_other |= ST_PE_IMPORT; 319 if (sym->a.dllexport) 320 esym->st_other |= ST_PE_EXPORT; 321 #endif 322 323 #if 0 324 printf("storage %s: bind=%c vis=%d exp=%d imp=%d\n", 325 get_tok_str(sym->v, NULL), 326 sym_bind == STB_WEAK ? 'w' : sym_bind == STB_LOCAL ? 'l' : 'g', 327 sym->a.visibility, 328 sym->a.dllexport, 329 sym->a.dllimport 330 ); 331 #endif 332 } 333 334 /* ------------------------------------------------------------------------- */ 335 /* update sym->c so that it points to an external symbol in section 336 'section' with value 'value' */ 337 338 ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, 339 addr_t value, unsigned long size, 340 int can_add_underscore) 341 { 342 int sym_type, sym_bind, info, other, t; 343 ElfSym *esym; 344 const char *name; 345 char buf1[256]; 346 #ifdef CONFIG_TCC_BCHECK 347 char buf[32]; 348 #endif 349 350 if (!sym->c) { 351 name = get_tok_str(sym->v, NULL); 352 #ifdef CONFIG_TCC_BCHECK 353 if (tcc_state->do_bounds_check) { 354 /* XXX: avoid doing that for statics ? */ 355 /* if bound checking is activated, we change some function 356 names by adding the "__bound" prefix */ 357 switch(sym->v) { 358 #ifdef TCC_TARGET_PE 359 /* XXX: we rely only on malloc hooks */ 360 case TOK_malloc: 361 case TOK_free: 362 case TOK_realloc: 363 case TOK_memalign: 364 case TOK_calloc: 365 #endif 366 case TOK_memcpy: 367 case TOK_memmove: 368 case TOK_memset: 369 case TOK_strlen: 370 case TOK_strcpy: 371 case TOK_alloca: 372 strcpy(buf, "__bound_"); 373 strcat(buf, name); 374 name = buf; 375 break; 376 } 377 } 378 #endif 379 t = sym->type.t; 380 if ((t & VT_BTYPE) == VT_FUNC) { 381 sym_type = STT_FUNC; 382 } else if ((t & VT_BTYPE) == VT_VOID) { 383 sym_type = STT_NOTYPE; 384 } else { 385 sym_type = STT_OBJECT; 386 } 387 if (t & VT_STATIC) 388 sym_bind = STB_LOCAL; 389 else 390 sym_bind = STB_GLOBAL; 391 other = 0; 392 #ifdef TCC_TARGET_PE 393 if (sym_type == STT_FUNC && sym->type.ref) { 394 Sym *ref = sym->type.ref; 395 if (ref->f.func_call == FUNC_STDCALL && can_add_underscore) { 396 sprintf(buf1, "_%s@%d", name, ref->f.func_args * PTR_SIZE); 397 name = buf1; 398 other |= ST_PE_STDCALL; 399 can_add_underscore = 0; 400 } 401 } 402 #endif 403 if (tcc_state->leading_underscore && can_add_underscore) { 404 buf1[0] = '_'; 405 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name); 406 name = buf1; 407 } 408 if (sym->asm_label) 409 name = get_tok_str(sym->asm_label, NULL); 410 info = ELFW(ST_INFO)(sym_bind, sym_type); 411 sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name); 412 } else { 413 esym = elfsym(sym); 414 esym->st_value = value; 415 esym->st_size = size; 416 esym->st_shndx = sh_num; 417 } 418 update_storage(sym); 419 } 420 421 ST_FUNC void put_extern_sym(Sym *sym, Section *section, 422 addr_t value, unsigned long size) 423 { 424 int sh_num = section ? section->sh_num : SHN_UNDEF; 425 put_extern_sym2(sym, sh_num, value, size, 1); 426 } 427 428 /* add a new relocation entry to symbol 'sym' in section 's' */ 429 ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, 430 addr_t addend) 431 { 432 int c = 0; 433 434 if (nocode_wanted && s == cur_text_section) 435 return; 436 437 if (sym) { 438 if (0 == sym->c) 439 put_extern_sym(sym, NULL, 0, 0); 440 c = sym->c; 441 } 442 443 /* now we can add ELF relocation info */ 444 put_elf_reloca(symtab_section, s, offset, type, c, addend); 445 } 446 447 #if PTR_SIZE == 4 448 ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type) 449 { 450 greloca(s, sym, offset, type, 0); 451 } 452 #endif 108 453 109 454 /* ------------------------------------------------------------------------- */ … … 131 476 { 132 477 Sym *sym; 478 #ifndef SYM_DEBUG 133 479 sym = sym_free_first; 134 480 if (!sym) … … 136 482 sym_free_first = sym->next; 137 483 return sym; 484 #else 485 sym = tcc_malloc(sizeof(Sym)); 486 return sym; 487 #endif 138 488 } 139 489 140 490 ST_INLN void sym_free(Sym *sym) 141 491 { 492 #ifndef SYM_DEBUG 142 493 sym->next = sym_free_first; 143 tcc_free(sym->asm_label);144 494 sym_free_first = sym; 495 #else 496 tcc_free(sym); 497 #endif 145 498 } 146 499 147 500 /* push, without hashing */ 148 ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, longc)501 ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c) 149 502 { 150 503 Sym *s; 151 if (ps == &local_stack) { 152 for (s = *ps; s && s != scope_stack_bottom; s = s->prev) 153 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM && s->v == v) 154 tcc_error("incompatible types for redefinition of '%s'", 155 get_tok_str(v, NULL)); 156 } 157 s = *ps; 504 158 505 s = sym_malloc(); 159 s->asm_label = NULL;506 memset(s, 0, sizeof *s); 160 507 s->v = v; 161 508 s->type.t = t; 162 s->type.ref = NULL;163 #ifdef _WIN64164 s->d = NULL;165 #endif166 509 s->c = c; 167 s->next = NULL;168 510 /* add in stack */ 169 511 s->prev = *ps; … … 179 521 if (s->v == v) 180 522 return s; 523 else if (s->v == -1) 524 return NULL; 181 525 s = s->prev; 182 526 } … … 226 570 s->prev_tok = *ps; 227 571 *ps = s; 572 s->sym_scope = local_scope; 573 if (s->prev_tok && s->prev_tok->sym_scope == s->sym_scope) 574 tcc_error("redeclaration of '%s'", 575 get_tok_str(v & ~SYM_STRUCT, NULL)); 228 576 } 229 577 return s; … … 240 588 /* modify the top most local identifier, so that 241 589 sym_identifier will point to 's' when popped */ 242 while (*ps != NULL )590 while (*ps != NULL && (*ps)->sym_scope) 243 591 ps = &(*ps)->prev_tok; 244 s->prev_tok = NULL;592 s->prev_tok = *ps; 245 593 *ps = s; 246 594 } … … 248 596 } 249 597 250 /* pop symbols until top reaches 'b' */ 251 ST_FUNC void sym_pop(Sym **ptop, Sym *b) 598 /* pop symbols until top reaches 'b'. If KEEP is non-zero don't really 599 pop them yet from the list, but do remove them from the token array. */ 600 ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep) 252 601 { 253 602 Sym *s, *ss, **ps; … … 269 618 *ps = s->prev_tok; 270 619 } 271 sym_free(s); 620 if (!keep) 621 sym_free(s); 272 622 s = ss; 273 623 } 274 *ptop = b; 275 } 276 277 static void weaken_symbol(Sym *sym) 278 { 279 sym->type.t |= VT_WEAK; 280 if (sym->c > 0) { 281 int esym_type; 282 ElfW(Sym) *esym; 283 284 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; 285 esym_type = ELFW(ST_TYPE)(esym->st_info); 286 esym->st_info = ELFW(ST_INFO)(STB_WEAK, esym_type); 287 } 624 if (!keep) 625 *ptop = b; 288 626 } 289 627 290 628 /* ------------------------------------------------------------------------- */ 291 629 292 ST_FUNC void swap(int *p, int *q)293 {294 int t;295 t = *p;296 *p = *q;297 *q = t;298 }299 300 630 static void vsetc(CType *type, int r, CValue *vc) 301 631 { … … 303 633 304 634 if (vtop >= vstack + (VSTACK_SIZE - 1)) 305 tcc_error("memory full ");635 tcc_error("memory full (vstack)"); 306 636 /* cannot let cpu flags if other instruction are generated. Also 307 637 avoid leaving VT_JMP anywhere except on the top of the stack 308 because it would complicate the code generator. */ 309 if (vtop >= vstack) { 638 because it would complicate the code generator. 639 640 Don't do this when nocode_wanted. vtop might come from 641 !nocode_wanted regions (see 88_codeopt.c) and transforming 642 it to a register without actually generating code is wrong 643 as their value might still be used for real. All values 644 we push under nocode_wanted will eventually be popped 645 again, so that the VT_CMP/VT_JMP value will be in vtop 646 when code is unsuppressed again. 647 648 Same logic below in vswap(); */ 649 if (vtop >= vstack && !nocode_wanted) { 310 650 v = vtop->r & VT_VALMASK; 311 651 if (v == VT_CMP || (v & ~1) == VT_JMP) 312 652 gv(RC_INT); 313 653 } 654 314 655 vtop++; 315 656 vtop->type = *type; … … 317 658 vtop->r2 = VT_CONST; 318 659 vtop->c = *vc; 660 vtop->sym = NULL; 661 } 662 663 ST_FUNC void vswap(void) 664 { 665 SValue tmp; 666 /* cannot vswap cpu flags. See comment at vsetc() above */ 667 if (vtop >= vstack && !nocode_wanted) { 668 int v = vtop->r & VT_VALMASK; 669 if (v == VT_CMP || (v & ~1) == VT_JMP) 670 gv(RC_INT); 671 } 672 tmp = vtop[0]; 673 vtop[0] = vtop[-1]; 674 vtop[-1] = tmp; 675 } 676 677 /* pop stack value */ 678 ST_FUNC void vpop(void) 679 { 680 int v; 681 v = vtop->r & VT_VALMASK; 682 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) 683 /* for x86, we need to pop the FP stack */ 684 if (v == TREG_ST0) { 685 o(0xd8dd); /* fstp %st(0) */ 686 } else 687 #endif 688 if (v == VT_JMP || v == VT_JMPI) { 689 /* need to put correct jump if && or || without test */ 690 gsym(vtop->c.i); 691 } 692 vtop--; 319 693 } 320 694 321 695 /* push constant of type "type" with useless value */ 322 void vpush(CType *type) 323 { 324 CValue cval; 325 vsetc(type, VT_CONST, &cval); 696 ST_FUNC void vpush(CType *type) 697 { 698 vset(type, VT_CONST, 0); 326 699 } 327 700 … … 335 708 336 709 /* push a pointer sized constant */ 337 static void vpushs( long longv)710 static void vpushs(addr_t v) 338 711 { 339 712 CValue cval; 340 if (PTR_SIZE == 4) 341 cval.i = (int)v; 342 else 343 cval.ull = v; 713 cval.i = v; 344 714 vsetc(&size_type, VT_CONST, &cval); 345 715 } 346 716 347 717 /* push arbitrary 64bit constant */ 348 void vpush64(int ty, unsigned long long v)718 ST_FUNC void vpush64(int ty, unsigned long long v) 349 719 { 350 720 CValue cval; … … 352 722 ctype.t = ty; 353 723 ctype.ref = NULL; 354 cval. ull= v;724 cval.i = v; 355 725 vsetc(&ctype, VT_CONST, &cval); 356 726 } … … 360 730 { 361 731 vpush64(VT_LLONG, v); 732 } 733 734 ST_FUNC void vset(CType *type, int r, int v) 735 { 736 CValue cval; 737 738 cval.i = v; 739 vsetc(type, r, &cval); 740 } 741 742 static void vseti(int r, int v) 743 { 744 CType type; 745 type.t = VT_INT; 746 type.ref = NULL; 747 vset(&type, r, v); 748 } 749 750 ST_FUNC void vpushv(SValue *v) 751 { 752 if (vtop >= vstack + (VSTACK_SIZE - 1)) 753 tcc_error("memory full (vstack)"); 754 vtop++; 755 *vtop = *v; 756 } 757 758 static void vdup(void) 759 { 760 vpushv(vtop); 761 } 762 763 /* rotate n first stack elements to the bottom 764 I1 ... In -> I2 ... In I1 [top is right] 765 */ 766 ST_FUNC void vrotb(int n) 767 { 768 int i; 769 SValue tmp; 770 771 tmp = vtop[-n + 1]; 772 for(i=-n+1;i!=0;i++) 773 vtop[i] = vtop[i+1]; 774 vtop[0] = tmp; 775 } 776 777 /* rotate the n elements before entry e towards the top 778 I1 ... In ... -> In I1 ... I(n-1) ... [top is right] 779 */ 780 ST_FUNC void vrote(SValue *e, int n) 781 { 782 int i; 783 SValue tmp; 784 785 tmp = *e; 786 for(i = 0;i < n - 1; i++) 787 e[-i] = e[-i - 1]; 788 e[-n + 1] = tmp; 789 } 790 791 /* rotate n first stack elements to the top 792 I1 ... In -> In I1 ... I(n-1) [top is right] 793 */ 794 ST_FUNC void vrott(int n) 795 { 796 vrote(vtop, n); 797 } 798 799 /* push a symbol value of TYPE */ 800 static inline void vpushsym(CType *type, Sym *sym) 801 { 802 CValue cval; 803 cval.i = 0; 804 vsetc(type, VT_CONST | VT_SYM, &cval); 805 vtop->sym = sym; 362 806 } 363 807 … … 379 823 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size) 380 824 { 381 CValue cval; 382 383 cval.ul = 0; 384 vsetc(type, VT_CONST | VT_SYM, &cval); 385 vtop->sym = get_sym_ref(type, sec, offset, size); 825 vpushsym(type, get_sym_ref(type, sec, offset, size)); 386 826 } 387 827 … … 397 837 s->type.ref = type->ref; 398 838 s->r = r | VT_CONST | VT_SYM; 839 } else if (IS_ASM_SYM(s)) { 840 s->type.t = type->t | (s->type.t & VT_EXTERN); 841 s->type.ref = type->ref; 842 update_storage(s); 399 843 } 400 844 return s; 401 845 } 402 846 403 /* define a new external reference to a symbol 'v' with alternate asm 404 name 'asm_label' of type 'u'. 'asm_label' is equal to NULL if there 405 is no alternate name (most cases) */ 406 static Sym *external_sym(int v, CType *type, int r, char *asm_label) 847 /* Merge some type attributes. */ 848 static void patch_type(Sym *sym, CType *type) 849 { 850 if (!(type->t & VT_EXTERN)) { 851 if (!(sym->type.t & VT_EXTERN)) 852 tcc_error("redefinition of '%s'", get_tok_str(sym->v, NULL)); 853 sym->type.t &= ~VT_EXTERN; 854 } 855 856 if (IS_ASM_SYM(sym)) { 857 /* stay static if both are static */ 858 sym->type.t = type->t & (sym->type.t | ~VT_STATIC); 859 sym->type.ref = type->ref; 860 } 861 862 if (!is_compatible_types(&sym->type, type)) { 863 tcc_error("incompatible types for redefinition of '%s'", 864 get_tok_str(sym->v, NULL)); 865 866 } else if ((sym->type.t & VT_BTYPE) == VT_FUNC) { 867 int static_proto = sym->type.t & VT_STATIC; 868 /* warn if static follows non-static function declaration */ 869 if ((type->t & VT_STATIC) && !static_proto && !(type->t & VT_INLINE)) 870 tcc_warning("static storage ignored for redefinition of '%s'", 871 get_tok_str(sym->v, NULL)); 872 873 if (0 == (type->t & VT_EXTERN)) { 874 /* put complete type, use static from prototype */ 875 sym->type.t = (type->t & ~VT_STATIC) | static_proto; 876 if (type->t & VT_INLINE) 877 sym->type.t = type->t; 878 sym->type.ref = type->ref; 879 } 880 881 } else { 882 if ((sym->type.t & VT_ARRAY) && type->ref->c >= 0) { 883 /* set array size if it was omitted in extern declaration */ 884 if (sym->type.ref->c < 0) 885 sym->type.ref->c = type->ref->c; 886 else if (sym->type.ref->c != type->ref->c) 887 tcc_error("conflicting type for '%s'", get_tok_str(sym->v, NULL)); 888 } 889 if ((type->t ^ sym->type.t) & VT_STATIC) 890 tcc_warning("storage mismatch for redefinition of '%s'", 891 get_tok_str(sym->v, NULL)); 892 } 893 } 894 895 896 /* Merge some storage attributes. */ 897 static void patch_storage(Sym *sym, AttributeDef *ad, CType *type) 898 { 899 if (type) 900 patch_type(sym, type); 901 902 #ifdef TCC_TARGET_PE 903 if (sym->a.dllimport != ad->a.dllimport) 904 tcc_error("incompatible dll linkage for redefinition of '%s'", 905 get_tok_str(sym->v, NULL)); 906 sym->a.dllexport |= ad->a.dllexport; 907 #endif 908 sym->a.weak |= ad->a.weak; 909 if (ad->a.visibility) { 910 int vis = sym->a.visibility; 911 int vis2 = ad->a.visibility; 912 if (vis == STV_DEFAULT) 913 vis = vis2; 914 else if (vis2 != STV_DEFAULT) 915 vis = (vis < vis2) ? vis : vis2; 916 sym->a.visibility = vis; 917 } 918 if (ad->a.aligned) 919 sym->a.aligned = ad->a.aligned; 920 if (ad->asm_label) 921 sym->asm_label = ad->asm_label; 922 update_storage(sym); 923 } 924 925 /* define a new external reference to a symbol 'v' */ 926 static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad) 407 927 { 408 928 Sym *s; 409 410 929 s = sym_find(v); 411 930 if (!s) { 412 931 /* push forward reference */ 413 932 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0); 414 s->asm_label = asm_label;415 933 s->type.t |= VT_EXTERN; 416 } else if (s->type.ref == func_old_type.ref) { 417 s->type.ref = type->ref; 418 s->r = r | VT_CONST | VT_SYM; 419 s->type.t |= VT_EXTERN; 420 } else if (!is_compatible_types(&s->type, type)) { 421 tcc_error("incompatible types for redefinition of '%s'", 422 get_tok_str(v, NULL)); 934 s->a = ad->a; 935 s->sym_scope = 0; 936 } else { 937 if (s->type.ref == func_old_type.ref) { 938 s->type.ref = type->ref; 939 s->r = r | VT_CONST | VT_SYM; 940 s->type.t |= VT_EXTERN; 941 } 942 patch_storage(s, ad, type); 423 943 } 424 944 return s; … … 428 948 ST_FUNC void vpush_global_sym(CType *type, int v) 429 949 { 430 Sym *sym; 431 CValue cval; 432 433 sym = external_global_sym(v, type, 0); 434 cval.ul = 0; 435 vsetc(type, VT_CONST | VT_SYM, &cval); 436 vtop->sym = sym; 437 } 438 439 ST_FUNC void vset(CType *type, int r, int v) 440 { 441 CValue cval; 442 443 cval.i = v; 444 vsetc(type, r, &cval); 445 } 446 447 static void vseti(int r, int v) 448 { 449 CType type; 450 type.t = VT_INT; 451 type.ref = 0; 452 vset(&type, r, v); 453 } 454 455 ST_FUNC void vswap(void) 456 { 457 SValue tmp; 458 /* cannot let cpu flags if other instruction are generated. Also 459 avoid leaving VT_JMP anywhere except on the top of the stack 460 because it would complicate the code generator. */ 461 if (vtop >= vstack) { 462 int v = vtop->r & VT_VALMASK; 463 if (v == VT_CMP || (v & ~1) == VT_JMP) 464 gv(RC_INT); 465 } 466 tmp = vtop[0]; 467 vtop[0] = vtop[-1]; 468 vtop[-1] = tmp; 469 470 /* XXX: +2% overall speed possible with optimized memswap 471 * 472 * memswap(&vtop[0], &vtop[1], sizeof *vtop); 473 */ 474 } 475 476 ST_FUNC void vpushv(SValue *v) 477 { 478 if (vtop >= vstack + (VSTACK_SIZE - 1)) 479 tcc_error("memory full"); 480 vtop++; 481 *vtop = *v; 482 } 483 484 static void vdup(void) 485 { 486 vpushv(vtop); 950 vpushsym(type, external_global_sym(v, type, 0)); 951 } 952 953 /* save registers up to (vtop - n) stack entry */ 954 ST_FUNC void save_regs(int n) 955 { 956 SValue *p, *p1; 957 for(p = vstack, p1 = vtop - n; p <= p1; p++) 958 save_reg(p->r); 487 959 } 488 960 … … 490 962 ST_FUNC void save_reg(int r) 491 963 { 964 save_reg_upstack(r, 0); 965 } 966 967 /* save r to the memory stack, and mark it as being free, 968 if seen up to (vtop - n) stack entry */ 969 ST_FUNC void save_reg_upstack(int r, int n) 970 { 492 971 int l, saved, size, align; 493 SValue *p, sv;972 SValue *p, *p1, sv; 494 973 CType *type; 974 975 if ((r &= VT_VALMASK) >= VT_CONST) 976 return; 977 if (nocode_wanted) 978 return; 495 979 496 980 /* modify all stack values */ 497 981 saved = 0; 498 982 l = 0; 499 for(p =vstack;p<=vtop;p++) {983 for(p = vstack, p1 = vtop - n; p <= p1; p++) { 500 984 if ((p->r & VT_VALMASK) == r || 501 985 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) { … … 508 992 if ((p->r & VT_LVAL) || 509 993 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG)) 510 #if def TCC_TARGET_X86_64994 #if PTR_SIZE == 8 511 995 type = &char_pointer_type; 512 996 #else … … 517 1001 sv.type.t = type->t; 518 1002 sv.r = VT_LOCAL | VT_LVAL; 519 sv.c. ul= loc;1003 sv.c.i = loc; 520 1004 store(r, &sv); 521 1005 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) … … 525 1009 } 526 1010 #endif 527 #if ndef TCC_TARGET_X86_641011 #if PTR_SIZE == 4 528 1012 /* special long long case */ 529 1013 if ((type->t & VT_BTYPE) == VT_LLONG) { 530 sv.c. ul+= 4;1014 sv.c.i += 4; 531 1015 store(p->r2, &sv); 532 1016 } … … 539 1023 /* also clear the bounded flag because the 540 1024 relocation address of the function was stored in 541 p->c. ul*/1025 p->c.i */ 542 1026 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL; 543 1027 } else { … … 545 1029 } 546 1030 p->r2 = VT_CONST; 547 p->c. ul= l;1031 p->c.i = l; 548 1032 } 549 1033 } … … 584 1068 for(r=0;r<NB_REGS;r++) { 585 1069 if (reg_classes[r] & rc) { 1070 if (nocode_wanted) 1071 return r; 586 1072 for(p=vstack;p<=vtop;p++) { 587 1073 if ((p->r & VT_VALMASK) == r || … … 613 1099 } 614 1100 615 /* save registers up to (vtop - n) stack entry */ 616 ST_FUNC void save_regs(int n) 617 { 618 int r; 619 SValue *p, *p1; 620 p1 = vtop - n; 621 for(p = vstack;p <= p1; p++) { 622 r = p->r & VT_VALMASK; 623 if (r < VT_CONST) { 624 save_reg(r); 625 } 626 } 627 } 628 629 /* move register 's' to 'r', and flush previous value of r to memory 1101 /* move register 's' (of type 't') to 'r', and flush previous value of r to memory 630 1102 if needed */ 631 static void move_reg(int r, int s )1103 static void move_reg(int r, int s, int t) 632 1104 { 633 1105 SValue sv; … … 635 1107 if (r != s) { 636 1108 save_reg(r); 637 sv.type.t = VT_INT; 1109 sv.type.t = t; 1110 sv.type.ref = NULL; 638 1111 sv.r = s; 639 sv.c. ul= 0;1112 sv.c.i = 0; 640 1113 load(r, &sv); 641 1114 } … … 643 1116 644 1117 /* get address of vtop (vtop MUST BE an lvalue) */ 645 static void gaddrof(void) 646 { 647 if (vtop->r & VT_REF) 648 gv(RC_INT); 1118 ST_FUNC void gaddrof(void) 1119 { 649 1120 vtop->r &= ~VT_LVAL; 650 1121 /* tricky: if saved lvalue, then we can go back to lvalue */ … … 670 1141 /* must save type because we must set it to int to get pointer */ 671 1142 type1 = vtop->type; 672 vtop->type.t = VT_ INT;1143 vtop->type.t = VT_PTR; 673 1144 gaddrof(); 674 1145 vpushi(0); … … 683 1154 #endif 684 1155 1156 static void incr_bf_adr(int o) 1157 { 1158 vtop->type = char_pointer_type; 1159 gaddrof(); 1160 vpushi(o); 1161 gen_op('+'); 1162 vtop->type.t = (vtop->type.t & ~(VT_BTYPE|VT_DEFSIGN)) 1163 | (VT_BYTE|VT_UNSIGNED); 1164 vtop->r = (vtop->r & ~VT_LVAL_TYPE) 1165 | (VT_LVAL_BYTE|VT_LVAL_UNSIGNED|VT_LVAL); 1166 } 1167 1168 /* single-byte load mode for packed or otherwise unaligned bitfields */ 1169 static void load_packed_bf(CType *type, int bit_pos, int bit_size) 1170 { 1171 int n, o, bits; 1172 save_reg_upstack(vtop->r, 1); 1173 vpush64(type->t & VT_BTYPE, 0); // B X 1174 bits = 0, o = bit_pos >> 3, bit_pos &= 7; 1175 do { 1176 vswap(); // X B 1177 incr_bf_adr(o); 1178 vdup(); // X B B 1179 n = 8 - bit_pos; 1180 if (n > bit_size) 1181 n = bit_size; 1182 if (bit_pos) 1183 vpushi(bit_pos), gen_op(TOK_SHR), bit_pos = 0; // X B Y 1184 if (n < 8) 1185 vpushi((1 << n) - 1), gen_op('&'); 1186 gen_cast(type); 1187 if (bits) 1188 vpushi(bits), gen_op(TOK_SHL); 1189 vrotb(3); // B Y X 1190 gen_op('|'); // B X 1191 bits += n, bit_size -= n, o = 1; 1192 } while (bit_size); 1193 vswap(), vpop(); 1194 if (!(type->t & VT_UNSIGNED)) { 1195 n = ((type->t & VT_BTYPE) == VT_LLONG ? 64 : 32) - bits; 1196 vpushi(n), gen_op(TOK_SHL); 1197 vpushi(n), gen_op(TOK_SAR); 1198 } 1199 } 1200 1201 /* single-byte store mode for packed or otherwise unaligned bitfields */ 1202 static void store_packed_bf(int bit_pos, int bit_size) 1203 { 1204 int bits, n, o, m, c; 1205 1206 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; 1207 vswap(); // X B 1208 save_reg_upstack(vtop->r, 1); 1209 bits = 0, o = bit_pos >> 3, bit_pos &= 7; 1210 do { 1211 incr_bf_adr(o); // X B 1212 vswap(); //B X 1213 c ? vdup() : gv_dup(); // B V X 1214 vrott(3); // X B V 1215 if (bits) 1216 vpushi(bits), gen_op(TOK_SHR); 1217 if (bit_pos) 1218 vpushi(bit_pos), gen_op(TOK_SHL); 1219 n = 8 - bit_pos; 1220 if (n > bit_size) 1221 n = bit_size; 1222 if (n < 8) { 1223 m = ((1 << n) - 1) << bit_pos; 1224 vpushi(m), gen_op('&'); // X B V1 1225 vpushv(vtop-1); // X B V1 B 1226 vpushi(m & 0x80 ? ~m & 0x7f : ~m); 1227 gen_op('&'); // X B V1 B1 1228 gen_op('|'); // X B V2 1229 } 1230 vdup(), vtop[-1] = vtop[-2]; // X B B V2 1231 vstore(), vpop(); // X B 1232 bits += n, bit_size -= n, bit_pos = 0, o = 1; 1233 } while (bit_size); 1234 vpop(), vpop(); 1235 } 1236 1237 static int adjust_bf(SValue *sv, int bit_pos, int bit_size) 1238 { 1239 int t; 1240 if (0 == sv->type.ref) 1241 return 0; 1242 t = sv->type.ref->auxtype; 1243 if (t != -1 && t != VT_STRUCT) { 1244 sv->type.t = (sv->type.t & ~VT_BTYPE) | t; 1245 sv->r = (sv->r & ~VT_LVAL_TYPE) | lvalue_type(sv->type.t); 1246 } 1247 return t; 1248 } 1249 685 1250 /* store vtop a register belonging to class 'rc'. lvalues are 686 1251 converted to values. Cannot be used if cannot be converted to … … 688 1253 ST_FUNC int gv(int rc) 689 1254 { 690 int r, bit_pos, bit_size, size, align, i; 691 #ifndef TCC_TARGET_X86_64 692 int rc2; 693 #endif 1255 int r, bit_pos, bit_size, size, align, rc2; 694 1256 695 1257 /* NOTE: get_reg can modify vstack[] */ 696 1258 if (vtop->type.t & VT_BITFIELD) { 697 1259 CType type; 698 int bits = 32; 699 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;700 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;1260 1261 bit_pos = BIT_POS(vtop->type.t); 1262 bit_size = BIT_SIZE(vtop->type.t); 701 1263 /* remove bit field info to avoid loops */ 702 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)); 703 /* cast to int to propagate signedness in following ops */ 704 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) { 705 type.t = VT_LLONG; 706 bits = 64; 707 } else 708 type.t = VT_INT; 709 if((vtop->type.t & VT_UNSIGNED) || 710 (vtop->type.t & VT_BTYPE) == VT_BOOL) 1264 vtop->type.t &= ~VT_STRUCT_MASK; 1265 1266 type.ref = NULL; 1267 type.t = vtop->type.t & VT_UNSIGNED; 1268 if ((vtop->type.t & VT_BTYPE) == VT_BOOL) 711 1269 type.t |= VT_UNSIGNED; 712 gen_cast(&type); 713 /* generate shifts */ 714 vpushi(bits - (bit_pos + bit_size)); 715 gen_op(TOK_SHL); 716 vpushi(bits - bit_size); 717 /* NOTE: transformed to SHR if unsigned */ 718 gen_op(TOK_SAR); 1270 1271 r = adjust_bf(vtop, bit_pos, bit_size); 1272 1273 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) 1274 type.t |= VT_LLONG; 1275 else 1276 type.t |= VT_INT; 1277 1278 if (r == VT_STRUCT) { 1279 load_packed_bf(&type, bit_pos, bit_size); 1280 } else { 1281 int bits = (type.t & VT_BTYPE) == VT_LLONG ? 64 : 32; 1282 /* cast to int to propagate signedness in following ops */ 1283 gen_cast(&type); 1284 /* generate shifts */ 1285 vpushi(bits - (bit_pos + bit_size)); 1286 gen_op(TOK_SHL); 1287 vpushi(bits - bit_size); 1288 /* NOTE: transformed to SHR if unsigned */ 1289 gen_op(TOK_SAR); 1290 } 719 1291 r = gv(rc); 720 1292 } else { 721 1293 if (is_float(vtop->type.t) && 722 1294 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { 723 Sym *sym;724 int *ptr;725 1295 unsigned long offset; 726 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)727 CValue check;728 #endif729 730 /* XXX: unify with initializers handling ? */731 1296 /* CPUs usually cannot use float constants, so we store them 732 1297 generically in data segment */ 733 1298 size = type_size(&vtop->type, &align); 734 offset = (data_section->data_offset + align - 1) & -align; 735 data_section->data_offset = offset; 736 /* XXX: not portable yet */ 737 #if defined(__i386__) || defined(__x86_64__) 738 /* Zero pad x87 tenbyte long doubles */ 739 if (size == LDOUBLE_SIZE) { 740 vtop->c.tab[2] &= 0xffff; 741 #if LDOUBLE_SIZE == 16 742 vtop->c.tab[3] = 0; 743 #endif 744 } 745 #endif 746 ptr = section_ptr_add(data_section, size); 747 size = size >> 2; 748 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP) 749 check.d = 1; 750 if(check.tab[0]) 751 for(i=0;i<size;i++) 752 ptr[i] = vtop->c.tab[size-1-i]; 753 else 754 #endif 755 for(i=0;i<size;i++) 756 ptr[i] = vtop->c.tab[i]; 757 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2); 758 vtop->r |= VT_LVAL | VT_SYM; 759 vtop->sym = sym; 760 vtop->c.ul = 0; 1299 if (NODATA_WANTED) 1300 size = 0, align = 1; 1301 offset = section_add(data_section, size, align); 1302 vpush_ref(&vtop->type, data_section, offset, size); 1303 vswap(); 1304 init_putv(&vtop->type, data_section, offset); 1305 vtop->r |= VT_LVAL; 761 1306 } 762 1307 #ifdef CONFIG_TCC_BCHECK … … 766 1311 767 1312 r = vtop->r & VT_VALMASK; 768 #ifndef TCC_TARGET_X86_64 769 rc2 = RC_INT; 1313 rc2 = (rc & RC_FLOAT) ? RC_FLOAT : RC_INT; 1314 #ifndef TCC_TARGET_ARM64 770 1315 if (rc == RC_IRET) 771 1316 rc2 = RC_LRET; 1317 #ifdef TCC_TARGET_X86_64 1318 else if (rc == RC_FRET) 1319 rc2 = RC_QRET; 1320 #endif 772 1321 #endif 773 1322 /* need to reload if: … … 778 1327 || (vtop->r & VT_LVAL) 779 1328 || !(reg_classes[r] & rc) 780 #ifndef TCC_TARGET_X86_64 1329 #if PTR_SIZE == 8 1330 || ((vtop->type.t & VT_BTYPE) == VT_QLONG && !(reg_classes[vtop->r2] & rc2)) 1331 || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT && !(reg_classes[vtop->r2] & rc2)) 1332 #else 781 1333 || ((vtop->type.t & VT_BTYPE) == VT_LLONG && !(reg_classes[vtop->r2] & rc2)) 782 1334 #endif … … 784 1336 { 785 1337 r = get_reg(rc); 786 #ifndef TCC_TARGET_X86_64 1338 #if PTR_SIZE == 8 1339 if (((vtop->type.t & VT_BTYPE) == VT_QLONG) || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT)) { 1340 int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE; 1341 #else 787 1342 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) { 788 int r2;1343 int addr_type = VT_INT, load_size = 4, load_type = VT_INT; 789 1344 unsigned long long ll; 1345 #endif 1346 int r2, original_type; 1347 original_type = vtop->type.t; 790 1348 /* two register type load : expand to two words 791 1349 temporarily */ 1350 #if PTR_SIZE == 4 792 1351 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { 793 1352 /* load constant */ 794 ll = vtop->c. ull;795 vtop->c. ui = ll; /* first word */1353 ll = vtop->c.i; 1354 vtop->c.i = ll; /* first word */ 796 1355 load(r, vtop); 797 1356 vtop->r = r; /* save register value */ 798 1357 vpushi(ll >> 32); /* second word */ 799 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */ 800 (vtop->r & VT_LVAL)) { 1358 } else 1359 #endif 1360 if (vtop->r & VT_LVAL) { 801 1361 /* We do not want to modifier the long long 802 1362 pointer here, so the safest (and less 803 1363 efficient) is to save all the other registers 804 1364 in the stack. XXX: totally inefficient. */ 1365 #if 0 805 1366 save_regs(1); 1367 #else 1368 /* lvalue_save: save only if used further down the stack */ 1369 save_reg_upstack(vtop->r, 1); 1370 #endif 806 1371 /* load from memory */ 1372 vtop->type.t = load_type; 807 1373 load(r, vtop); 808 1374 vdup(); 809 1375 vtop[-1].r = r; /* save register value */ 810 1376 /* increment pointer to get second word */ 811 vtop->type.t = VT_INT;1377 vtop->type.t = addr_type; 812 1378 gaddrof(); 813 vpushi( 4);1379 vpushi(load_size); 814 1380 gen_op('+'); 815 1381 vtop->r |= VT_LVAL; 1382 vtop->type.t = load_type; 816 1383 } else { 817 1384 /* move registers */ … … 828 1395 /* write second register */ 829 1396 vtop->r2 = r2; 830 } else 831 #endif 832 if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) { 1397 vtop->type.t = original_type; 1398 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) { 833 1399 int t1, t; 834 1400 /* lvalue of scalar type : need to use lvalue type … … 894 1460 } 895 1461 1462 #ifndef TCC_TARGET_ARM64 896 1463 /* wrapper around RC_FRET to return a register by type */ 897 1464 static int rc_fret(int t) … … 904 1471 return RC_FRET; 905 1472 } 1473 #endif 906 1474 907 1475 /* wrapper around REG_FRET to return a register by type */ … … 916 1484 } 917 1485 918 /* expand long long on stack in two int registers */ 1486 #if PTR_SIZE == 4 1487 /* expand 64bit on stack in two ints */ 919 1488 static void lexpand(void) 920 1489 { 921 int u; 922 923 u = vtop->type.t & VT_UNSIGNED; 924 gv(RC_INT); 925 vdup(); 926 vtop[0].r = vtop[-1].r2; 927 vtop[0].r2 = VT_CONST; 928 vtop[-1].r2 = VT_CONST; 929 vtop[0].type.t = VT_INT | u; 930 vtop[-1].type.t = VT_INT | u; 931 } 1490 int u, v; 1491 u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED); 1492 v = vtop->r & (VT_VALMASK | VT_LVAL); 1493 if (v == VT_CONST) { 1494 vdup(); 1495 vtop[0].c.i >>= 32; 1496 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) { 1497 vdup(); 1498 vtop[0].c.i += 4; 1499 } else { 1500 gv(RC_INT); 1501 vdup(); 1502 vtop[0].r = vtop[-1].r2; 1503 vtop[0].r2 = vtop[-1].r2 = VT_CONST; 1504 } 1505 vtop[0].type.t = vtop[-1].type.t = VT_INT | u; 1506 } 1507 #endif 932 1508 933 1509 #ifdef TCC_TARGET_ARM … … 937 1513 int u,v; 938 1514 939 u = vtop->type.t & VT_UNSIGNED;1515 u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED); 940 1516 vdup(); 941 1517 vtop->r2 = VT_CONST; … … 943 1519 v=vtop[-1].r & (VT_VALMASK | VT_LVAL); 944 1520 if (v == VT_CONST) { 945 vtop[-1].c. ui = vtop->c.ull;946 vtop->c. ui = vtop->c.ull>> 32;1521 vtop[-1].c.i = vtop->c.i; 1522 vtop->c.i = vtop->c.i >> 32; 947 1523 vtop->r = VT_CONST; 948 1524 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) { 949 vtop->c. ui += 4;1525 vtop->c.i += 4; 950 1526 vtop->r = vtop[-1].r; 951 1527 } else if (v > VT_CONST) { … … 959 1535 #endif 960 1536 1537 #if PTR_SIZE == 4 961 1538 /* build a long long from two ints */ 962 1539 static void lbuild(int t) … … 967 1544 vpop(); 968 1545 } 969 970 /* rotate n first stack elements to the bottom 971 I1 ... In -> I2 ... In I1 [top is right] 972 */ 973 ST_FUNC void vrotb(int n) 974 { 975 int i; 976 SValue tmp; 977 978 tmp = vtop[-n + 1]; 979 for(i=-n+1;i!=0;i++) 980 vtop[i] = vtop[i+1]; 981 vtop[0] = tmp; 982 } 983 984 /* rotate the n elements before entry e towards the top 985 I1 ... In ... -> In I1 ... I(n-1) ... [top is right] 986 */ 987 ST_FUNC void vrote(SValue *e, int n) 988 { 989 int i; 990 SValue tmp; 991 992 tmp = *e; 993 for(i = 0;i < n - 1; i++) 994 e[-i] = e[-i - 1]; 995 e[-n + 1] = tmp; 996 } 997 998 /* rotate n first stack elements to the top 999 I1 ... In -> In I1 ... I(n-1) [top is right] 1000 */ 1001 ST_FUNC void vrott(int n) 1002 { 1003 vrote(vtop, n); 1004 } 1005 1006 /* pop stack value */ 1007 ST_FUNC void vpop(void) 1008 { 1009 int v; 1010 v = vtop->r & VT_VALMASK; 1011 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) 1012 /* for x86, we need to pop the FP stack */ 1013 if (v == TREG_ST0 && !nocode_wanted) { 1014 o(0xd8dd); /* fstp %st(0) */ 1015 } else 1016 #endif 1017 if (v == VT_JMP || v == VT_JMPI) { 1018 /* need to put correct jump if && or || without test */ 1019 gsym(vtop->c.ul); 1020 } 1021 vtop--; 1022 } 1546 #endif 1023 1547 1024 1548 /* convert stack entry to register and duplicate its value in another … … 1030 1554 1031 1555 t = vtop->type.t; 1556 #if PTR_SIZE == 4 1032 1557 if ((t & VT_BTYPE) == VT_LLONG) { 1558 if (t & VT_BITFIELD) { 1559 gv(RC_INT); 1560 t = vtop->type.t; 1561 } 1033 1562 lexpand(); 1034 1563 gv_dup(); … … 1044 1573 lbuild(t); 1045 1574 vswap(); 1046 } else { 1575 } else 1576 #endif 1577 { 1047 1578 /* duplicate value */ 1048 1579 rc = RC_INT; … … 1060 1591 r1 = get_reg(rc); 1061 1592 sv.r = r; 1062 sv.c. ul= 0;1593 sv.c.i = 0; 1063 1594 load(r1, &sv); /* move r to r1 */ 1064 1595 vdup(); … … 1069 1600 } 1070 1601 1071 #ifndef TCC_TARGET_X86_64 1602 /* Generate value test 1603 * 1604 * Generate a test for any value (jump, comparison and integers) */ 1605 ST_FUNC int gvtst(int inv, int t) 1606 { 1607 int v = vtop->r & VT_VALMASK; 1608 if (v != VT_CMP && v != VT_JMP && v != VT_JMPI) { 1609 vpushi(0); 1610 gen_op(TOK_NE); 1611 } 1612 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { 1613 /* constant jmp optimization */ 1614 if ((vtop->c.i != 0) != inv) 1615 t = gjmp(t); 1616 vtop--; 1617 return t; 1618 } 1619 return gtst(inv, t); 1620 } 1621 1622 #if PTR_SIZE == 4 1072 1623 /* generate CPU independent (unsigned) long long operations */ 1073 1624 static void gen_opl(int op) … … 1112 1663 case '+': 1113 1664 case '-': 1665 //pv("gen_opl A",0,2); 1114 1666 t = vtop->type.t; 1115 1667 vswap(); … … 1126 1678 vswap(); 1127 1679 /* stack: H1 H2 L1 L2 */ 1680 //pv("gen_opl B",0,4); 1128 1681 if (op == '*') { 1129 1682 vpushv(vtop - 1); … … 1181 1734 /* constant: simpler */ 1182 1735 /* NOTE: all comments are for SHL. the other cases are 1183 done by swap ing words */1736 done by swapping words */ 1184 1737 vpop(); 1185 1738 if (op != TOK_SHL) … … 1266 1819 b = 0; 1267 1820 gen_op(op1); 1268 if (op1 != TOK_NE) { 1269 a = gtst(1, 0); 1270 } 1271 if (op != TOK_EQ) { 1272 /* generate non equal test */ 1273 /* XXX: NOT PORTABLE yet */ 1274 if (a == 0) { 1275 b = gtst(0, 0); 1276 } else { 1277 #if defined(TCC_TARGET_I386) 1278 b = psym(0x850f, 0); 1279 #elif defined(TCC_TARGET_ARM) 1280 b = ind; 1281 o(0x1A000000 | encbranch(ind, 0, 1)); 1282 #elif defined(TCC_TARGET_C67) 1283 tcc_error("not implemented"); 1284 #elif defined(TCC_TARGET_IL) 1285 tcc_error("not implemented"); 1286 #else 1287 #error not supported 1288 #endif 1821 if (op == TOK_NE) { 1822 b = gvtst(0, 0); 1823 } else { 1824 a = gvtst(1, 0); 1825 if (op != TOK_EQ) { 1826 /* generate non equal test */ 1827 vpushi(TOK_NE); 1828 vtop->r = VT_CMP; 1829 b = gvtst(0, 0); 1289 1830 } 1290 1831 } … … 1300 1841 op1 = TOK_UGE; 1301 1842 gen_op(op1); 1302 a = g tst(1, a);1843 a = gvtst(1, a); 1303 1844 gsym(b); 1304 1845 vseti(VT_JMPI, a); … … 1308 1849 #endif 1309 1850 1851 static uint64_t gen_opic_sdiv(uint64_t a, uint64_t b) 1852 { 1853 uint64_t x = (a >> 63 ? -a : a) / (b >> 63 ? -b : b); 1854 return (a ^ b) >> 63 ? -x : x; 1855 } 1856 1857 static int gen_opic_lt(uint64_t a, uint64_t b) 1858 { 1859 return (a ^ (uint64_t)1 << 63) < (b ^ (uint64_t)1 << 63); 1860 } 1861 1310 1862 /* handle integer constant optimizations and various machine 1311 1863 independent opt */ 1312 1864 static void gen_opic(int op) 1313 1865 { 1314 int c1, c2, t1, t2, n; 1315 SValue *v1, *v2; 1316 long long l1, l2; 1317 typedef unsigned long long U; 1318 1319 v1 = vtop - 1; 1320 v2 = vtop; 1321 t1 = v1->type.t & VT_BTYPE; 1322 t2 = v2->type.t & VT_BTYPE; 1323 1324 if (t1 == VT_LLONG) 1325 l1 = v1->c.ll; 1326 else if (v1->type.t & VT_UNSIGNED) 1327 l1 = v1->c.ui; 1328 else 1329 l1 = v1->c.i; 1330 1331 if (t2 == VT_LLONG) 1332 l2 = v2->c.ll; 1333 else if (v2->type.t & VT_UNSIGNED) 1334 l2 = v2->c.ui; 1335 else 1336 l2 = v2->c.i; 1337 1338 /* currently, we cannot do computations with forward symbols */ 1339 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; 1340 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; 1866 SValue *v1 = vtop - 1; 1867 SValue *v2 = vtop; 1868 int t1 = v1->type.t & VT_BTYPE; 1869 int t2 = v2->type.t & VT_BTYPE; 1870 int c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; 1871 int c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; 1872 uint64_t l1 = c1 ? v1->c.i : 0; 1873 uint64_t l2 = c2 ? v2->c.i : 0; 1874 int shm = (t1 == VT_LLONG) ? 63 : 31; 1875 1876 if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR)) 1877 l1 = ((uint32_t)l1 | 1878 (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000))); 1879 if (t2 != VT_LLONG && (PTR_SIZE != 8 || t2 != VT_PTR)) 1880 l2 = ((uint32_t)l2 | 1881 (v2->type.t & VT_UNSIGNED ? 0 : -(l2 & 0x80000000))); 1882 1341 1883 if (c1 && c2) { 1342 1884 switch(op) { … … 1360 1902 } 1361 1903 switch(op) { 1362 default: l1 /= l2; break;1363 case '%': l1 %= l2; break;1364 case TOK_UDIV: l1 = (U)l1 / l2; break;1365 case TOK_UMOD: l1 = (U)l1 % l2; break;1904 default: l1 = gen_opic_sdiv(l1, l2); break; 1905 case '%': l1 = l1 - l2 * gen_opic_sdiv(l1, l2); break; 1906 case TOK_UDIV: l1 = l1 / l2; break; 1907 case TOK_UMOD: l1 = l1 % l2; break; 1366 1908 } 1367 1909 break; 1368 case TOK_SHL: l1 <<= l2; break; 1369 case TOK_SHR: l1 = (U)l1 >> l2; break; 1370 case TOK_SAR: l1 >>= l2; break; 1910 case TOK_SHL: l1 <<= (l2 & shm); break; 1911 case TOK_SHR: l1 >>= (l2 & shm); break; 1912 case TOK_SAR: 1913 l1 = (l1 >> 63) ? ~(~l1 >> (l2 & shm)) : l1 >> (l2 & shm); 1914 break; 1371 1915 /* tests */ 1372 case TOK_ULT: l1 = (U)l1 < (U)l2; break;1373 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;1916 case TOK_ULT: l1 = l1 < l2; break; 1917 case TOK_UGE: l1 = l1 >= l2; break; 1374 1918 case TOK_EQ: l1 = l1 == l2; break; 1375 1919 case TOK_NE: l1 = l1 != l2; break; 1376 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;1377 case TOK_UGT: l1 = (U)l1 > (U)l2; break;1378 case TOK_LT: l1 = l1 < l2; break;1379 case TOK_GE: l1 = l1 >= l2; break;1380 case TOK_LE: l1 = l1 <= l2; break;1381 case TOK_GT: l1 = l1 > l2; break;1920 case TOK_ULE: l1 = l1 <= l2; break; 1921 case TOK_UGT: l1 = l1 > l2; break; 1922 case TOK_LT: l1 = gen_opic_lt(l1, l2); break; 1923 case TOK_GE: l1 = !gen_opic_lt(l1, l2); break; 1924 case TOK_LE: l1 = !gen_opic_lt(l2, l1); break; 1925 case TOK_GT: l1 = gen_opic_lt(l2, l1); break; 1382 1926 /* logical */ 1383 1927 case TOK_LAND: l1 = l1 && l2; break; … … 1386 1930 goto general_case; 1387 1931 } 1388 v1->c.ll = l1; 1932 if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR)) 1933 l1 = ((uint32_t)l1 | 1934 (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000))); 1935 v1->c.i = l1; 1389 1936 vtop--; 1390 1937 } else { … … 1396 1943 l2 = l1; //l = l1, l1 = l2, l2 = l; 1397 1944 } 1398 /* Filter out NOP operations like x*1, x-0, x&-1... */ 1399 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV || 1400 op == TOK_PDIV) && 1401 l2 == 1) || 1402 ((op == '+' || op == '-' || op == '|' || op == '^' || 1403 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) && 1404 l2 == 0) || 1405 (op == '&' && 1406 l2 == -1))) { 1407 /* nothing to do */ 1945 if (!const_wanted && 1946 c1 && ((l1 == 0 && 1947 (op == TOK_SHL || op == TOK_SHR || op == TOK_SAR)) || 1948 (l1 == -1 && op == TOK_SAR))) { 1949 /* treat (0 << x), (0 >> x) and (-1 >> x) as constant */ 1950 vtop--; 1951 } else if (!const_wanted && 1952 c2 && ((l2 == 0 && (op == '&' || op == '*')) || 1953 (op == '|' && 1954 (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))) || 1955 (l2 == 1 && (op == '%' || op == TOK_UMOD)))) { 1956 /* treat (x & 0), (x * 0), (x | -1) and (x % 1) as constant */ 1957 if (l2 == 1) 1958 vtop->c.i = 0; 1959 vswap(); 1960 vtop--; 1961 } else if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV || 1962 op == TOK_PDIV) && 1963 l2 == 1) || 1964 ((op == '+' || op == '-' || op == '|' || op == '^' || 1965 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) && 1966 l2 == 0) || 1967 (op == '&' && 1968 (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))))) { 1969 /* filter out NOP operations like x*1, x-0, x&-1... */ 1408 1970 vtop--; 1409 1971 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) { 1410 1972 /* try to use shifts instead of muls or divs */ 1411 1973 if (l2 > 0 && (l2 & (l2 - 1)) == 0) { 1412 n = -1;1974 int n = -1; 1413 1975 while (l2) { 1414 1976 l2 >>= 1; 1415 1977 n++; 1416 1978 } 1417 vtop->c. ll= n;1979 vtop->c.i = n; 1418 1980 if (op == '*') 1419 1981 op = TOK_SHL; … … 1430 1992 if (op == '-') 1431 1993 l2 = -l2; 1994 l2 += vtop[-1].c.i; 1995 /* The backends can't always deal with addends to symbols 1996 larger than +-1<<31. Don't construct such. */ 1997 if ((int)l2 != l2) 1998 goto general_case; 1432 1999 vtop--; 1433 vtop->c. ll += l2;2000 vtop->c.i = l2; 1434 2001 } else { 1435 2002 general_case: 1436 if (!nocode_wanted) {1437 2003 /* call low level op generator */ 1438 if (t1 == VT_LLONG || t2 == VT_LLONG) 2004 if (t1 == VT_LLONG || t2 == VT_LLONG || 2005 (PTR_SIZE == 8 && (t1 == VT_PTR || t2 == VT_PTR))) 1439 2006 gen_opl(op); 1440 2007 else 1441 2008 gen_opi(op); 1442 } else {1443 vtop--;1444 }1445 2009 } 1446 2010 } … … 1452 2016 int c1, c2; 1453 2017 SValue *v1, *v2; 2018 #if defined _MSC_VER && defined _AMD64_ 2019 /* avoid bad optimization with f1 -= f2 for f1:-0.0, f2:0.0 */ 2020 volatile 2021 #endif 1454 2022 long double f1, f2; 1455 2023 … … 1503 2071 } else { 1504 2072 general_case: 1505 if (!nocode_wanted) { 1506 gen_opf(op); 1507 } else { 1508 vtop--; 1509 } 2073 gen_opf(op); 1510 2074 } 1511 2075 } … … 1527 2091 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) 1528 2092 return 0; 1529 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) || 1530 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0) || 1531 ((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr == 0); 2093 return ((p->type.t & VT_BTYPE) == VT_INT && (uint32_t)p->c.i == 0) || 2094 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.i == 0) || 2095 ((p->type.t & VT_BTYPE) == VT_PTR && 2096 (PTR_SIZE == 4 ? (uint32_t)p->c.i == 0 : p->c.i == 0)); 1532 2097 } 1533 2098 … … 1538 2103 } 1539 2104 1540 /* check types for comparison or sub straction of pointers */2105 /* check types for comparison or subtraction of pointers */ 1541 2106 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op) 1542 2107 { … … 1575 2140 tmp_type1 = *type1; 1576 2141 tmp_type2 = *type2; 1577 tmp_type1.t &= ~(VT_ UNSIGNED | VT_CONSTANT | VT_VOLATILE);1578 tmp_type2.t &= ~(VT_ UNSIGNED | VT_CONSTANT | VT_VOLATILE);2142 tmp_type1.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); 2143 tmp_type2.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); 1579 2144 if (!is_compatible_types(&tmp_type1, &tmp_type2)) { 1580 2145 /* gcc-like error if '-' is used */ … … 1592 2157 CType type1; 1593 2158 2159 redo: 1594 2160 t1 = vtop[-1].type.t; 1595 2161 t2 = vtop[0].type.t; … … 1597 2163 bt2 = t2 & VT_BTYPE; 1598 2164 1599 if (bt1 == VT_PTR || bt2 == VT_PTR) { 2165 if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) { 2166 tcc_error("operation on a struct"); 2167 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) { 2168 if (bt2 == VT_FUNC) { 2169 mk_pointer(&vtop->type); 2170 gaddrof(); 2171 } 2172 if (bt1 == VT_FUNC) { 2173 vswap(); 2174 mk_pointer(&vtop->type); 2175 gaddrof(); 2176 vswap(); 2177 } 2178 goto redo; 2179 } else if (bt1 == VT_PTR || bt2 == VT_PTR) { 1600 2180 /* at least one operand is a pointer */ 1601 /* relation nal op: must be both pointers */2181 /* relational op: must be both pointers */ 1602 2182 if (op >= TOK_ULT && op <= TOK_LOR) { 1603 2183 check_comparison_pointer_types(vtop - 1, vtop, op); 1604 2184 /* pointers are handled are unsigned */ 1605 #if def TCC_TARGET_X86_642185 #if PTR_SIZE == 8 1606 2186 t = VT_LLONG | VT_UNSIGNED; 1607 2187 #else … … 1623 2203 vrott(3); 1624 2204 gen_opic(op); 1625 /* set to integer type */ 1626 #ifdef TCC_TARGET_X86_64 1627 vtop->type.t = VT_LLONG; 1628 #else 1629 vtop->type.t = VT_INT; 1630 #endif 2205 vtop->type.t = ptrdiff_type.t; 1631 2206 vswap(); 1632 2207 gen_op(TOK_PDIV); … … 1638 2213 if (bt2 == VT_PTR) { 1639 2214 vswap(); 1640 swap(&t1, &t2); 1641 } 2215 t = t1, t1 = t2, t2 = t; 2216 } 2217 #if PTR_SIZE == 4 2218 if ((vtop[0].type.t & VT_BTYPE) == VT_LLONG) 2219 /* XXX: truncate here because gen_opl can't handle ptr + long long */ 2220 gen_cast_s(VT_INT); 2221 #endif 1642 2222 type1 = vtop[-1].type; 1643 2223 type1.t &= ~VT_ARRAY; … … 1648 2228 if (u < 0) 1649 2229 tcc_error("unknown array element size"); 1650 #if def TCC_TARGET_X86_642230 #if PTR_SIZE == 8 1651 2231 vpushll(u); 1652 2232 #else … … 1656 2236 } 1657 2237 gen_op('*'); 1658 #ifdef CONFIG_TCC_BCHECK 2238 #if 0 2239 /* #ifdef CONFIG_TCC_BCHECK 2240 The main reason to removing this code: 2241 #include <stdio.h> 2242 int main () 2243 { 2244 int v[10]; 2245 int i = 10; 2246 int j = 9; 2247 fprintf(stderr, "v+i-j = %p\n", v+i-j); 2248 fprintf(stderr, "v+(i-j) = %p\n", v+(i-j)); 2249 } 2250 When this code is on. then the output looks like 2251 v+i-j = 0xfffffffe 2252 v+(i-j) = 0xbff84000 2253 */ 1659 2254 /* if evaluating constant expression, no code should be 1660 2255 generated, so no bound check */ … … 1692 2287 } else if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL) { 1693 2288 t = bt1 == VT_LLONG ? VT_LLONG : VT_INT; 1694 if ((t1 & (VT_BTYPE | VT_UNSIGNED )) == (t | VT_UNSIGNED))2289 if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (t | VT_UNSIGNED)) 1695 2290 t |= VT_UNSIGNED; 2291 t |= (VT_LONG & t1); 1696 2292 goto std_op; 1697 2293 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) { 1698 2294 /* cast to biggest op */ 1699 t = VT_LLONG; 2295 t = VT_LLONG | VT_LONG; 2296 if (bt1 == VT_LLONG) 2297 t &= t1; 2298 if (bt2 == VT_LLONG) 2299 t &= t2; 1700 2300 /* convert to unsigned if it does not fit in a long long */ 1701 if ((t1 & (VT_BTYPE | VT_UNSIGNED )) == (VT_LLONG | VT_UNSIGNED) ||1702 (t2 & (VT_BTYPE | VT_UNSIGNED )) == (VT_LLONG | VT_UNSIGNED))2301 if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED) || 2302 (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED)) 1703 2303 t |= VT_UNSIGNED; 1704 2304 goto std_op; 1705 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {1706 tcc_error("comparison of struct");1707 2305 } else { 1708 2306 /* integer operations */ 1709 t = VT_INT ;2307 t = VT_INT | (VT_LONG & (t1 | t2)); 1710 2308 /* convert to unsigned if it does not fit in an integer */ 1711 if ((t1 & (VT_BTYPE | VT_UNSIGNED )) == (VT_INT | VT_UNSIGNED) ||1712 (t2 & (VT_BTYPE | VT_UNSIGNED )) == (VT_INT | VT_UNSIGNED))2309 if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED) || 2310 (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED)) 1713 2311 t |= VT_UNSIGNED; 1714 2312 std_op: … … 1733 2331 vswap(); 1734 2332 type1.t = t; 2333 type1.ref = NULL; 1735 2334 gen_cast(&type1); 1736 2335 vswap(); … … 1745 2344 gen_opic(op); 1746 2345 if (op >= TOK_ULT && op <= TOK_GT) { 1747 /* relation nal op: the result is an int */2346 /* relational op: the result is an int */ 1748 2347 vtop->type.t = VT_INT; 1749 2348 } else { … … 1751 2350 } 1752 2351 } 2352 // Make sure that we have converted to an rvalue: 2353 if (vtop->r & VT_LVAL) 2354 gv(is_float(vtop->type.t & VT_BTYPE) ? RC_FLOAT : RC_INT); 1753 2355 } 1754 2356 … … 1757 2359 static void gen_cvt_itof1(int t) 1758 2360 { 2361 #ifdef TCC_TARGET_ARM64 2362 gen_cvt_itof(t); 2363 #else 1759 2364 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == 1760 2365 (VT_LLONG | VT_UNSIGNED)) { … … 1775 2380 gen_cvt_itof(t); 1776 2381 } 2382 #endif 1777 2383 } 1778 2384 #endif … … 1781 2387 static void gen_cvt_ftoi1(int t) 1782 2388 { 2389 #ifdef TCC_TARGET_ARM64 2390 gen_cvt_ftoi(t); 2391 #else 1783 2392 int st; 1784 2393 … … 1802 2411 gen_cvt_ftoi(t); 1803 2412 } 2413 #endif 1804 2414 } 1805 2415 … … 1808 2418 { 1809 2419 int bits, dbt; 2420 2421 /* cannot cast static initializers */ 2422 if (STATIC_DATA_WANTED) 2423 return; 2424 1810 2425 dbt = t & VT_BTYPE; 1811 2426 /* XXX: add optimization if lvalue : just change type and offset */ … … 1818 2433 gen_op('&'); 1819 2434 } else { 1820 bits = 32 - bits; 2435 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) 2436 bits = 64 - bits; 2437 else 2438 bits = 32 - bits; 1821 2439 vpushi(bits); 1822 2440 gen_op(TOK_SHL); … … 1831 2449 1832 2450 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */ 2451 static void gen_cast_s(int t) 2452 { 2453 CType type; 2454 type.t = t; 2455 type.ref = NULL; 2456 gen_cast(&type); 2457 } 2458 1833 2459 static void gen_cast(CType *type) 1834 2460 { … … 1856 2482 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; 1857 2483 p = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM); 2484 #if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_387 2485 c &= dbt != VT_LDOUBLE; 2486 #endif 1858 2487 if (c) { 1859 2488 /* constant case: we can do it now */ … … 1866 2495 if (df) { 1867 2496 if ((sbt & VT_BTYPE) == VT_LLONG) { 1868 if ( sbt & VT_UNSIGNED)1869 vtop->c.ld = vtop->c. ull;2497 if ((sbt & VT_UNSIGNED) || !(vtop->c.i >> 63)) 2498 vtop->c.ld = vtop->c.i; 1870 2499 else 1871 vtop->c.ld = vtop->c.ll;2500 vtop->c.ld = -(long double)-vtop->c.i; 1872 2501 } else if(!sf) { 1873 if ( sbt & VT_UNSIGNED)1874 vtop->c.ld = vtop->c.ui;2502 if ((sbt & VT_UNSIGNED) || !(vtop->c.i >> 31)) 2503 vtop->c.ld = (uint32_t)vtop->c.i; 1875 2504 else 1876 vtop->c.ld = vtop->c.i;2505 vtop->c.ld = -(long double)-(uint32_t)vtop->c.i; 1877 2506 } 1878 2507 … … 1882 2511 vtop->c.d = (double)vtop->c.ld; 1883 2512 } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) { 1884 vtop->c. ull = (unsigned long long)vtop->c.ld;2513 vtop->c.i = vtop->c.ld; 1885 2514 } else if (sf && dbt == VT_BOOL) { 1886 2515 vtop->c.i = (vtop->c.ld != 0); 1887 2516 } else { 1888 2517 if(sf) 1889 vtop->c. ll = (long long)vtop->c.ld;2518 vtop->c.i = vtop->c.ld; 1890 2519 else if (sbt == (VT_LLONG|VT_UNSIGNED)) 1891 vtop->c.ll = vtop->c.ull;2520 ; 1892 2521 else if (sbt & VT_UNSIGNED) 1893 vtop->c. ll = vtop->c.ui;1894 #if def TCC_TARGET_X86_642522 vtop->c.i = (uint32_t)vtop->c.i; 2523 #if PTR_SIZE == 8 1895 2524 else if (sbt == VT_PTR) 1896 2525 ; 1897 2526 #endif 1898 2527 else if (sbt != VT_LLONG) 1899 vtop->c.ll = vtop->c.i; 2528 vtop->c.i = ((uint32_t)vtop->c.i | 2529 -(vtop->c.i & 0x80000000)); 1900 2530 1901 2531 if (dbt == (VT_LLONG|VT_UNSIGNED)) 1902 vtop->c.ull = vtop->c.ll;2532 ; 1903 2533 else if (dbt == VT_BOOL) 1904 vtop->c.i = (vtop->c.ll != 0); 2534 vtop->c.i = (vtop->c.i != 0); 2535 #if PTR_SIZE == 8 2536 else if (dbt == VT_PTR) 2537 ; 2538 #endif 1905 2539 else if (dbt != VT_LLONG) { 1906 int s = 0; 1907 if ((dbt & VT_BTYPE) == VT_BYTE) 1908 s = 24; 1909 else if ((dbt & VT_BTYPE) == VT_SHORT) 1910 s = 16; 1911 1912 if(dbt & VT_UNSIGNED) 1913 vtop->c.ui = ((unsigned int)vtop->c.ll << s) >> s; 1914 else 1915 vtop->c.i = ((int)vtop->c.ll << s) >> s; 2540 uint32_t m = ((dbt & VT_BTYPE) == VT_BYTE ? 0xff : 2541 (dbt & VT_BTYPE) == VT_SHORT ? 0xffff : 2542 0xffffffff); 2543 vtop->c.i &= m; 2544 if (!(dbt & VT_UNSIGNED)) 2545 vtop->c.i |= -(vtop->c.i & ((m >> 1) + 1)); 1916 2546 } 1917 2547 } … … 1919 2549 vtop->r = VT_CONST; 1920 2550 vtop->c.i = 1; 1921 } else if (!nocode_wanted){2551 } else { 1922 2552 /* non constant case: generate code */ 1923 2553 if (sf && df) { … … 1945 2575 } 1946 2576 } 1947 #if ndef TCC_TARGET_X86_642577 #if PTR_SIZE == 4 1948 2578 } else if ((dbt & VT_BTYPE) == VT_LLONG) { 1949 2579 if ((sbt & VT_BTYPE) != VT_LLONG) { … … 1959 2589 /* cast from pointer to int before we apply 1960 2590 shift operation, which pointers don't support*/ 1961 gen_cast (&int_type);2591 gen_cast_s(VT_INT); 1962 2592 } 1963 2593 gv_dup(); … … 1977 2607 (sbt & VT_BTYPE) != VT_FUNC) { 1978 2608 /* need to convert from 32bit to 64bit */ 1979 int r =gv(RC_INT);2609 gv(RC_INT); 1980 2610 if (sbt != (VT_INT | VT_UNSIGNED)) { 2611 #if defined(TCC_TARGET_ARM64) 2612 gen_cvt_sxtw(); 2613 #elif defined(TCC_TARGET_X86_64) 2614 int r = gv(RC_INT); 1981 2615 /* x86_64 specific: movslq */ 1982 2616 o(0x6348); 1983 2617 o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r)); 2618 #else 2619 #error 2620 #endif 1984 2621 } 1985 2622 } … … 1996 2633 } 1997 2634 force_charshort_cast(dbt); 2635 #if PTR_SIZE == 4 1998 2636 } else if ((dbt & VT_BTYPE) == VT_INT) { 1999 2637 /* scalar to int */ 2000 if ( sbt== VT_LLONG) {2638 if ((sbt & VT_BTYPE) == VT_LLONG) { 2001 2639 /* from long long: just take low order word */ 2002 2640 lexpand(); … … 2006 2644 the lvalue already contains the real type size (see 2007 2645 VT_LVAL_xxx constants) */ 2646 #endif 2008 2647 } 2009 2648 } … … 2044 2683 return PTR_SIZE; 2045 2684 } 2685 } else if (IS_ENUM(type->t) && type->ref->c == -1) { 2686 return -1; /* incomplete enum */ 2046 2687 } else if (bt == VT_LDOUBLE) { 2047 2688 *a = LDOUBLE_ALIGN; … … 2064 2705 #endif 2065 2706 return 8; 2066 } else if (bt == VT_INT || bt == VT_ ENUM || bt == VT_FLOAT) {2707 } else if (bt == VT_INT || bt == VT_FLOAT) { 2067 2708 *a = 4; 2068 2709 return 4; … … 2070 2711 *a = 2; 2071 2712 return 2; 2713 } else if (bt == VT_QLONG || bt == VT_QFLOAT) { 2714 *a = 8; 2715 return 16; 2072 2716 } else { 2073 2717 /* char, void, function, _Bool */ … … 2082 2726 { 2083 2727 if (type->t & VT_VLA) { 2728 type_size(&type->ref->type, a); 2084 2729 vset(&int_type, VT_LOCAL|VT_LVAL, type->ref->c); 2085 2730 } else { … … 2088 2733 } 2089 2734 2735 static void vla_sp_restore(void) { 2736 if (vlas_in_scope) { 2737 gen_vla_sp_restore(vla_sp_loc); 2738 } 2739 } 2740 2741 static void vla_sp_restore_root(void) { 2742 if (vlas_in_scope) { 2743 gen_vla_sp_restore(vla_sp_root_loc); 2744 } 2745 } 2746 2090 2747 /* return the pointed type of t */ 2091 2748 static inline CType *pointed_type(CType *type) … … 2099 2756 Sym *s; 2100 2757 s = sym_push(SYM_FIELD, type, 0, -1); 2101 type->t = VT_PTR | (type->t & ~VT_TYPE);2758 type->t = VT_PTR | (type->t & VT_STORAGE); 2102 2759 type->ref = s; 2103 2760 } … … 2113 2770 return 0; 2114 2771 /* check func_call */ 2115 if ( FUNC_CALL(s1->r) != FUNC_CALL(s2->r))2772 if (s1->f.func_call != s2->f.func_call) 2116 2773 return 0; 2117 2774 /* XXX: not complete */ 2118 if (s1-> c == FUNC_OLD || s2->c== FUNC_OLD)2775 if (s1->f.func_type == FUNC_OLD || s2->f.func_type == FUNC_OLD) 2119 2776 return 1; 2120 if (s1-> c != s2->c)2777 if (s1->f.func_type != s2->f.func_type) 2121 2778 return 0; 2122 2779 while (s1 != NULL) { 2123 2780 if (s2 == NULL) 2124 2781 return 0; 2125 if (!is_compatible_ parameter_types(&s1->type, &s2->type))2782 if (!is_compatible_unqualified_types(&s1->type, &s2->type)) 2126 2783 return 0; 2127 2784 s1 = s1->next; … … 2148 2805 t1 &= ~(VT_CONSTANT | VT_VOLATILE); 2149 2806 t2 &= ~(VT_CONSTANT | VT_VOLATILE); 2807 } 2808 2809 /* Default Vs explicit signedness only matters for char */ 2810 if ((t1 & VT_BTYPE) != VT_BYTE) { 2811 t1 &= ~VT_DEFSIGN; 2812 t2 &= ~VT_DEFSIGN; 2150 2813 } 2151 2814 /* XXX: bitfields ? */ … … 2177 2840 /* return true if type1 and type2 are the same (ignoring qualifiers). 2178 2841 */ 2179 static int is_compatible_ parameter_types(CType *type1, CType *type2)2842 static int is_compatible_unqualified_types(CType *type1, CType *type2) 2180 2843 { 2181 2844 return compare_types(type1,type2,1); … … 2194 2857 const char *tstr; 2195 2858 2196 t = type->t & VT_TYPE;2859 t = type->t; 2197 2860 bt = t & VT_BTYPE; 2198 2861 buf[0] = '\0'; 2862 2863 if (t & VT_EXTERN) 2864 pstrcat(buf, buf_size, "extern "); 2865 if (t & VT_STATIC) 2866 pstrcat(buf, buf_size, "static "); 2867 if (t & VT_TYPEDEF) 2868 pstrcat(buf, buf_size, "typedef "); 2869 if (t & VT_INLINE) 2870 pstrcat(buf, buf_size, "inline "); 2871 if (t & VT_VOLATILE) 2872 pstrcat(buf, buf_size, "volatile "); 2199 2873 if (t & VT_CONSTANT) 2200 2874 pstrcat(buf, buf_size, "const "); 2201 if (t & VT_VOLATILE) 2202 pstrcat(buf, buf_size, "volatile "); 2203 if (t & VT_UNSIGNED) 2204 pstrcat(buf, buf_size, "unsigned "); 2875 2876 if (((t & VT_DEFSIGN) && bt == VT_BYTE) 2877 || ((t & VT_UNSIGNED) 2878 && (bt == VT_SHORT || bt == VT_INT || bt == VT_LLONG) 2879 && !IS_ENUM(t) 2880 )) 2881 pstrcat(buf, buf_size, (t & VT_UNSIGNED) ? "unsigned " : "signed "); 2882 2883 buf_size -= strlen(buf); 2884 buf += strlen(buf); 2885 2205 2886 switch(bt) { 2206 2887 case VT_VOID: … … 2218 2899 case VT_INT: 2219 2900 tstr = "int"; 2220 goto add_tstr; 2221 case VT_LONG: 2222 tstr = "long"; 2223 goto add_tstr; 2901 goto maybe_long; 2224 2902 case VT_LLONG: 2225 2903 tstr = "long long"; 2226 goto add_tstr; 2904 maybe_long: 2905 if (t & VT_LONG) 2906 tstr = "long"; 2907 if (!IS_ENUM(t)) 2908 goto add_tstr; 2909 tstr = "enum "; 2910 goto tstruct; 2227 2911 case VT_FLOAT: 2228 2912 tstr = "float"; … … 2236 2920 pstrcat(buf, buf_size, tstr); 2237 2921 break; 2238 case VT_ENUM:2239 2922 case VT_STRUCT: 2240 if (bt == VT_STRUCT)2241 tstr = "struct ";2242 else2243 tstr = "enum ";2923 tstr = "struct "; 2924 if (IS_UNION(t)) 2925 tstr = "union "; 2926 tstruct: 2244 2927 pstrcat(buf, buf_size, tstr); 2245 2928 v = type->ref->v & ~SYM_STRUCT; … … 2265 2948 case VT_PTR: 2266 2949 s = type->ref; 2950 if (t & VT_ARRAY) { 2951 snprintf(buf1, sizeof(buf1), "%s[%d]", varstr ? varstr : "", s->c); 2952 type_to_str(buf, buf_size, &s->type, buf1); 2953 goto no_var; 2954 } 2267 2955 pstrcpy(buf1, sizeof(buf1), "*"); 2956 if (t & VT_CONSTANT) 2957 pstrcat(buf1, buf_size, "const "); 2958 if (t & VT_VOLATILE) 2959 pstrcat(buf1, buf_size, "volatile "); 2268 2960 if (varstr) 2269 2961 pstrcat(buf1, sizeof(buf1), varstr); … … 2282 2974 static void gen_assign_cast(CType *dt) 2283 2975 { 2284 CType *st, *type1, *type2 , tmp_type1, tmp_type2;2976 CType *st, *type1, *type2; 2285 2977 char buf1[256], buf2[256]; 2286 2978 int dbt, sbt; … … 2289 2981 dbt = dt->t & VT_BTYPE; 2290 2982 sbt = st->t & VT_BTYPE; 2291 if (sbt == VT_VOID) 2292 tcc_error("Cannot assign void value"); 2983 if (sbt == VT_VOID || dbt == VT_VOID) { 2984 if (sbt == VT_VOID && dbt == VT_VOID) 2985 ; /* 2986 It is Ok if both are void 2987 A test program: 2988 void func1() {} 2989 void func2() { 2990 return func1(); 2991 } 2992 gcc accepts this program 2993 */ 2994 else 2995 tcc_error("cannot cast from/to void"); 2996 } 2293 2997 if (dt->t & VT_CONSTANT) 2294 2998 tcc_warning("assignment of read-only location"); … … 2305 3009 } 2306 3010 type1 = pointed_type(dt); 2307 /* a function is implicit ely a function pointer */3011 /* a function is implicitly a function pointer */ 2308 3012 if (sbt == VT_FUNC) { 2309 3013 if ((type1->t & VT_BTYPE) != VT_VOID && … … 2319 3023 /* void * can match anything */ 2320 3024 } else { 2321 /* exact type match, except for unsigned */ 2322 tmp_type1 = *type1; 2323 tmp_type2 = *type2; 2324 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); 2325 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); 2326 if (!is_compatible_types(&tmp_type1, &tmp_type2)) 2327 tcc_warning("assignment from incompatible pointer type"); 3025 //printf("types %08x %08x\n", type1->t, type2->t); 3026 /* exact type match, except for qualifiers */ 3027 if (!is_compatible_unqualified_types(type1, type2)) { 3028 /* Like GCC don't warn by default for merely changes 3029 in pointer target signedness. Do warn for different 3030 base types, though, in particular for unsigned enums 3031 and signed int targets. */ 3032 if ((type1->t & (VT_BTYPE|VT_LONG)) != (type2->t & (VT_BTYPE|VT_LONG)) 3033 || IS_ENUM(type1->t) || IS_ENUM(type2->t) 3034 ) 3035 tcc_warning("assignment from incompatible pointer type"); 3036 } 2328 3037 } 2329 3038 /* check const and volatile */ … … 2338 3047 if (sbt == VT_PTR || sbt == VT_FUNC) { 2339 3048 tcc_warning("assignment makes integer from pointer without a cast"); 3049 } else if (sbt == VT_STRUCT) { 3050 goto case_VT_STRUCT; 2340 3051 } 2341 3052 /* XXX: more tests */ 2342 3053 break; 2343 3054 case VT_STRUCT: 2344 tmp_type1 = *dt; 2345 tmp_type2 = *st; 2346 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE); 2347 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE); 2348 if (!is_compatible_types(&tmp_type1, &tmp_type2)) { 3055 case_VT_STRUCT: 3056 if (!is_compatible_unqualified_types(dt, st)) { 2349 3057 error: 2350 3058 type_to_str(buf1, sizeof(buf1), st, NULL); … … 2371 3079 /* optimize char/short casts */ 2372 3080 delayed_cast = VT_MUSTCAST; 2373 vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));3081 vtop->type.t = ft & VT_TYPE; 2374 3082 /* XXX: factorize */ 2375 3083 if (ft & VT_CONSTANT) … … 2385 3093 /* structure assignment : generate memcpy */ 2386 3094 /* XXX: optimize if small size */ 2387 if (!nocode_wanted) {2388 3095 size = type_size(&vtop->type, &align); 2389 3096 … … 2401 3108 else 2402 3109 #endif 2403 vpush_global_sym(&func_old_type, TOK_memcpy); 3110 /* Use memmove, rather than memcpy, as dest and src may be same: */ 3111 vpush_global_sym(&func_old_type, TOK_memmove); 2404 3112 2405 3113 vswap(); … … 2411 3119 vpushi(size); 2412 3120 gfunc_call(3); 2413 } else { 2414 vswap(); 2415 vpop(); 2416 } 3121 2417 3122 /* leave source on stack */ 2418 3123 } else if (ft & VT_BITFIELD) { 2419 3124 /* bitfield store handling */ 2420 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f; 2421 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f; 3125 3126 /* save lvalue as expression result (example: s.b = s.a = n;) */ 3127 vdup(), vtop[-1] = vtop[-2]; 3128 3129 bit_pos = BIT_POS(ft); 3130 bit_size = BIT_SIZE(ft); 2422 3131 /* remove bit field info to avoid loops */ 2423 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)); 2424 2425 /* duplicate source into other register */ 2426 gv_dup(); 2427 vswap(); 2428 vrott(3); 2429 2430 if((ft & VT_BTYPE) == VT_BOOL) { 3132 vtop[-1].type.t = ft & ~VT_STRUCT_MASK; 3133 3134 if ((ft & VT_BTYPE) == VT_BOOL) { 2431 3135 gen_cast(&vtop[-1].type); 2432 3136 vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED); 2433 3137 } 2434 3138 2435 /* duplicate destination */ 2436 vdup(); 2437 vtop[-1] = vtop[-2]; 2438 2439 /* mask and shift source */ 2440 if((ft & VT_BTYPE) != VT_BOOL) { 2441 if((ft & VT_BTYPE) == VT_LLONG) { 2442 vpushll((1ULL << bit_size) - 1ULL); 2443 } else { 2444 vpushi((1 << bit_size) - 1); 2445 } 3139 r = adjust_bf(vtop - 1, bit_pos, bit_size); 3140 if (r == VT_STRUCT) { 3141 gen_cast_s((ft & VT_BTYPE) == VT_LLONG ? VT_LLONG : VT_INT); 3142 store_packed_bf(bit_pos, bit_size); 3143 } else { 3144 unsigned long long mask = (1ULL << bit_size) - 1; 3145 if ((ft & VT_BTYPE) != VT_BOOL) { 3146 /* mask source */ 3147 if ((vtop[-1].type.t & VT_BTYPE) == VT_LLONG) 3148 vpushll(mask); 3149 else 3150 vpushi((unsigned)mask); 3151 gen_op('&'); 3152 } 3153 /* shift source */ 3154 vpushi(bit_pos); 3155 gen_op(TOK_SHL); 3156 vswap(); 3157 /* duplicate destination */ 3158 vdup(); 3159 vrott(3); 3160 /* load destination, mask and or with source */ 3161 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) 3162 vpushll(~(mask << bit_pos)); 3163 else 3164 vpushi(~((unsigned)mask << bit_pos)); 2446 3165 gen_op('&'); 2447 } 2448 vpushi(bit_pos); 2449 gen_op(TOK_SHL); 2450 /* load destination, mask and or with source */ 2451 vswap(); 2452 if((ft & VT_BTYPE) == VT_LLONG) { 2453 vpushll(~(((1ULL << bit_size) - 1ULL) << bit_pos)); 2454 } else { 2455 vpushi(~(((1 << bit_size) - 1) << bit_pos)); 2456 } 2457 gen_op('&'); 2458 gen_op('|'); 2459 /* store result */ 2460 vstore(); 2461 2462 /* pop off shifted source from "duplicate source..." above */ 2463 vpop(); 2464 3166 gen_op('|'); 3167 /* store result */ 3168 vstore(); 3169 /* ... and discard */ 3170 vpop(); 3171 } 3172 } else if (dbt == VT_VOID) { 3173 --vtop; 2465 3174 } else { 2466 3175 #ifdef CONFIG_TCC_BCHECK 2467 /* bound check case */ 2468 if (vtop[-1].r & VT_MUSTBOUND) { 2469 vswap(); 2470 gbound(); 2471 vswap(); 2472 } 2473 #endif 2474 if (!nocode_wanted) { 3176 /* bound check case */ 3177 if (vtop[-1].r & VT_MUSTBOUND) { 3178 vswap(); 3179 gbound(); 3180 vswap(); 3181 } 3182 #endif 2475 3183 rc = RC_INT; 2476 3184 if (is_float(ft)) { … … 2479 3187 if ((ft & VT_BTYPE) == VT_LDOUBLE) { 2480 3188 rc = RC_ST0; 3189 } else if ((ft & VT_BTYPE) == VT_QFLOAT) { 3190 rc = RC_FRET; 2481 3191 } 2482 3192 #endif … … 2487 3197 SValue sv; 2488 3198 t = get_reg(RC_INT); 2489 #if def TCC_TARGET_X86_643199 #if PTR_SIZE == 8 2490 3200 sv.type.t = VT_PTR; 2491 3201 #else … … 2493 3203 #endif 2494 3204 sv.r = VT_LOCAL | VT_LVAL; 2495 sv.c. ul = vtop[-1].c.ul;3205 sv.c.i = vtop[-1].c.i; 2496 3206 load(t, &sv); 2497 3207 vtop[-1].r = t | VT_LVAL; 2498 3208 } 2499 store(r, vtop - 1); 2500 #ifndef TCC_TARGET_X86_64 2501 /* two word case handling : store second register at word + 4 */ 3209 /* two word case handling : store second register at word + 4 (or +8 for x86-64) */ 3210 #if PTR_SIZE == 8 3211 if (((ft & VT_BTYPE) == VT_QLONG) || ((ft & VT_BTYPE) == VT_QFLOAT)) { 3212 int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE; 3213 #else 2502 3214 if ((ft & VT_BTYPE) == VT_LLONG) { 3215 int addr_type = VT_INT, load_size = 4, load_type = VT_INT; 3216 #endif 3217 vtop[-1].type.t = load_type; 3218 store(r, vtop - 1); 2503 3219 vswap(); 2504 3220 /* convert to int to increment easily */ 2505 vtop->type.t = VT_INT;3221 vtop->type.t = addr_type; 2506 3222 gaddrof(); 2507 vpushi( 4);3223 vpushi(load_size); 2508 3224 gen_op('+'); 2509 3225 vtop->r |= VT_LVAL; 2510 3226 vswap(); 3227 vtop[-1].type.t = load_type; 2511 3228 /* XXX: it works because r2 is spilled last ! */ 2512 3229 store(vtop->r2, vtop - 1); 2513 } 2514 #endif 2515 } 3230 } else { 3231 store(r, vtop - 1); 3232 } 3233 2516 3234 vswap(); 2517 3235 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */ … … 2538 3256 } 2539 3257 2540 /* Parse GNUC __attribute__ extension. Currently, the following 2541 extensions are recognized: 2542 - aligned(n) : set data/function alignment. 2543 - packed : force data alignment to 1 2544 - section(x) : generate data/code in this section. 2545 - unused : currently ignored, but may be used someday. 2546 - regparm(n) : pass function parameters in registers (i386 only) 2547 */ 3258 ST_FUNC void parse_mult_str (CString *astr, const char *msg) 3259 { 3260 /* read the string */ 3261 if (tok != TOK_STR) 3262 expect(msg); 3263 cstr_new(astr); 3264 while (tok == TOK_STR) { 3265 /* XXX: add \0 handling too ? */ 3266 cstr_cat(astr, tokc.str.data, -1); 3267 next(); 3268 } 3269 cstr_ccat(astr, '\0'); 3270 } 3271 3272 /* If I is >= 1 and a power of two, returns log2(i)+1. 3273 If I is 0 returns 0. */ 3274 static int exact_log2p1(int i) 3275 { 3276 int ret; 3277 if (!i) 3278 return 0; 3279 for (ret = 1; i >= 1 << 8; ret += 8) 3280 i >>= 8; 3281 if (i >= 1 << 4) 3282 ret += 4, i >>= 4; 3283 if (i >= 1 << 2) 3284 ret += 2, i >>= 2; 3285 if (i >= 1 << 1) 3286 ret++; 3287 return ret; 3288 } 3289 3290 /* Parse __attribute__((...)) GNUC extension. */ 2548 3291 static void parse_attribute(AttributeDef *ad) 2549 3292 { 2550 3293 int t, n; 3294 CString astr; 2551 3295 2552 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) { 3296 redo: 3297 if (tok != TOK_ATTRIBUTE1 && tok != TOK_ATTRIBUTE2) 3298 return; 2553 3299 next(); 2554 3300 skip('('); … … 2563 3309 case TOK_SECTION2: 2564 3310 skip('('); 2565 if (tok != TOK_STR) 2566 expect("section name"); 2567 ad->section = find_section(tcc_state, (char *)tokc.cstr->data); 2568 next(); 3311 parse_mult_str(&astr, "section name"); 3312 ad->section = find_section(tcc_state, (char *)astr.data); 2569 3313 skip(')'); 3314 cstr_free(&astr); 2570 3315 break; 2571 3316 case TOK_ALIAS1: 2572 3317 case TOK_ALIAS2: 2573 3318 skip('('); 2574 if (tok != TOK_STR) 2575 expect("alias(\"target\")"); 3319 parse_mult_str(&astr, "alias(\"target\")"); 2576 3320 ad->alias_target = /* save string as token, for later */ 2577 tok_alloc((char*)tokc.cstr->data, tokc.cstr->size-1)->tok; 2578 next(); 3321 tok_alloc((char*)astr.data, astr.size-1)->tok; 2579 3322 skip(')'); 3323 cstr_free(&astr); 3324 break; 3325 case TOK_VISIBILITY1: 3326 case TOK_VISIBILITY2: 3327 skip('('); 3328 parse_mult_str(&astr, 3329 "visibility(\"default|hidden|internal|protected\")"); 3330 if (!strcmp (astr.data, "default")) 3331 ad->a.visibility = STV_DEFAULT; 3332 else if (!strcmp (astr.data, "hidden")) 3333 ad->a.visibility = STV_HIDDEN; 3334 else if (!strcmp (astr.data, "internal")) 3335 ad->a.visibility = STV_INTERNAL; 3336 else if (!strcmp (astr.data, "protected")) 3337 ad->a.visibility = STV_PROTECTED; 3338 else 3339 expect("visibility(\"default|hidden|internal|protected\")"); 3340 skip(')'); 3341 cstr_free(&astr); 2580 3342 break; 2581 3343 case TOK_ALIGNED1: … … 2590 3352 n = MAX_ALIGN; 2591 3353 } 2592 ad->aligned = n; 3354 ad->a.aligned = exact_log2p1(n); 3355 if (n != 1 << (ad->a.aligned - 1)) 3356 tcc_error("alignment of %d is larger than implemented", n); 2593 3357 break; 2594 3358 case TOK_PACKED1: 2595 3359 case TOK_PACKED2: 2596 ad-> packed = 1;3360 ad->a.packed = 1; 2597 3361 break; 2598 3362 case TOK_WEAK1: 2599 3363 case TOK_WEAK2: 2600 ad-> weak = 1;3364 ad->a.weak = 1; 2601 3365 break; 2602 3366 case TOK_UNUSED1: … … 2613 3377 case TOK_CDECL2: 2614 3378 case TOK_CDECL3: 2615 ad->f unc_call = FUNC_CDECL;3379 ad->f.func_call = FUNC_CDECL; 2616 3380 break; 2617 3381 case TOK_STDCALL1: 2618 3382 case TOK_STDCALL2: 2619 3383 case TOK_STDCALL3: 2620 ad->f unc_call = FUNC_STDCALL;3384 ad->f.func_call = FUNC_STDCALL; 2621 3385 break; 2622 3386 #ifdef TCC_TARGET_I386 … … 2630 3394 n = 0; 2631 3395 if (n > 0) 2632 ad->f unc_call = FUNC_FASTCALL1 + n - 1;3396 ad->f.func_call = FUNC_FASTCALL1 + n - 1; 2633 3397 skip(')'); 2634 3398 break; … … 2636 3400 case TOK_FASTCALL2: 2637 3401 case TOK_FASTCALL3: 2638 ad->f unc_call = FUNC_FASTCALLW;3402 ad->f.func_call = FUNC_FASTCALLW; 2639 3403 break; 2640 3404 #endif … … 2643 3407 switch(tok) { 2644 3408 case TOK_MODE_DI: 2645 ad->mode = VT_LLONG + 1; 3409 ad->attr_mode = VT_LLONG + 1; 3410 break; 3411 case TOK_MODE_QI: 3412 ad->attr_mode = VT_BYTE + 1; 2646 3413 break; 2647 3414 case TOK_MODE_HI: 2648 ad-> mode = VT_SHORT + 1;3415 ad->attr_mode = VT_SHORT + 1; 2649 3416 break; 2650 3417 case TOK_MODE_SI: 2651 ad->mode = VT_INT + 1; 3418 case TOK_MODE_word: 3419 ad->attr_mode = VT_INT + 1; 2652 3420 break; 2653 3421 default: … … 2659 3427 break; 2660 3428 case TOK_DLLEXPORT: 2661 ad-> func_export = 1;3429 ad->a.dllexport = 1; 2662 3430 break; 2663 3431 case TOK_DLLIMPORT: 2664 ad-> func_import = 1;3432 ad->a.dllimport = 1; 2665 3433 break; 2666 3434 default: … … 2686 3454 skip(')'); 2687 3455 skip(')'); 2688 } 2689 } 2690 2691 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */ 3456 goto redo; 3457 } 3458 3459 static Sym * find_field (CType *type, int v) 3460 { 3461 Sym *s = type->ref; 3462 v |= SYM_FIELD; 3463 while ((s = s->next) != NULL) { 3464 if ((s->v & SYM_FIELD) && 3465 (s->type.t & VT_BTYPE) == VT_STRUCT && 3466 (s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) { 3467 Sym *ret = find_field (&s->type, v); 3468 if (ret) 3469 return ret; 3470 } 3471 if (s->v == v) 3472 break; 3473 } 3474 return s; 3475 } 3476 3477 static void struct_add_offset (Sym *s, int offset) 3478 { 3479 while ((s = s->next) != NULL) { 3480 if ((s->v & SYM_FIELD) && 3481 (s->type.t & VT_BTYPE) == VT_STRUCT && 3482 (s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) { 3483 struct_add_offset(s->type.ref, offset); 3484 } else 3485 s->c += offset; 3486 } 3487 } 3488 3489 static void struct_layout(CType *type, AttributeDef *ad) 3490 { 3491 int size, align, maxalign, offset, c, bit_pos, bit_size; 3492 int packed, a, bt, prevbt, prev_bit_size; 3493 int pcc = !tcc_state->ms_bitfields; 3494 int pragma_pack = *tcc_state->pack_stack_ptr; 3495 Sym *f; 3496 3497 maxalign = 1; 3498 offset = 0; 3499 c = 0; 3500 bit_pos = 0; 3501 prevbt = VT_STRUCT; /* make it never match */ 3502 prev_bit_size = 0; 3503 3504 //#define BF_DEBUG 3505 3506 for (f = type->ref->next; f; f = f->next) { 3507 if (f->type.t & VT_BITFIELD) 3508 bit_size = BIT_SIZE(f->type.t); 3509 else 3510 bit_size = -1; 3511 size = type_size(&f->type, &align); 3512 a = f->a.aligned ? 1 << (f->a.aligned - 1) : 0; 3513 packed = 0; 3514 3515 if (pcc && bit_size == 0) { 3516 /* in pcc mode, packing does not affect zero-width bitfields */ 3517 3518 } else { 3519 /* in pcc mode, attribute packed overrides if set. */ 3520 if (pcc && (f->a.packed || ad->a.packed)) 3521 align = packed = 1; 3522 3523 /* pragma pack overrides align if lesser and packs bitfields always */ 3524 if (pragma_pack) { 3525 packed = 1; 3526 if (pragma_pack < align) 3527 align = pragma_pack; 3528 /* in pcc mode pragma pack also overrides individual align */ 3529 if (pcc && pragma_pack < a) 3530 a = 0; 3531 } 3532 } 3533 /* some individual align was specified */ 3534 if (a) 3535 align = a; 3536 3537 if (type->ref->type.t == VT_UNION) { 3538 if (pcc && bit_size >= 0) 3539 size = (bit_size + 7) >> 3; 3540 offset = 0; 3541 if (size > c) 3542 c = size; 3543 3544 } else if (bit_size < 0) { 3545 if (pcc) 3546 c += (bit_pos + 7) >> 3; 3547 c = (c + align - 1) & -align; 3548 offset = c; 3549 if (size > 0) 3550 c += size; 3551 bit_pos = 0; 3552 prevbt = VT_STRUCT; 3553 prev_bit_size = 0; 3554 3555 } else { 3556 /* A bit-field. Layout is more complicated. There are two 3557 options: PCC (GCC) compatible and MS compatible */ 3558 if (pcc) { 3559 /* In PCC layout a bit-field is placed adjacent to the 3560 preceding bit-fields, except if: 3561 - it has zero-width 3562 - an individual alignment was given 3563 - it would overflow its base type container and 3564 there is no packing */ 3565 if (bit_size == 0) { 3566 new_field: 3567 c = (c + ((bit_pos + 7) >> 3) + align - 1) & -align; 3568 bit_pos = 0; 3569 } else if (f->a.aligned) { 3570 goto new_field; 3571 } else if (!packed) { 3572 int a8 = align * 8; 3573 int ofs = ((c * 8 + bit_pos) % a8 + bit_size + a8 - 1) / a8; 3574 if (ofs > size / align) 3575 goto new_field; 3576 } 3577 3578 /* in pcc mode, long long bitfields have type int if they fit */ 3579 if (size == 8 && bit_size <= 32) 3580 f->type.t = (f->type.t & ~VT_BTYPE) | VT_INT, size = 4; 3581 3582 while (bit_pos >= align * 8) 3583 c += align, bit_pos -= align * 8; 3584 offset = c; 3585 3586 /* In PCC layout named bit-fields influence the alignment 3587 of the containing struct using the base types alignment, 3588 except for packed fields (which here have correct align). */ 3589 if (f->v & SYM_FIRST_ANOM 3590 // && bit_size // ??? gcc on ARM/rpi does that 3591 ) 3592 align = 1; 3593 3594 } else { 3595 bt = f->type.t & VT_BTYPE; 3596 if ((bit_pos + bit_size > size * 8) 3597 || (bit_size > 0) == (bt != prevbt) 3598 ) { 3599 c = (c + align - 1) & -align; 3600 offset = c; 3601 bit_pos = 0; 3602 /* In MS bitfield mode a bit-field run always uses 3603 at least as many bits as the underlying type. 3604 To start a new run it's also required that this 3605 or the last bit-field had non-zero width. */ 3606 if (bit_size || prev_bit_size) 3607 c += size; 3608 } 3609 /* In MS layout the records alignment is normally 3610 influenced by the field, except for a zero-width 3611 field at the start of a run (but by further zero-width 3612 fields it is again). */ 3613 if (bit_size == 0 && prevbt != bt) 3614 align = 1; 3615 prevbt = bt; 3616 prev_bit_size = bit_size; 3617 } 3618 3619 f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT)) 3620 | (bit_pos << VT_STRUCT_SHIFT); 3621 bit_pos += bit_size; 3622 } 3623 if (align > maxalign) 3624 maxalign = align; 3625 3626 #ifdef BF_DEBUG 3627 printf("set field %s offset %-2d size %-2d align %-2d", 3628 get_tok_str(f->v & ~SYM_FIELD, NULL), offset, size, align); 3629 if (f->type.t & VT_BITFIELD) { 3630 printf(" pos %-2d bits %-2d", 3631 BIT_POS(f->type.t), 3632 BIT_SIZE(f->type.t) 3633 ); 3634 } 3635 printf("\n"); 3636 #endif 3637 3638 if (f->v & SYM_FIRST_ANOM && (f->type.t & VT_BTYPE) == VT_STRUCT) { 3639 Sym *ass; 3640 /* An anonymous struct/union. Adjust member offsets 3641 to reflect the real offset of our containing struct. 3642 Also set the offset of this anon member inside 3643 the outer struct to be zero. Via this it 3644 works when accessing the field offset directly 3645 (from base object), as well as when recursing 3646 members in initializer handling. */ 3647 int v2 = f->type.ref->v; 3648 if (!(v2 & SYM_FIELD) && 3649 (v2 & ~SYM_STRUCT) < SYM_FIRST_ANOM) { 3650 Sym **pps; 3651 /* This happens only with MS extensions. The 3652 anon member has a named struct type, so it 3653 potentially is shared with other references. 3654 We need to unshare members so we can modify 3655 them. */ 3656 ass = f->type.ref; 3657 f->type.ref = sym_push(anon_sym++ | SYM_FIELD, 3658 &f->type.ref->type, 0, 3659 f->type.ref->c); 3660 pps = &f->type.ref->next; 3661 while ((ass = ass->next) != NULL) { 3662 *pps = sym_push(ass->v, &ass->type, 0, ass->c); 3663 pps = &((*pps)->next); 3664 } 3665 *pps = NULL; 3666 } 3667 struct_add_offset(f->type.ref, offset); 3668 f->c = 0; 3669 } else { 3670 f->c = offset; 3671 } 3672 3673 f->r = 0; 3674 } 3675 3676 if (pcc) 3677 c += (bit_pos + 7) >> 3; 3678 3679 /* store size and alignment */ 3680 a = bt = ad->a.aligned ? 1 << (ad->a.aligned - 1) : 1; 3681 if (a < maxalign) 3682 a = maxalign; 3683 type->ref->r = a; 3684 if (pragma_pack && pragma_pack < maxalign && 0 == pcc) { 3685 /* can happen if individual align for some member was given. In 3686 this case MSVC ignores maxalign when aligning the size */ 3687 a = pragma_pack; 3688 if (a < bt) 3689 a = bt; 3690 } 3691 c = (c + a - 1) & -a; 3692 type->ref->c = c; 3693 3694 #ifdef BF_DEBUG 3695 printf("struct size %-2d align %-2d\n\n", c, a), fflush(stdout); 3696 #endif 3697 3698 /* check whether we can access bitfields by their type */ 3699 for (f = type->ref->next; f; f = f->next) { 3700 int s, px, cx, c0; 3701 CType t; 3702 3703 if (0 == (f->type.t & VT_BITFIELD)) 3704 continue; 3705 f->type.ref = f; 3706 f->auxtype = -1; 3707 bit_size = BIT_SIZE(f->type.t); 3708 if (bit_size == 0) 3709 continue; 3710 bit_pos = BIT_POS(f->type.t); 3711 size = type_size(&f->type, &align); 3712 if (bit_pos + bit_size <= size * 8 && f->c + size <= c) 3713 continue; 3714 3715 /* try to access the field using a different type */ 3716 c0 = -1, s = align = 1; 3717 for (;;) { 3718 px = f->c * 8 + bit_pos; 3719 cx = (px >> 3) & -align; 3720 px = px - (cx << 3); 3721 if (c0 == cx) 3722 break; 3723 s = (px + bit_size + 7) >> 3; 3724 if (s > 4) { 3725 t.t = VT_LLONG; 3726 } else if (s > 2) { 3727 t.t = VT_INT; 3728 } else if (s > 1) { 3729 t.t = VT_SHORT; 3730 } else { 3731 t.t = VT_BYTE; 3732 } 3733 s = type_size(&t, &align); 3734 c0 = cx; 3735 } 3736 3737 if (px + bit_size <= s * 8 && cx + s <= c) { 3738 /* update offset and bit position */ 3739 f->c = cx; 3740 bit_pos = px; 3741 f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT)) 3742 | (bit_pos << VT_STRUCT_SHIFT); 3743 if (s != size) 3744 f->auxtype = t.t; 3745 #ifdef BF_DEBUG 3746 printf("FIX field %s offset %-2d size %-2d align %-2d " 3747 "pos %-2d bits %-2d\n", 3748 get_tok_str(f->v & ~SYM_FIELD, NULL), 3749 cx, s, align, px, bit_size); 3750 #endif 3751 } else { 3752 /* fall back to load/store single-byte wise */ 3753 f->auxtype = VT_STRUCT; 3754 #ifdef BF_DEBUG 3755 printf("FIX field %s : load byte-wise\n", 3756 get_tok_str(f->v & ~SYM_FIELD, NULL)); 3757 #endif 3758 } 3759 } 3760 } 3761 3762 /* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */ 2692 3763 static void struct_decl(CType *type, int u) 2693 3764 { 2694 int a, v, size, align, maxalign, c, offset;2695 int bit_size, b it_pos, bsize, bt, lbit_pos, prevbt;2696 Sym *s, *ss, * ass, **ps;2697 AttributeDef ad ;3765 int v, c, size, align, flexible; 3766 int bit_size, bsize, bt; 3767 Sym *s, *ss, **ps; 3768 AttributeDef ad, ad1; 2698 3769 CType type1, btype; 2699 3770 2700 a = tok; /* save decl type */3771 memset(&ad, 0, sizeof ad); 2701 3772 next(); 3773 parse_attribute(&ad); 2702 3774 if (tok != '{') { 2703 3775 v = tok; … … 2707 3779 expect("struct/union/enum name"); 2708 3780 s = struct_find(v); 2709 if (s) { 2710 if (s->type.t != a) 2711 tcc_error("invalid type"); 2712 goto do_decl; 3781 if (s && (s->sym_scope == local_scope || tok != '{')) { 3782 if (u == s->type.t) 3783 goto do_decl; 3784 if (u == VT_ENUM && IS_ENUM(s->type.t)) 3785 goto do_decl; 3786 tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); 2713 3787 } 2714 3788 } else { 2715 3789 v = anon_sym++; 2716 3790 } 2717 type1.t = a; 3791 /* Record the original enum/struct/union token. */ 3792 type1.t = u == VT_ENUM ? u | VT_INT | VT_UNSIGNED : u; 3793 type1.ref = NULL; 2718 3794 /* we put an undefined size for struct/union */ 2719 3795 s = sym_push(v | SYM_STRUCT, &type1, 0, -1); 2720 3796 s->r = 0; /* default alignment is zero as gcc */ 2721 /* put struct/union/enum name in type */ 2722 do_decl: 2723 type->t = u; 3797 do_decl: 3798 type->t = s->type.t; 2724 3799 type->ref = s; 2725 3800 2726 3801 if (tok == '{') { 2727 3802 next(); … … 2729 3804 tcc_error("struct/union/enum already defined"); 2730 3805 /* cannot be empty */ 2731 c = 0;2732 3806 /* non empty enums are not allowed */ 2733 if (a == TOK_ENUM) { 3807 ps = &s->next; 3808 if (u == VT_ENUM) { 3809 long long ll = 0, pl = 0, nl = 0; 3810 CType t; 3811 t.ref = s; 3812 /* enum symbols have static storage */ 3813 t.t = VT_INT|VT_STATIC|VT_ENUM_VAL; 2734 3814 for(;;) { 2735 3815 v = tok; 2736 3816 if (v < TOK_UIDENT) 2737 3817 expect("identifier"); 3818 ss = sym_find(v); 3819 if (ss && !local_stack) 3820 tcc_error("redefinition of enumerator '%s'", 3821 get_tok_str(v, NULL)); 2738 3822 next(); 2739 3823 if (tok == '=') { 2740 3824 next(); 2741 c = expr_const();3825 ll = expr_const64(); 2742 3826 } 2743 /* enum symbols have static storage */ 2744 ss = sym_push(v, &int_type, VT_CONST, c); 2745 ss->type.t |= VT_STATIC; 3827 ss = sym_push(v, &t, VT_CONST, 0); 3828 ss->enum_val = ll; 3829 *ps = ss, ps = &ss->next; 3830 if (ll < nl) 3831 nl = ll; 3832 if (ll > pl) 3833 pl = ll; 2746 3834 if (tok != ',') 2747 3835 break; 2748 3836 next(); 2749 c++;3837 ll++; 2750 3838 /* NOTE: we accept a trailing comma */ 2751 3839 if (tok == '}') … … 2753 3841 } 2754 3842 skip('}'); 3843 /* set integral type of the enum */ 3844 t.t = VT_INT; 3845 if (nl >= 0) { 3846 if (pl != (unsigned)pl) 3847 t.t = (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG); 3848 t.t |= VT_UNSIGNED; 3849 } else if (pl != (int)pl || nl != (int)nl) 3850 t.t = (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG); 3851 s->type.t = type->t = t.t | VT_ENUM; 3852 s->c = 0; 3853 /* set type for enum members */ 3854 for (ss = s->next; ss; ss = ss->next) { 3855 ll = ss->enum_val; 3856 if (ll == (int)ll) /* default is int if it fits */ 3857 continue; 3858 if (t.t & VT_UNSIGNED) { 3859 ss->type.t |= VT_UNSIGNED; 3860 if (ll == (unsigned)ll) 3861 continue; 3862 } 3863 ss->type.t = (ss->type.t & ~VT_BTYPE) 3864 | (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG); 3865 } 2755 3866 } else { 2756 maxalign = 1; 2757 ps = &s->next; 2758 prevbt = VT_INT; 2759 bit_pos = 0; 2760 offset = 0; 3867 c = 0; 3868 flexible = 0; 2761 3869 while (tok != '}') { 2762 parse_btype(&btype, &ad); 3870 if (!parse_btype(&btype, &ad1)) { 3871 skip(';'); 3872 continue; 3873 } 2763 3874 while (1) { 3875 if (flexible) 3876 tcc_error("flexible array member '%s' not at the end of struct", 3877 get_tok_str(v, NULL)); 2764 3878 bit_size = -1; 2765 3879 v = 0; 2766 3880 type1 = btype; 2767 3881 if (tok != ':') { 2768 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT); 2769 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT) 2770 expect("identifier"); 3882 if (tok != ';') 3883 type_decl(&type1, &ad1, &v, TYPE_DIRECT); 3884 if (v == 0) { 3885 if ((type1.t & VT_BTYPE) != VT_STRUCT) 3886 expect("identifier"); 3887 else { 3888 int v = btype.ref->v; 3889 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) { 3890 if (tcc_state->ms_extensions == 0) 3891 expect("identifier"); 3892 } 3893 } 3894 } 3895 if (type_size(&type1, &align) < 0) { 3896 if ((u == VT_STRUCT) && (type1.t & VT_ARRAY) && c) 3897 flexible = 1; 3898 else 3899 tcc_error("field '%s' has incomplete type", 3900 get_tok_str(v, NULL)); 3901 } 2771 3902 if ((type1.t & VT_BTYPE) == VT_FUNC || 2772 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))3903 (type1.t & VT_STORAGE)) 2773 3904 tcc_error("invalid type for '%s'", 2774 3905 get_tok_str(v, NULL)); … … 2784 3915 tcc_error("zero width for bit-field '%s'", 2785 3916 get_tok_str(v, NULL)); 3917 parse_attribute(&ad1); 2786 3918 } 2787 3919 size = type_size(&type1, &align); 2788 if (ad.aligned) {2789 if (align < ad.aligned)2790 align = ad.aligned;2791 } else if (ad.packed) {2792 align = 1;2793 } else if (*tcc_state->pack_stack_ptr) {2794 if (align > *tcc_state->pack_stack_ptr)2795 align = *tcc_state->pack_stack_ptr;2796 }2797 lbit_pos = 0;2798 3920 if (bit_size >= 0) { 2799 3921 bt = type1.t & VT_BTYPE; … … 2802 3924 bt != VT_SHORT && 2803 3925 bt != VT_BOOL && 2804 bt != VT_ENUM &&2805 3926 bt != VT_LLONG) 2806 3927 tcc_error("bitfields must have scalar type"); … … 2809 3930 tcc_error("width of '%s' exceeds its type", 2810 3931 get_tok_str(v, NULL)); 2811 } else if (bit_size == bsize) { 3932 } else if (bit_size == bsize 3933 && !ad.a.packed && !ad1.a.packed) { 2812 3934 /* no need for bit fields */ 2813 bit_pos = 0; 2814 } else if (bit_size == 0) { 2815 /* XXX: what to do if only padding in a 2816 structure ? */ 2817 /* zero size: means to pad */ 2818 bit_pos = 0; 3935 ; 3936 } else if (bit_size == 64) { 3937 tcc_error("field width 64 not implemented"); 2819 3938 } else { 2820 /* we do not have enough room ? 2821 did the type change? 2822 is it a union? */ 2823 if ((bit_pos + bit_size) > bsize || 2824 bt != prevbt || a == TOK_UNION) 2825 bit_pos = 0; 2826 lbit_pos = bit_pos; 2827 /* XXX: handle LSB first */ 2828 type1.t |= VT_BITFIELD | 2829 (bit_pos << VT_STRUCT_SHIFT) | 2830 (bit_size << (VT_STRUCT_SHIFT + 6)); 2831 bit_pos += bit_size; 3939 type1.t = (type1.t & ~VT_STRUCT_MASK) 3940 | VT_BITFIELD 3941 | (bit_size << (VT_STRUCT_SHIFT + 6)); 2832 3942 } 2833 prevbt = bt;2834 } else {2835 bit_pos = 0;2836 3943 } 2837 3944 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) { 2838 /* add new memory data only if starting 2839 bit field */ 2840 if (lbit_pos == 0) { 2841 if (a == TOK_STRUCT) { 2842 c = (c + align - 1) & -align; 2843 offset = c; 2844 if (size > 0) 2845 c += size; 2846 } else { 2847 offset = 0; 2848 if (size > c) 2849 c = size; 2850 } 2851 if (align > maxalign) 2852 maxalign = align; 2853 } 2854 #if 0 2855 printf("add field %s offset=%d", 2856 get_tok_str(v, NULL), offset); 2857 if (type1.t & VT_BITFIELD) { 2858 printf(" pos=%d size=%d", 2859 (type1.t >> VT_STRUCT_SHIFT) & 0x3f, 2860 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f); 2861 } 2862 printf("\n"); 2863 #endif 3945 /* Remember we've seen a real field to check 3946 for placement of flexible array member. */ 3947 c = 1; 2864 3948 } 2865 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) { 2866 ass = type1.ref; 2867 while ((ass = ass->next) != NULL) { 2868 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c); 2869 *ps = ss; 2870 ps = &ss->next; 2871 } 2872 } else if (v) { 2873 ss = sym_push(v | SYM_FIELD, &type1, 0, offset); 3949 /* If member is a struct or bit-field, enforce 3950 placing into the struct (as anonymous). */ 3951 if (v == 0 && 3952 ((type1.t & VT_BTYPE) == VT_STRUCT || 3953 bit_size >= 0)) { 3954 v = anon_sym++; 3955 } 3956 if (v) { 3957 ss = sym_push(v | SYM_FIELD, &type1, 0, 0); 3958 ss->a = ad1.a; 2874 3959 *ps = ss; 2875 3960 ps = &ss->next; … … 2882 3967 } 2883 3968 skip('}'); 2884 /* store size and alignment */ 2885 s->c = (c + maxalign - 1) & -maxalign; 2886 s->r = maxalign; 2887 } 2888 } 3969 parse_attribute(&ad); 3970 struct_layout(type, &ad); 3971 } 3972 } 3973 } 3974 3975 static void sym_to_attr(AttributeDef *ad, Sym *s) 3976 { 3977 if (s->a.aligned && 0 == ad->a.aligned) 3978 ad->a.aligned = s->a.aligned; 3979 if (s->f.func_call && 0 == ad->f.func_call) 3980 ad->f.func_call = s->f.func_call; 3981 if (s->f.func_type && 0 == ad->f.func_type) 3982 ad->f.func_type = s->f.func_type; 3983 if (s->a.packed) 3984 ad->a.packed = 1; 3985 } 3986 3987 /* Add type qualifiers to a type. If the type is an array then the qualifiers 3988 are added to the element type, copied because it could be a typedef. */ 3989 static void parse_btype_qualify(CType *type, int qualifiers) 3990 { 3991 while (type->t & VT_ARRAY) { 3992 type->ref = sym_push(SYM_FIELD, &type->ref->type, 0, type->ref->c); 3993 type = &type->ref->type; 3994 } 3995 type->t |= qualifiers; 2889 3996 } 2890 3997 … … 2894 4001 static int parse_btype(CType *type, AttributeDef *ad) 2895 4002 { 2896 int t, u, type_found, typespec_found, typedef_found;4003 int t, u, bt, st, type_found, typespec_found, g; 2897 4004 Sym *s; 2898 4005 CType type1; … … 2901 4008 type_found = 0; 2902 4009 typespec_found = 0; 2903 typedef_found = 0; 2904 t = 0; 4010 t = VT_INT; 4011 bt = st = -1; 4012 type->ref = NULL; 4013 2905 4014 while(1) { 2906 4015 switch(tok) { … … 2916 4025 next(); 2917 4026 basic_type1: 2918 if ((t & VT_BTYPE) != 0) 2919 tcc_error("too many basic types"); 2920 t |= u; 4027 if (u == VT_SHORT || u == VT_LONG) { 4028 if (st != -1 || (bt != -1 && bt != VT_INT)) 4029 tmbt: tcc_error("too many basic types"); 4030 st = u; 4031 } else { 4032 if (bt != -1 || (st != -1 && u != VT_INT)) 4033 goto tmbt; 4034 bt = u; 4035 } 4036 if (u != VT_INT) 4037 t = (t & ~(VT_BTYPE|VT_LONG)) | u; 2921 4038 typespec_found = 1; 2922 4039 break; … … 2928 4045 goto basic_type; 2929 4046 case TOK_INT: 2930 next(); 2931 typespec_found = 1; 2932 break; 4047 u = VT_INT; 4048 goto basic_type; 2933 4049 case TOK_LONG: 2934 next();2935 4050 if ((t & VT_BTYPE) == VT_DOUBLE) { 2936 #ifndef TCC_TARGET_PE 2937 t = (t & ~VT_BTYPE) | VT_LDOUBLE; 2938 #endif 2939 } else if ((t & VT_BTYPE) == VT_LONG) { 2940 t = (t & ~VT_BTYPE) | VT_LLONG; 4051 t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LDOUBLE; 4052 } else if ((t & (VT_BTYPE|VT_LONG)) == VT_LONG) { 4053 t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LLONG; 2941 4054 } else { 2942 4055 u = VT_LONG; 2943 goto basic_type1; 2944 } 4056 goto basic_type; 4057 } 4058 next(); 2945 4059 break; 4060 #ifdef TCC_TARGET_ARM64 4061 case TOK_UINT128: 4062 /* GCC's __uint128_t appears in some Linux header files. Make it a 4063 synonym for long double to get the size and alignment right. */ 4064 u = VT_LDOUBLE; 4065 goto basic_type; 4066 #endif 2946 4067 case TOK_BOOL: 2947 4068 u = VT_BOOL; … … 2951 4072 goto basic_type; 2952 4073 case TOK_DOUBLE: 2953 next(); 2954 if ((t & VT_BTYPE) == VT_LONG) { 2955 #ifdef TCC_TARGET_PE 2956 t = (t & ~VT_BTYPE) | VT_DOUBLE; 2957 #else 2958 t = (t & ~VT_BTYPE) | VT_LDOUBLE; 2959 #endif 4074 if ((t & (VT_BTYPE|VT_LONG)) == VT_LONG) { 4075 t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LDOUBLE; 2960 4076 } else { 2961 4077 u = VT_DOUBLE; 2962 goto basic_type1; 2963 } 4078 goto basic_type; 4079 } 4080 next(); 2964 4081 break; 2965 4082 case TOK_ENUM: … … 2970 4087 goto basic_type1; 2971 4088 case TOK_STRUCT: 4089 struct_decl(&type1, VT_STRUCT); 4090 goto basic_type2; 2972 4091 case TOK_UNION: 2973 struct_decl(&type1, VT_ STRUCT);4092 struct_decl(&type1, VT_UNION); 2974 4093 goto basic_type2; 2975 4094 … … 2978 4097 case TOK_CONST2: 2979 4098 case TOK_CONST3: 2980 t |= VT_CONSTANT; 4099 type->t = t; 4100 parse_btype_qualify(type, VT_CONSTANT); 4101 t = type->t; 2981 4102 next(); 2982 4103 break; … … 2984 4105 case TOK_VOLATILE2: 2985 4106 case TOK_VOLATILE3: 2986 t |= VT_VOLATILE; 4107 type->t = t; 4108 parse_btype_qualify(type, VT_VOLATILE); 4109 t = type->t; 2987 4110 next(); 2988 4111 break; … … 2990 4113 case TOK_SIGNED2: 2991 4114 case TOK_SIGNED3: 4115 if ((t & (VT_DEFSIGN|VT_UNSIGNED)) == (VT_DEFSIGN|VT_UNSIGNED)) 4116 tcc_error("signed and unsigned modifier"); 4117 t |= VT_DEFSIGN; 4118 next(); 2992 4119 typespec_found = 1; 2993 t |= VT_SIGNED;2994 next();2995 4120 break; 2996 4121 case TOK_REGISTER: … … 3002 4127 break; 3003 4128 case TOK_UNSIGNED: 3004 t |= VT_UNSIGNED; 4129 if ((t & (VT_DEFSIGN|VT_UNSIGNED)) == VT_DEFSIGN) 4130 tcc_error("signed and unsigned modifier"); 4131 t |= VT_DEFSIGN | VT_UNSIGNED; 3005 4132 next(); 3006 4133 typespec_found = 1; … … 3009 4136 /* storage */ 3010 4137 case TOK_EXTERN: 3011 t |= VT_EXTERN; 3012 next(); 3013 break; 4138 g = VT_EXTERN; 4139 goto storage; 3014 4140 case TOK_STATIC: 3015 t |= VT_STATIC; 3016 next(); 3017 break; 4141 g = VT_STATIC; 4142 goto storage; 3018 4143 case TOK_TYPEDEF: 3019 t |= VT_TYPEDEF; 4144 g = VT_TYPEDEF; 4145 goto storage; 4146 storage: 4147 if (t & (VT_EXTERN|VT_STATIC|VT_TYPEDEF) & ~g) 4148 tcc_error("multiple storage classes"); 4149 t |= g; 3020 4150 next(); 3021 4151 break; … … 3031 4161 case TOK_ATTRIBUTE2: 3032 4162 parse_attribute(ad); 3033 if (ad-> mode) {3034 u = ad-> mode -1;3035 t = (t & ~ VT_BTYPE) | u;4163 if (ad->attr_mode) { 4164 u = ad->attr_mode -1; 4165 t = (t & ~(VT_BTYPE|VT_LONG)) | u; 3036 4166 } 3037 4167 break; … … 3044 4174 /* remove all storage modifiers except typedef */ 3045 4175 type1.t &= ~(VT_STORAGE&~VT_TYPEDEF); 4176 if (type1.ref) 4177 sym_to_attr(ad, type1.ref); 3046 4178 goto basic_type2; 3047 4179 default: 3048 if (typespec_found || typedef_found)4180 if (typespec_found) 3049 4181 goto the_end; 3050 4182 s = sym_find(tok); 3051 4183 if (!s || !(s->type.t & VT_TYPEDEF)) 3052 4184 goto the_end; 3053 typedef_found = 1; 3054 t |= (s->type.t & ~VT_TYPEDEF); 4185 t &= ~(VT_BTYPE|VT_LONG); 4186 u = t & ~(VT_CONSTANT | VT_VOLATILE), t ^= u; 4187 type->t = (s->type.t & ~VT_TYPEDEF) | u; 3055 4188 type->ref = s->type.ref; 3056 if (s->r) { 3057 /* get attributes from typedef */ 3058 if (0 == ad->aligned) 3059 ad->aligned = FUNC_ALIGN(s->r); 3060 if (0 == ad->func_call) 3061 ad->func_call = FUNC_CALL(s->r); 3062 ad->packed |= FUNC_PACKED(s->r); 3063 } 4189 if (t) 4190 parse_btype_qualify(type, t); 4191 t = type->t; 4192 /* get attributes from typedef */ 4193 sym_to_attr(ad, s); 3064 4194 next(); 3065 4195 typespec_found = 1; 4196 st = bt = -2; 3066 4197 break; 3067 4198 } … … 3069 4200 } 3070 4201 the_end: 3071 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))3072 tcc_error("signed and unsigned modifier");3073 4202 if (tcc_state->char_is_unsigned) { 3074 if ((t & (VT_ SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)4203 if ((t & (VT_DEFSIGN|VT_BTYPE)) == VT_BYTE) 3075 4204 t |= VT_UNSIGNED; 3076 4205 } 3077 t &= ~VT_SIGNED; 3078 3079 /* long is never used as type */ 3080 if ((t & VT_BTYPE) == VT_LONG) 3081 #if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE 3082 t = (t & ~VT_BTYPE) | VT_INT; 3083 #else 3084 t = (t & ~VT_BTYPE) | VT_LLONG; 4206 /* VT_LONG is used just as a modifier for VT_INT / VT_LLONG */ 4207 bt = t & (VT_BTYPE|VT_LONG); 4208 if (bt == VT_LONG) 4209 t |= LONG_SIZE == 8 ? VT_LLONG : VT_INT; 4210 #ifdef TCC_TARGET_PE 4211 if (bt == VT_LDOUBLE) 4212 t = (t & ~(VT_BTYPE|VT_LONG)) | VT_DOUBLE; 3085 4213 #endif 3086 4214 type->t = t; … … 3105 4233 { 3106 4234 skip('('); 3107 /* read the string */ 3108 if (tok != TOK_STR) 3109 expect("string constant"); 3110 cstr_new(astr); 3111 while (tok == TOK_STR) { 3112 /* XXX: add \0 handling too ? */ 3113 cstr_cat(astr, tokc.cstr->data); 3114 next(); 3115 } 3116 cstr_ccat(astr, '\0'); 3117 } 3118 3119 /* Parse an asm label and return the label 3120 * Don't forget to free the CString in the caller! */ 3121 static void asm_label_instr(CString *astr) 3122 { 4235 parse_mult_str(astr, "string constant"); 4236 } 4237 4238 /* Parse an asm label and return the token */ 4239 static int asm_label_instr(void) 4240 { 4241 int v; 4242 CString astr; 4243 3123 4244 next(); 3124 parse_asm_str( astr);4245 parse_asm_str(&astr); 3125 4246 skip(')'); 3126 4247 #ifdef ASM_DEBUG 3127 printf("asm_alias: \"%s\"\n", (char *)astr->data); 3128 #endif 3129 } 3130 3131 static void post_type(CType *type, AttributeDef *ad) 4248 printf("asm_alias: \"%s\"\n", (char *)astr.data); 4249 #endif 4250 v = tok_alloc(astr.data, astr.size - 1)->tok; 4251 cstr_free(&astr); 4252 return v; 4253 } 4254 4255 static int post_type(CType *type, AttributeDef *ad, int storage, int td) 3132 4256 { 3133 4257 int n, l, t1, arg_size, align; … … 3137 4261 3138 4262 if (tok == '(') { 3139 /* function declaration*/4263 /* function type, or recursive declarator (return if so) */ 3140 4264 next(); 3141 l = 0; 4265 if (td && !(td & TYPE_ABSTRACT)) 4266 return 0; 4267 if (tok == ')') 4268 l = 0; 4269 else if (parse_btype(&pt, &ad1)) 4270 l = FUNC_NEW; 4271 else if (td) 4272 return 0; 4273 else 4274 l = FUNC_OLD; 3142 4275 first = NULL; 3143 4276 plast = &first; 3144 4277 arg_size = 0; 3145 if ( tok != ')') {4278 if (l) { 3146 4279 for(;;) { 3147 4280 /* read param name and compute offset */ 3148 4281 if (l != FUNC_OLD) { 3149 if (!parse_btype(&pt, &ad1)) {3150 if (l) {3151 tcc_error("invalid type");3152 } else {3153 l = FUNC_OLD;3154 goto old_proto;3155 }3156 }3157 l = FUNC_NEW;3158 4282 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')') 3159 4283 break; … … 3163 4287 arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE; 3164 4288 } else { 3165 old_proto:3166 4289 n = tok; 3167 4290 if (n < TOK_UIDENT) 3168 4291 expect("identifier"); 3169 pt.t = VT_ INT;4292 pt.t = VT_VOID; /* invalid type */ 3170 4293 next(); 3171 4294 } … … 3182 4305 break; 3183 4306 } 3184 } 3185 } 3186 /* if no parameters, then old type prototype */ 3187 if (l == 0) 4307 if (l == FUNC_NEW && !parse_btype(&pt, &ad1)) 4308 tcc_error("invalid type"); 4309 } 4310 } else 4311 /* if no parameters, then old type prototype */ 3188 4312 l = FUNC_OLD; 3189 4313 skip(')'); … … 3197 4321 next(); 3198 4322 skip(']'); /* only handle simple "[]" */ 3199 type->t |= VT_PTR;4323 mk_pointer(type); 3200 4324 } 3201 4325 /* we push a anonymous symbol which will contain the function prototype */ 3202 ad->func_args = arg_size; 3203 s = sym_push(SYM_FIELD, type, INT_ATTR(ad), l); 4326 ad->f.func_args = arg_size; 4327 ad->f.func_type = l; 4328 s = sym_push(SYM_FIELD, type, 0, 0); 4329 s->a = ad->a; 4330 s->f = ad->f; 3204 4331 s->next = first; 3205 4332 type->t = VT_FUNC; 3206 4333 type->ref = s; 3207 4334 } else if (tok == '[') { 4335 int saved_nocode_wanted = nocode_wanted; 3208 4336 /* array definition */ 3209 4337 next(); … … 3213 4341 t1 = 0; 3214 4342 if (tok != ']') { 3215 if (!local_stack || nocode_wanted) 3216 vpushi(expr_const()); 3217 else gexpr(); 4343 if (!local_stack || (storage & VT_STATIC)) 4344 vpushi(expr_const()); 4345 else { 4346 /* VLAs (which can only happen with local_stack && !VT_STATIC) 4347 length must always be evaluated, even under nocode_wanted, 4348 so that its size slot is initialized (e.g. under sizeof 4349 or typeof). */ 4350 nocode_wanted = 0; 4351 gexpr(); 4352 } 3218 4353 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { 3219 4354 n = vtop->c.i; … … 3228 4363 skip(']'); 3229 4364 /* parse next post type */ 3230 post_type(type, ad); 4365 post_type(type, ad, storage, 0); 4366 if (type->t == VT_FUNC) 4367 tcc_error("declaration of an array of functions"); 3231 4368 t1 |= type->t & VT_VLA; 3232 4369 … … 3238 4375 vla_runtime_type_size(type, &align); 3239 4376 gen_op('*'); 3240 vset(&int_type, VT_LOCAL|VT_LVAL, loc);4377 vset(&int_type, VT_LOCAL|VT_LVAL, n); 3241 4378 vswap(); 3242 4379 vstore(); … … 3244 4381 if (n != -1) 3245 4382 vpop(); 4383 nocode_wanted = saved_nocode_wanted; 3246 4384 3247 4385 /* we push an anonymous symbol which will contain the array … … 3251 4389 type->ref = s; 3252 4390 } 3253 } 3254 3255 /* Parse a type declaration (except basic type), and return the type 4391 return 1; 4392 } 4393 4394 /* Parse a type declarator (except basic type), and return the type 3256 4395 in 'type'. 'td' is a bitmask indicating which kind of type decl is 3257 4396 expected. 'type' should contain the basic type. 'ad' is the 3258 4397 attribute definition of the basic type. It can be modified by 3259 type_decl(). 3260 */3261 static void type_decl(CType *type, AttributeDef *ad, int *v, int td) 3262 { 3263 Sym *s; 3264 CType type1, *type2;4398 type_decl(). If this (possibly abstract) declarator is a pointer chain 4399 it returns the innermost pointed to type (equals *type, but is a different 4400 pointer), otherwise returns type itself, that's used for recursive calls. */ 4401 static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td) 4402 { 4403 CType *post, *ret; 3265 4404 int qualifiers, storage; 4405 4406 /* recursive type, remove storage bits first, apply them later again */ 4407 storage = type->t & VT_STORAGE; 4408 type->t &= ~VT_STORAGE; 4409 post = ret = type; 3266 4410 3267 4411 while (tok == '*') { … … 3284 4428 case TOK_RESTRICT3: 3285 4429 goto redo; 4430 /* XXX: clarify attribute handling */ 4431 case TOK_ATTRIBUTE1: 4432 case TOK_ATTRIBUTE2: 4433 parse_attribute(ad); 4434 break; 3286 4435 } 3287 4436 mk_pointer(type); 3288 4437 type->t |= qualifiers; 3289 } 3290 3291 /* XXX: clarify attribute handling */ 3292 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) 3293 parse_attribute(ad); 3294 3295 /* recursive type */ 3296 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */ 3297 type1.t = 0; /* XXX: same as int */ 4438 if (ret == type) 4439 /* innermost pointed to type is the one for the first derivation */ 4440 ret = pointed_type(type); 4441 } 4442 3298 4443 if (tok == '(') { 3299 next(); 3300 /* XXX: this is not correct to modify 'ad' at this point, but 3301 the syntax is not clear */ 3302 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) 3303 parse_attribute(ad); 3304 type_decl(&type1, ad, v, td); 3305 skip(')'); 4444 /* This is possibly a parameter type list for abstract declarators 4445 ('int ()'), use post_type for testing this. */ 4446 if (!post_type(type, ad, 0, td)) { 4447 /* It's not, so it's a nested declarator, and the post operations 4448 apply to the innermost pointed to type (if any). */ 4449 /* XXX: this is not correct to modify 'ad' at this point, but 4450 the syntax is not clear */ 4451 parse_attribute(ad); 4452 post = type_decl(type, ad, v, td); 4453 skip(')'); 4454 } 4455 } else if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) { 4456 /* type identifier */ 4457 *v = tok; 4458 next(); 3306 4459 } else { 3307 /* type identifier */ 3308 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) { 3309 *v = tok; 3310 next(); 3311 } else { 3312 if (!(td & TYPE_ABSTRACT)) 3313 expect("identifier"); 3314 *v = 0; 3315 } 3316 } 3317 storage = type->t & VT_STORAGE; 3318 type->t &= ~VT_STORAGE; 3319 if (storage & VT_STATIC) { 3320 int saved_nocode_wanted = nocode_wanted; 3321 nocode_wanted = 1; 3322 post_type(type, ad); 3323 nocode_wanted = saved_nocode_wanted; 3324 } else 3325 post_type(type, ad); 4460 if (!(td & TYPE_ABSTRACT)) 4461 expect("identifier"); 4462 *v = 0; 4463 } 4464 post_type(post, ad, storage, 0); 4465 parse_attribute(ad); 3326 4466 type->t |= storage; 3327 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) 3328 parse_attribute(ad); 3329 3330 if (!type1.t) 3331 return; 3332 /* append type at the end of type1 */ 3333 type2 = &type1; 3334 for(;;) { 3335 s = type2->ref; 3336 type2 = &s->type; 3337 if (!type2->t) { 3338 *type2 = *type; 3339 break; 3340 } 3341 } 3342 *type = type1; 4467 return ret; 3343 4468 } 3344 4469 … … 3368 4493 expect("pointer"); 3369 4494 } 3370 if ( (vtop->r & VT_LVAL) && !nocode_wanted)4495 if (vtop->r & VT_LVAL) 3371 4496 gv(RC_INT); 3372 4497 vtop->type = *pointed_type(&vtop->type); … … 3389 4514 CType type; 3390 4515 3391 func_type = func-> c;4516 func_type = func->f.func_type; 3392 4517 if (func_type == FUNC_OLD || 3393 4518 (func_type == FUNC_ELLIPSIS && arg == NULL)) { 3394 4519 /* default casting : only need to convert float to double */ 3395 4520 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) { 3396 type.t = VT_DOUBLE; 4521 gen_cast_s(VT_DOUBLE); 4522 } else if (vtop->type.t & VT_BITFIELD) { 4523 type.t = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); 4524 type.ref = vtop->type.ref; 3397 4525 gen_cast(&type); 3398 4526 } … … 3406 4534 } 3407 4535 4536 /* parse an expression and return its type without any side effect. */ 4537 static void expr_type(CType *type, void (*expr_fn)(void)) 4538 { 4539 nocode_wanted++; 4540 expr_fn(); 4541 *type = vtop->type; 4542 vpop(); 4543 nocode_wanted--; 4544 } 4545 3408 4546 /* parse an expression of the form '(type)' or '(expr)' and return its 3409 4547 type */ … … 3417 4555 type_decl(type, &ad, &n, TYPE_ABSTRACT); 3418 4556 } else { 3419 expr_type(type );4557 expr_type(type, gexpr); 3420 4558 } 3421 4559 skip(')'); … … 3433 4571 } 3434 4572 3435 static void vpush_tokc(int t) 3436 { 3437 CType type; 3438 type.t = t; 3439 type.ref = 0; 3440 vsetc(&type, VT_CONST, &tokc); 4573 static void parse_builtin_params(int nc, const char *args) 4574 { 4575 char c, sep = '('; 4576 CType t; 4577 if (nc) 4578 nocode_wanted++; 4579 next(); 4580 while ((c = *args++)) { 4581 skip(sep); 4582 sep = ','; 4583 switch (c) { 4584 case 'e': expr_eq(); continue; 4585 case 't': parse_type(&t); vpush(&t); continue; 4586 default: tcc_error("internal error"); break; 4587 } 4588 } 4589 skip(')'); 4590 if (nc) 4591 nocode_wanted--; 3441 4592 } 3442 4593 … … 3447 4598 Sym *s; 3448 4599 AttributeDef ad; 3449 static int in_sizeof = 0;3450 4600 3451 4601 sizeof_caller = in_sizeof; 3452 4602 in_sizeof = 0; 4603 type.ref = NULL; 3453 4604 /* XXX: GCC 2.95.3 does not generate a table although it should be 3454 4605 better here */ … … 3458 4609 next(); 3459 4610 goto tok_next; 4611 case TOK_LCHAR: 4612 #ifdef TCC_TARGET_PE 4613 t = VT_SHORT|VT_UNSIGNED; 4614 goto push_tokc; 4615 #endif 3460 4616 case TOK_CINT: 3461 4617 case TOK_CCHAR: 3462 case TOK_LCHAR: 3463 vpushi(tokc.i); 4618 t = VT_INT; 4619 push_tokc: 4620 type.t = t; 4621 vsetc(&type, VT_CONST, &tokc); 3464 4622 next(); 3465 4623 break; 3466 4624 case TOK_CUINT: 3467 vpush_tokc(VT_INT | VT_UNSIGNED); 3468 next(); 3469 break; 4625 t = VT_INT | VT_UNSIGNED; 4626 goto push_tokc; 3470 4627 case TOK_CLLONG: 3471 vpush_tokc(VT_LLONG); 3472 next(); 3473 break; 4628 t = VT_LLONG; 4629 goto push_tokc; 3474 4630 case TOK_CULLONG: 3475 vpush_tokc(VT_LLONG | VT_UNSIGNED); 3476 next(); 3477 break; 4631 t = VT_LLONG | VT_UNSIGNED; 4632 goto push_tokc; 3478 4633 case TOK_CFLOAT: 3479 vpush_tokc(VT_FLOAT); 3480 next(); 3481 break; 4634 t = VT_FLOAT; 4635 goto push_tokc; 3482 4636 case TOK_CDOUBLE: 3483 vpush_tokc(VT_DOUBLE); 3484 next(); 3485 break; 4637 t = VT_DOUBLE; 4638 goto push_tokc; 3486 4639 case TOK_CLDOUBLE: 3487 vpush_tokc(VT_LDOUBLE); 3488 next(); 3489 break; 4640 t = VT_LDOUBLE; 4641 goto push_tokc; 4642 case TOK_CLONG: 4643 t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG; 4644 goto push_tokc; 4645 case TOK_CULONG: 4646 t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG | VT_UNSIGNED; 4647 goto push_tokc; 3490 4648 case TOK___FUNCTION__: 3491 4649 if (!gnu_ext) … … 3504 4662 type.ref->c = len; 3505 4663 vpush_ref(&type, data_section, data_section->data_offset, len); 3506 ptr = section_ptr_add(data_section, len); 3507 memcpy(ptr, funcname, len); 4664 if (!NODATA_WANTED) { 4665 ptr = section_ptr_add(data_section, len); 4666 memcpy(ptr, funcname, len); 4667 } 3508 4668 next(); 3509 4669 } … … 3519 4679 /* string parsing */ 3520 4680 t = VT_BYTE; 4681 if (tcc_state->char_is_unsigned) 4682 t = VT_BYTE | VT_UNSIGNED; 3521 4683 str_init: 3522 4684 if (tcc_state->warn_write_strings) … … 3526 4688 type.t |= VT_ARRAY; 3527 4689 memset(&ad, 0, sizeof(AttributeDef)); 3528 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, NULL,0);4690 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0); 3529 4691 break; 3530 4692 case '(': … … 3545 4707 r |= lvalue_type(type.t); 3546 4708 memset(&ad, 0, sizeof(AttributeDef)); 3547 decl_initializer_alloc(&type, &ad, r, 1, 0, NULL,0);4709 decl_initializer_alloc(&type, &ad, r, 1, 0, 0); 3548 4710 } else { 3549 4711 if (sizeof_caller) { … … 3555 4717 } 3556 4718 } else if (tok == '{') { 4719 int saved_nocode_wanted = nocode_wanted; 4720 if (const_wanted) 4721 tcc_error("expected constant"); 3557 4722 /* save all registers */ 3558 save_regs(0); 4723 save_regs(0); 3559 4724 /* statement expression : we do not accept break/continue 3560 inside as GCC does */ 3561 block(NULL, NULL, NULL, NULL, 0, 1); 4725 inside as GCC does. We do retain the nocode_wanted state, 4726 as statement expressions can't ever be entered from the 4727 outside, so any reactivation of code emission (from labels 4728 or loop heads) can be disabled again after the end of it. */ 4729 block(NULL, NULL, 1); 4730 nocode_wanted = saved_nocode_wanted; 3562 4731 skip(')'); 3563 4732 } else { … … 3580 4749 /* arrays can also be used although they are not lvalues */ 3581 4750 if ((vtop->type.t & VT_BTYPE) != VT_FUNC && 3582 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))4751 !(vtop->type.t & VT_ARRAY)) 3583 4752 test_lvalue(); 3584 4753 mk_pointer(&vtop->type); … … 3589 4758 unary(); 3590 4759 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { 3591 CType boolean; 3592 boolean.t = VT_BOOL; 3593 gen_cast(&boolean); 4760 gen_cast_s(VT_BOOL); 3594 4761 vtop->c.i = !vtop->c.i; 3595 4762 } else if ((vtop->r & VT_VALMASK) == VT_CMP) 3596 vtop->c.i = vtop->c.i ^1;4763 vtop->c.i ^= 1; 3597 4764 else { 3598 4765 save_regs(1); 3599 vseti(VT_JMP, g tst(1, 0));4766 vseti(VT_JMP, gvtst(1, 0)); 3600 4767 } 3601 4768 break; … … 3608 4775 case '+': 3609 4776 next(); 3610 /* in order to force cast, we add zero */3611 4777 unary(); 3612 4778 if ((vtop->type.t & VT_BTYPE) == VT_PTR) 3613 4779 tcc_error("pointer not accepted for unary plus"); 3614 vpushi(0); 3615 gen_op('+'); 4780 /* In order to force cast, we add zero, except for floating point 4781 where we really need an noop (otherwise -0.0 will be transformed 4782 into +0.0). */ 4783 if (!is_float(vtop->type.t)) { 4784 vpushi(0); 4785 gen_op('+'); 4786 } 3616 4787 break; 3617 4788 case TOK_SIZEOF: … … 3621 4792 next(); 3622 4793 in_sizeof++; 3623 unary_type(&type); // Perform a in_sizeof = 0; 4794 expr_type(&type, unary); /* Perform a in_sizeof = 0; */ 4795 s = vtop[1].sym; /* hack: accessing previous vtop */ 3624 4796 size = type_size(&type, &align); 4797 if (s && s->a.aligned) 4798 align = 1 << (s->a.aligned - 1); 3625 4799 if (t == TOK_SIZEOF) { 3626 4800 if (!(type.t & VT_VLA)) { … … 3637 4811 break; 3638 4812 4813 case TOK_builtin_expect: 4814 /* __builtin_expect is a no-op for now */ 4815 parse_builtin_params(0, "ee"); 4816 vpop(); 4817 break; 3639 4818 case TOK_builtin_types_compatible_p: 4819 parse_builtin_params(0, "tt"); 4820 vtop[-1].type.t &= ~(VT_CONSTANT | VT_VOLATILE); 4821 vtop[0].type.t &= ~(VT_CONSTANT | VT_VOLATILE); 4822 n = is_compatible_types(&vtop[-1].type, &vtop[0].type); 4823 vtop -= 2; 4824 vpushi(n); 4825 break; 4826 case TOK_builtin_choose_expr: 4827 { 4828 int64_t c; 4829 next(); 4830 skip('('); 4831 c = expr_const64(); 4832 skip(','); 4833 if (!c) { 4834 nocode_wanted++; 4835 } 4836 expr_eq(); 4837 if (!c) { 4838 vpop(); 4839 nocode_wanted--; 4840 } 4841 skip(','); 4842 if (c) { 4843 nocode_wanted++; 4844 } 4845 expr_eq(); 4846 if (c) { 4847 vpop(); 4848 nocode_wanted--; 4849 } 4850 skip(')'); 4851 } 4852 break; 4853 case TOK_builtin_constant_p: 4854 parse_builtin_params(1, "e"); 4855 n = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; 4856 vtop--; 4857 vpushi(n); 4858 break; 4859 case TOK_builtin_frame_address: 4860 case TOK_builtin_return_address: 3640 4861 { 3641 CType type1, type2; 4862 int tok1 = tok; 4863 int level; 3642 4864 next(); 3643 4865 skip('('); 3644 parse_type(&type1); 3645 skip(','); 3646 parse_type(&type2); 3647 skip(')'); 3648 type1.t &= ~(VT_CONSTANT | VT_VOLATILE); 3649 type2.t &= ~(VT_CONSTANT | VT_VOLATILE); 3650 vpushi(is_compatible_types(&type1, &type2)); 3651 } 3652 break; 3653 case TOK_builtin_constant_p: 3654 { 3655 int saved_nocode_wanted, res; 3656 next(); 3657 skip('('); 3658 saved_nocode_wanted = nocode_wanted; 3659 nocode_wanted = 1; 3660 gexpr(); 3661 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; 3662 vpop(); 3663 nocode_wanted = saved_nocode_wanted; 3664 skip(')'); 3665 vpushi(res); 3666 } 3667 break; 3668 case TOK_builtin_frame_address: 3669 { 3670 int level; 3671 CType type; 3672 next(); 3673 skip('('); 3674 if (tok != TOK_CINT || tokc.i < 0) { 3675 tcc_error("__builtin_frame_address only takes positive integers"); 3676 } 3677 level = tokc.i; 4866 if (tok != TOK_CINT) { 4867 tcc_error("%s only takes positive integers", 4868 tok1 == TOK_builtin_return_address ? 4869 "__builtin_return_address" : 4870 "__builtin_frame_address"); 4871 } 4872 level = (uint32_t)tokc.i; 3678 4873 next(); 3679 4874 skip(')'); … … 3685 4880 indir(); /* -> parent frame */ 3686 4881 } 4882 if (tok1 == TOK_builtin_return_address) { 4883 // assume return address is just above frame pointer on stack 4884 vpushi(PTR_SIZE); 4885 gen_op('+'); 4886 mk_pointer(&vtop->type); 4887 indir(); 4888 } 3687 4889 } 3688 4890 break; 3689 4891 #ifdef TCC_TARGET_X86_64 4892 #ifdef TCC_TARGET_PE 4893 case TOK_builtin_va_start: 4894 parse_builtin_params(0, "ee"); 4895 r = vtop->r & VT_VALMASK; 4896 if (r == VT_LLOCAL) 4897 r = VT_LOCAL; 4898 if (r != VT_LOCAL) 4899 tcc_error("__builtin_va_start expects a local variable"); 4900 vtop->r = r; 4901 vtop->type = char_pointer_type; 4902 vtop->c.i += 8; 4903 vstore(); 4904 break; 4905 #else 3690 4906 case TOK_builtin_va_arg_types: 3691 { 3692 /* This definition must be synced with stdarg.h */ 3693 enum __va_arg_type { 3694 __va_gen_reg, __va_float_reg, __va_stack 3695 }; 3696 CType type; 3697 int bt; 3698 next(); 3699 skip('('); 3700 parse_type(&type); 3701 skip(')'); 3702 bt = type.t & VT_BTYPE; 3703 if (bt == VT_STRUCT || bt == VT_LDOUBLE) { 3704 vpushi(__va_stack); 3705 } else if (bt == VT_FLOAT || bt == VT_DOUBLE) { 3706 vpushi(__va_float_reg); 3707 } else { 3708 vpushi(__va_gen_reg); 3709 } 3710 } 4907 parse_builtin_params(0, "t"); 4908 vpushi(classify_x86_64_va_arg(&vtop->type)); 4909 vswap(); 4910 vpop(); 3711 4911 break; 3712 4912 #endif 4913 #endif 4914 4915 #ifdef TCC_TARGET_ARM64 4916 case TOK___va_start: { 4917 parse_builtin_params(0, "ee"); 4918 //xx check types 4919 gen_va_start(); 4920 vpushi(0); 4921 vtop->type.t = VT_VOID; 4922 break; 4923 } 4924 case TOK___va_arg: { 4925 parse_builtin_params(0, "et"); 4926 type = vtop->type; 4927 vpop(); 4928 //xx check types 4929 gen_va_arg(&type); 4930 vtop->type = type; 4931 break; 4932 } 4933 case TOK___arm64_clear_cache: { 4934 parse_builtin_params(0, "ee"); 4935 gen_clear_cache(); 4936 vpushi(0); 4937 vtop->type.t = VT_VOID; 4938 break; 4939 } 4940 #endif 4941 /* pre operations */ 3713 4942 case TOK_INC: 3714 4943 case TOK_DEC: … … 3720 4949 case '-': 3721 4950 next(); 3722 vpushi(0);3723 4951 unary(); 3724 gen_op('-'); 4952 t = vtop->type.t & VT_BTYPE; 4953 if (is_float(t)) { 4954 /* In IEEE negate(x) isn't subtract(0,x), but rather 4955 subtract(-0, x). */ 4956 vpush(&vtop->type); 4957 if (t == VT_FLOAT) 4958 vtop->c.f = -1.0 * 0.0; 4959 else if (t == VT_DOUBLE) 4960 vtop->c.d = -1.0 * 0.0; 4961 else 4962 vtop->c.ld = -1.0 * 0.0; 4963 } else 4964 vpushi(0); 4965 vswap(); 4966 gen_op('-'); 3725 4967 break; 3726 4968 case TOK_LAND: … … 3743 4985 s->type.t |= VT_STATIC; 3744 4986 } 3745 vset(&s->type, VT_CONST | VT_SYM, 0); 3746 vtop->sym = s; 4987 vpushsym(&s->type, s); 3747 4988 next(); 3748 4989 break; 3749 4990 4991 case TOK_GENERIC: 4992 { 4993 CType controlling_type; 4994 int has_default = 0; 4995 int has_match = 0; 4996 int learn = 0; 4997 TokenString *str = NULL; 4998 4999 next(); 5000 skip('('); 5001 expr_type(&controlling_type, expr_eq); 5002 controlling_type.t &= ~(VT_CONSTANT | VT_VOLATILE | VT_ARRAY); 5003 for (;;) { 5004 learn = 0; 5005 skip(','); 5006 if (tok == TOK_DEFAULT) { 5007 if (has_default) 5008 tcc_error("too many 'default'"); 5009 has_default = 1; 5010 if (!has_match) 5011 learn = 1; 5012 next(); 5013 } else { 5014 AttributeDef ad_tmp; 5015 int itmp; 5016 CType cur_type; 5017 parse_btype(&cur_type, &ad_tmp); 5018 type_decl(&cur_type, &ad_tmp, &itmp, TYPE_ABSTRACT); 5019 if (compare_types(&controlling_type, &cur_type, 0)) { 5020 if (has_match) { 5021 tcc_error("type match twice"); 5022 } 5023 has_match = 1; 5024 learn = 1; 5025 } 5026 } 5027 skip(':'); 5028 if (learn) { 5029 if (str) 5030 tok_str_free(str); 5031 skip_or_save_block(&str); 5032 } else { 5033 skip_or_save_block(NULL); 5034 } 5035 if (tok == ')') 5036 break; 5037 } 5038 if (!str) { 5039 char buf[60]; 5040 type_to_str(buf, sizeof buf, &controlling_type, NULL); 5041 tcc_error("type '%s' does not match any association", buf); 5042 } 5043 begin_macro(str, 1); 5044 next(); 5045 expr_eq(); 5046 if (tok != TOK_EOF) 5047 expect(","); 5048 end_macro(); 5049 next(); 5050 break; 5051 } 3750 5052 // special qnan , snan and infinity values 3751 5053 case TOK___NAN__: … … 3769 5071 expect("identifier"); 3770 5072 s = sym_find(t); 3771 if (!s) { 5073 if (!s || IS_ASM_SYM(s)) { 5074 const char *name = get_tok_str(t, NULL); 3772 5075 if (tok != '(') 3773 tcc_error("'%s' undeclared", get_tok_str(t, NULL));5076 tcc_error("'%s' undeclared", name); 3774 5077 /* for simple function calls, we tolerate undeclared 3775 5078 external reference to int() function */ 3776 if (tcc_state->warn_implicit_function_declaration) 3777 tcc_warning("implicit declaration of function '%s'", 3778 get_tok_str(t, NULL)); 5079 if (tcc_state->warn_implicit_function_declaration 5080 #ifdef TCC_TARGET_PE 5081 /* people must be warned about using undeclared WINAPI functions 5082 (which usually start with uppercase letter) */ 5083 || (name[0] >= 'A' && name[0] <= 'Z') 5084 #endif 5085 ) 5086 tcc_warning("implicit declaration of function '%s'", name); 3779 5087 s = external_global_sym(t, &func_old_type, 0); 3780 5088 } 3781 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) == 3782 (VT_STATIC | VT_INLINE | VT_FUNC)) { 3783 /* if referencing an inline function, then we generate a 3784 symbol to it if not already done. It will have the 3785 effect to generate code for it at the end of the 3786 compilation unit. Inline function as always 3787 generated in the text section. */ 3788 if (!s->c) 3789 put_extern_sym(s, text_section, 0, 0); 3790 r = VT_SYM | VT_CONST; 3791 } else { 3792 r = s->r; 3793 } 5089 5090 r = s->r; 5091 /* A symbol that has a register is a local register variable, 5092 which starts out as VT_LOCAL value. */ 5093 if ((r & VT_VALMASK) < VT_CONST) 5094 r = (r & ~VT_VALMASK) | VT_LOCAL; 5095 3794 5096 vset(&s->type, r, s->c); 3795 /* if forward reference, we must point to s */ 3796 if (vtop->r & VT_SYM) { 3797 vtop->sym = s; 3798 vtop->c.ul = 0; 5097 /* Point to s as backpointer (even without r&VT_SYM). 5098 Will be used by at least the x86 inline asm parser for 5099 regvars. */ 5100 vtop->sym = s; 5101 5102 if (r & VT_SYM) { 5103 vtop->c.i = 0; 5104 } else if (r == VT_CONST && IS_ENUM_VAL(s->type.t)) { 5105 vtop->c.i = s->enum_val; 3799 5106 } 3800 5107 break; … … 3806 5113 inc(1, tok); 3807 5114 next(); 3808 } else if (tok == '.' || tok == TOK_ARROW ) {5115 } else if (tok == '.' || tok == TOK_ARROW || tok == TOK_CDOUBLE) { 3809 5116 int qualifiers; 3810 5117 /* field */ … … 3814 5121 test_lvalue(); 3815 5122 gaddrof(); 3816 next();3817 5123 /* expect pointer on structure */ 3818 5124 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT) 3819 5125 expect("struct or union"); 3820 s = vtop->type.ref; 3821 /* find field */ 3822 tok |= SYM_FIELD; 3823 while ((s = s->next) != NULL) { 3824 if (s->v == tok) 3825 break; 3826 } 5126 if (tok == TOK_CDOUBLE) 5127 expect("field name"); 5128 next(); 5129 if (tok == TOK_CINT || tok == TOK_CUINT) 5130 expect("field name"); 5131 s = find_field(&vtop->type, tok); 3827 5132 if (!s) 3828 tcc_error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL));5133 tcc_error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, &tokc)); 3829 5134 /* add field offset to pointer */ 3830 5135 vtop->type = char_pointer_type; /* change type to 'char *' */ … … 3839 5144 #ifdef CONFIG_TCC_BCHECK 3840 5145 /* if bound checking, the referenced pointer must be checked */ 3841 if (tcc_state->do_bounds_check )5146 if (tcc_state->do_bounds_check && (vtop->r & VT_VALMASK) != VT_LOCAL) 3842 5147 vtop->r |= VT_MUSTBOUND; 3843 5148 #endif … … 3853 5158 SValue ret; 3854 5159 Sym *sa; 3855 int nb_args ;5160 int nb_args, ret_nregs, ret_align, regsize, variadic; 3856 5161 3857 5162 /* function call */ … … 3873 5178 next(); 3874 5179 sa = s->next; /* first parameter */ 3875 nb_args = 0;5180 nb_args = regsize = 0; 3876 5181 ret.r2 = VT_CONST; 3877 5182 /* compute first implicit argument if a structure is returned */ 3878 5183 if ((s->type.t & VT_BTYPE) == VT_STRUCT) { 3879 /* get some space for the returned structure */ 3880 size = type_size(&s->type, &align); 3881 loc = (loc - size) & -align; 5184 variadic = (s->f.func_type == FUNC_ELLIPSIS); 5185 ret_nregs = gfunc_sret(&s->type, variadic, &ret.type, 5186 &ret_align, ®size); 5187 if (!ret_nregs) { 5188 /* get some space for the returned structure */ 5189 size = type_size(&s->type, &align); 5190 #ifdef TCC_TARGET_ARM64 5191 /* On arm64, a small struct is return in registers. 5192 It is much easier to write it to memory if we know 5193 that we are allowed to write some extra bytes, so 5194 round the allocated space up to a power of 2: */ 5195 if (size < 16) 5196 while (size & (size - 1)) 5197 size = (size | (size - 1)) + 1; 5198 #endif 5199 loc = (loc - size) & -align; 5200 ret.type = s->type; 5201 ret.r = VT_LOCAL | VT_LVAL; 5202 /* pass it as 'int' to avoid structure arg passing 5203 problems */ 5204 vseti(VT_LOCAL, loc); 5205 ret.c = vtop->c; 5206 nb_args++; 5207 } 5208 } else { 5209 ret_nregs = 1; 3882 5210 ret.type = s->type; 3883 ret.r = VT_LOCAL | VT_LVAL; 3884 /* pass it as 'int' to avoid structure arg passing 3885 problems */ 3886 vseti(VT_LOCAL, loc); 3887 ret.c = vtop->c; 3888 nb_args++; 3889 } else { 3890 ret.type = s->type; 5211 } 5212 5213 if (ret_nregs) { 3891 5214 /* return in register */ 3892 5215 if (is_float(ret.type.t)) { 3893 5216 ret.r = reg_fret(ret.type.t); 5217 #ifdef TCC_TARGET_X86_64 5218 if ((ret.type.t & VT_BTYPE) == VT_QFLOAT) 5219 ret.r2 = REG_QRET; 5220 #endif 3894 5221 } else { 5222 #ifndef TCC_TARGET_ARM64 5223 #ifdef TCC_TARGET_X86_64 5224 if ((ret.type.t & VT_BTYPE) == VT_QLONG) 5225 #else 3895 5226 if ((ret.type.t & VT_BTYPE) == VT_LLONG) 5227 #endif 3896 5228 ret.r2 = REG_LRET; 5229 #endif 3897 5230 ret.r = REG_IRET; 3898 5231 } … … 3914 5247 tcc_error("too few arguments to function"); 3915 5248 skip(')'); 3916 if (!nocode_wanted) { 3917 gfunc_call(nb_args); 3918 } else { 3919 vtop -= (nb_args + 1); 3920 } 5249 gfunc_call(nb_args); 5250 3921 5251 /* return value */ 3922 vsetc(&ret.type, ret.r, &ret.c); 3923 vtop->r2 = ret.r2; 5252 for (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) { 5253 vsetc(&ret.type, r, &ret.c); 5254 vtop->r2 = ret.r2; /* Loop only happens when r2 is VT_CONST */ 5255 } 5256 5257 /* handle packed struct return */ 5258 if (((s->type.t & VT_BTYPE) == VT_STRUCT) && ret_nregs) { 5259 int addr, offset; 5260 5261 size = type_size(&s->type, &align); 5262 /* We're writing whole regs often, make sure there's enough 5263 space. Assume register size is power of 2. */ 5264 if (regsize > align) 5265 align = regsize; 5266 loc = (loc - size) & -align; 5267 addr = loc; 5268 offset = 0; 5269 for (;;) { 5270 vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset); 5271 vswap(); 5272 vstore(); 5273 vtop--; 5274 if (--ret_nregs == 0) 5275 break; 5276 offset += regsize; 5277 } 5278 vset(&s->type, VT_LOCAL | VT_LVAL, addr); 5279 } 3924 5280 } else { 3925 5281 break; … … 4024 5380 } 4025 5381 4026 /* XXX: fix this mess */4027 static void expr_land_const(void)4028 {4029 expr_or();4030 while (tok == TOK_LAND) {4031 next();4032 expr_or();4033 gen_op(TOK_LAND);4034 }4035 }4036 4037 /* XXX: fix this mess */4038 static void expr_lor_const(void)4039 {4040 expr_land_const();4041 while (tok == TOK_LOR) {4042 next();4043 expr_land_const();4044 gen_op(TOK_LOR);4045 }4046 }4047 4048 /* only used if non constant */4049 5382 static void expr_land(void) 4050 5383 { 4051 int t;4052 4053 5384 expr_or(); 4054 5385 if (tok == TOK_LAND) { 4055 t = 0; 4056 save_regs(1); 4057 for(;;) { 4058 t = gtst(1, t); 4059 if (tok != TOK_LAND) { 4060 vseti(VT_JMPI, t); 4061 break; 4062 } 4063 next(); 4064 expr_or(); 4065 } 5386 int t = 0; 5387 for(;;) { 5388 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { 5389 gen_cast_s(VT_BOOL); 5390 if (vtop->c.i) { 5391 vpop(); 5392 } else { 5393 nocode_wanted++; 5394 while (tok == TOK_LAND) { 5395 next(); 5396 expr_or(); 5397 vpop(); 5398 } 5399 nocode_wanted--; 5400 if (t) 5401 gsym(t); 5402 gen_cast_s(VT_INT); 5403 break; 5404 } 5405 } else { 5406 if (!t) 5407 save_regs(1); 5408 t = gvtst(1, t); 5409 } 5410 if (tok != TOK_LAND) { 5411 if (t) 5412 vseti(VT_JMPI, t); 5413 else 5414 vpushi(1); 5415 break; 5416 } 5417 next(); 5418 expr_or(); 5419 } 4066 5420 } 4067 5421 } … … 4069 5423 static void expr_lor(void) 4070 5424 { 4071 int t;4072 4073 5425 expr_land(); 4074 5426 if (tok == TOK_LOR) { 4075 t = 0; 4076 save_regs(1); 4077 for(;;) { 4078 t = gtst(0, t); 4079 if (tok != TOK_LOR) { 4080 vseti(VT_JMP, t); 4081 break; 4082 } 4083 next(); 4084 expr_land(); 4085 } 4086 } 4087 } 4088 4089 /* XXX: better constant handling */ 5427 int t = 0; 5428 for(;;) { 5429 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { 5430 gen_cast_s(VT_BOOL); 5431 if (!vtop->c.i) { 5432 vpop(); 5433 } else { 5434 nocode_wanted++; 5435 while (tok == TOK_LOR) { 5436 next(); 5437 expr_land(); 5438 vpop(); 5439 } 5440 nocode_wanted--; 5441 if (t) 5442 gsym(t); 5443 gen_cast_s(VT_INT); 5444 break; 5445 } 5446 } else { 5447 if (!t) 5448 save_regs(1); 5449 t = gvtst(0, t); 5450 } 5451 if (tok != TOK_LOR) { 5452 if (t) 5453 vseti(VT_JMP, t); 5454 else 5455 vpushi(0); 5456 break; 5457 } 5458 next(); 5459 expr_land(); 5460 } 5461 } 5462 } 5463 5464 /* Assuming vtop is a value used in a conditional context 5465 (i.e. compared with zero) return 0 if it's false, 1 if 5466 true and -1 if it can't be statically determined. */ 5467 static int condition_3way(void) 5468 { 5469 int c = -1; 5470 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && 5471 (!(vtop->r & VT_SYM) || !vtop->sym->a.weak)) { 5472 vdup(); 5473 gen_cast_s(VT_BOOL); 5474 c = vtop->c.i; 5475 vpop(); 5476 } 5477 return c; 5478 } 5479 4090 5480 static void expr_cond(void) 4091 5481 { 4092 int tt, u, r1, r2, rc, t1, t2, bt1, bt2 ;5482 int tt, u, r1, r2, rc, t1, t2, bt1, bt2, islv, c, g; 4093 5483 SValue sv; 4094 5484 CType type, type1, type2; 4095 5485 4096 if (const_wanted) { 4097 expr_lor_const(); 4098 if (tok == '?') { 4099 CType boolean; 4100 int c; 4101 boolean.t = VT_BOOL; 4102 vdup(); 4103 gen_cast(&boolean); 4104 c = vtop->c.i; 4105 vpop(); 4106 next(); 4107 if (tok != ':' || !gnu_ext) { 5486 expr_lor(); 5487 if (tok == '?') { 5488 next(); 5489 c = condition_3way(); 5490 g = (tok == ':' && gnu_ext); 5491 if (c < 0) { 5492 /* needed to avoid having different registers saved in 5493 each branch */ 5494 if (is_float(vtop->type.t)) { 5495 rc = RC_FLOAT; 5496 #ifdef TCC_TARGET_X86_64 5497 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { 5498 rc = RC_ST0; 5499 } 5500 #endif 5501 } else 5502 rc = RC_INT; 5503 gv(rc); 5504 save_regs(1); 5505 if (g) 5506 gv_dup(); 5507 tt = gvtst(1, 0); 5508 5509 } else { 5510 if (!g) 4108 5511 vpop(); 5512 tt = 0; 5513 } 5514 5515 if (1) { 5516 if (c == 0) 5517 nocode_wanted++; 5518 if (!g) 4109 5519 gexpr(); 4110 } 4111 if (!c) 4112 vpop(); 4113 skip(':'); 4114 expr_cond(); 4115 if (c) 4116 vpop(); 4117 } 4118 } else { 4119 expr_lor(); 4120 if (tok == '?') { 4121 next(); 4122 if (vtop != vstack) { 4123 /* needed to avoid having different registers saved in 4124 each branch */ 4125 if (is_float(vtop->type.t)) { 4126 rc = RC_FLOAT; 4127 #ifdef TCC_TARGET_X86_64 4128 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { 4129 rc = RC_ST0; 4130 } 4131 #endif 4132 } 4133 else 4134 rc = RC_INT; 4135 gv(rc); 4136 save_regs(1); 4137 } 4138 if (tok == ':' && gnu_ext) { 4139 gv_dup(); 4140 tt = gtst(1, 0); 4141 } else { 4142 tt = gtst(1, 0); 4143 gexpr(); 4144 } 5520 4145 5521 type1 = vtop->type; 4146 5522 sv = *vtop; /* save value to handle it later */ 4147 5523 vtop--; /* no vpop so that FP stack is not flushed */ 4148 5524 skip(':'); 4149 u = gjmp(0); 5525 5526 u = 0; 5527 if (c < 0) 5528 u = gjmp(0); 4150 5529 gsym(tt); 5530 5531 if (c == 0) 5532 nocode_wanted--; 5533 if (c == 1) 5534 nocode_wanted++; 4151 5535 expr_cond(); 5536 if (c == 1) 5537 nocode_wanted--; 5538 4152 5539 type2 = vtop->type; 4153 4154 5540 t1 = type1.t; 4155 5541 bt1 = t1 & VT_BTYPE; 4156 5542 t2 = type2.t; 4157 5543 bt2 = t2 & VT_BTYPE; 5544 type.ref = NULL; 5545 4158 5546 /* cast operands to correct type according to ISOC rules */ 4159 5547 if (is_float(bt1) || is_float(bt2)) { 4160 5548 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) { 4161 5549 type.t = VT_LDOUBLE; 5550 4162 5551 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) { 4163 5552 type.t = VT_DOUBLE; … … 4167 5556 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) { 4168 5557 /* cast to biggest op */ 4169 type.t = VT_LLONG; 5558 type.t = VT_LLONG | VT_LONG; 5559 if (bt1 == VT_LLONG) 5560 type.t &= t1; 5561 if (bt2 == VT_LLONG) 5562 type.t &= t2; 4170 5563 /* convert to unsigned if it does not fit in a long long */ 4171 if ((t1 & (VT_BTYPE | VT_UNSIGNED )) == (VT_LLONG | VT_UNSIGNED) ||4172 (t2 & (VT_BTYPE | VT_UNSIGNED )) == (VT_LLONG | VT_UNSIGNED))5564 if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED) || 5565 (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED)) 4173 5566 type.t |= VT_UNSIGNED; 4174 5567 } else if (bt1 == VT_PTR || bt2 == VT_PTR) { … … 4194 5587 } else { 4195 5588 /* integer operations */ 4196 type.t = VT_INT ;5589 type.t = VT_INT | (VT_LONG & (t1 | t2)); 4197 5590 /* convert to unsigned if it does not fit in an integer */ 4198 if ((t1 & (VT_BTYPE | VT_UNSIGNED )) == (VT_INT | VT_UNSIGNED) ||4199 (t2 & (VT_BTYPE | VT_UNSIGNED )) == (VT_INT | VT_UNSIGNED))5591 if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED) || 5592 (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED)) 4200 5593 type.t |= VT_UNSIGNED; 4201 5594 } 4202 5595 /* keep structs lvalue by transforming `(expr ? a : b)` to `*(expr ? &a : &b)` so 5596 that `(expr ? a : b).mem` does not error with "lvalue expected" */ 5597 islv = (vtop->r & VT_LVAL) && (sv.r & VT_LVAL) && VT_STRUCT == (type.t & VT_BTYPE); 5598 islv &= c < 0; 5599 4203 5600 /* now we convert second operand */ 4204 gen_cast(&type); 4205 if (VT_STRUCT == (vtop->type.t & VT_BTYPE)) 4206 gaddrof(); 5601 if (c != 1) { 5602 gen_cast(&type); 5603 if (islv) { 5604 mk_pointer(&vtop->type); 5605 gaddrof(); 5606 } else if (VT_STRUCT == (vtop->type.t & VT_BTYPE)) 5607 gaddrof(); 5608 } 5609 4207 5610 rc = RC_INT; 4208 5611 if (is_float(type.t)) { … … 4216 5619 /* for long longs, we use fixed registers to avoid having 4217 5620 to handle a complicated move */ 4218 rc = RC_IRET; 4219 } 4220 4221 r2 = gv(rc); 5621 rc = RC_IRET; 5622 } 5623 5624 tt = r2 = 0; 5625 if (c < 0) { 5626 r2 = gv(rc); 5627 tt = gjmp(0); 5628 } 5629 gsym(u); 5630 4222 5631 /* this is horrible, but we must also convert first 4223 5632 operand */ 4224 tt = gjmp(0); 4225 gsym(u); 4226 /* put again first value and cast it */ 4227 *vtop = sv; 4228 gen_cast(&type); 4229 if (VT_STRUCT == (vtop->type.t & VT_BTYPE)) 4230 gaddrof(); 4231 r1 = gv(rc); 4232 move_reg(r2, r1); 4233 vtop->r = r2; 4234 gsym(tt); 5633 if (c != 0) { 5634 *vtop = sv; 5635 gen_cast(&type); 5636 if (islv) { 5637 mk_pointer(&vtop->type); 5638 gaddrof(); 5639 } else if (VT_STRUCT == (vtop->type.t & VT_BTYPE)) 5640 gaddrof(); 5641 } 5642 5643 if (c < 0) { 5644 r1 = gv(rc); 5645 move_reg(r2, r1, type.t); 5646 vtop->r = r2; 5647 gsym(tt); 5648 if (islv) 5649 indir(); 5650 } 4235 5651 } 4236 5652 } … … 4271 5687 } 4272 5688 4273 /* parse an expression and return its type without any side effect. */4274 static void expr_type(CType *type)4275 {4276 int saved_nocode_wanted;4277 4278 saved_nocode_wanted = nocode_wanted;4279 nocode_wanted = 1;4280 gexpr();4281 *type = vtop->type;4282 vpop();4283 nocode_wanted = saved_nocode_wanted;4284 }4285 4286 /* parse a unary expression and return its type without any side4287 effect. */4288 static void unary_type(CType *type)4289 {4290 int a;4291 4292 a = nocode_wanted;4293 nocode_wanted = 1;4294 unary();4295 *type = vtop->type;4296 vpop();4297 nocode_wanted = a;4298 }4299 4300 5689 /* parse a constant expression and return value in vtop. */ 4301 5690 static void expr_const1(void) 4302 5691 { 4303 int a; 4304 a = const_wanted; 4305 const_wanted = 1; 5692 const_wanted++; 5693 nocode_wanted++; 4306 5694 expr_cond(); 4307 const_wanted = a; 5695 nocode_wanted--; 5696 const_wanted--; 4308 5697 } 4309 5698 4310 5699 /* parse an integer constant and return its value. */ 4311 ST_FUNC int expr_const(void)4312 { 4313 int c;5700 static inline int64_t expr_const64(void) 5701 { 5702 int64_t c; 4314 5703 expr_const1(); 4315 5704 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) … … 4317 5706 c = vtop->c.i; 4318 5707 vpop(); 5708 return c; 5709 } 5710 5711 /* parse an integer constant and return its value. 5712 Complain if it doesn't fit 32bit (signed or unsigned). */ 5713 ST_FUNC int expr_const(void) 5714 { 5715 int c; 5716 int64_t wc = expr_const64(); 5717 c = wc; 5718 if (c != wc && (unsigned)c != wc) 5719 tcc_error("constant exceeds 32 bit"); 4319 5720 return c; 4320 5721 } … … 4333 5734 next(); 4334 5735 if (tok == ':') { 4335 next();4336 5736 return last_tok; 4337 5737 } else { … … 4341 5741 } 4342 5742 4343 static void label_or_decl(int l) 4344 { 4345 int last_tok; 4346 4347 /* fast test first */ 4348 if (tok >= TOK_UIDENT) 4349 { 4350 /* no need to save tokc because tok is an identifier */ 4351 last_tok = tok; 4352 next(); 4353 if (tok == ':') { 4354 unget_tok(last_tok); 4355 return; 4356 } 4357 unget_tok(last_tok); 4358 } 4359 decl(l); 4360 } 4361 4362 static void block(int *bsym, int *csym, int *case_sym, int *def_sym, 4363 int case_reg, int is_expr) 4364 { 4365 int a, b, c, d; 4366 Sym *s, *frame_bottom; 5743 #ifndef TCC_TARGET_ARM64 5744 static void gfunc_return(CType *func_type) 5745 { 5746 if ((func_type->t & VT_BTYPE) == VT_STRUCT) { 5747 CType type, ret_type; 5748 int ret_align, ret_nregs, regsize; 5749 ret_nregs = gfunc_sret(func_type, func_var, &ret_type, 5750 &ret_align, ®size); 5751 if (0 == ret_nregs) { 5752 /* if returning structure, must copy it to implicit 5753 first pointer arg location */ 5754 type = *func_type; 5755 mk_pointer(&type); 5756 vset(&type, VT_LOCAL | VT_LVAL, func_vc); 5757 indir(); 5758 vswap(); 5759 /* copy structure value to pointer */ 5760 vstore(); 5761 } else { 5762 /* returning structure packed into registers */ 5763 int r, size, addr, align; 5764 size = type_size(func_type,&align); 5765 if ((vtop->r != (VT_LOCAL | VT_LVAL) || 5766 (vtop->c.i & (ret_align-1))) 5767 && (align & (ret_align-1))) { 5768 loc = (loc - size) & -ret_align; 5769 addr = loc; 5770 type = *func_type; 5771 vset(&type, VT_LOCAL | VT_LVAL, addr); 5772 vswap(); 5773 vstore(); 5774 vpop(); 5775 vset(&ret_type, VT_LOCAL | VT_LVAL, addr); 5776 } 5777 vtop->type = ret_type; 5778 if (is_float(ret_type.t)) 5779 r = rc_fret(ret_type.t); 5780 else 5781 r = RC_IRET; 5782 5783 if (ret_nregs == 1) 5784 gv(r); 5785 else { 5786 for (;;) { 5787 vdup(); 5788 gv(r); 5789 vpop(); 5790 if (--ret_nregs == 0) 5791 break; 5792 /* We assume that when a structure is returned in multiple 5793 registers, their classes are consecutive values of the 5794 suite s(n) = 2^n */ 5795 r <<= 1; 5796 vtop->c.i += regsize; 5797 } 5798 } 5799 } 5800 } else if (is_float(func_type->t)) { 5801 gv(rc_fret(func_type->t)); 5802 } else { 5803 gv(RC_IRET); 5804 } 5805 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */ 5806 } 5807 #endif 5808 5809 static int case_cmp(const void *pa, const void *pb) 5810 { 5811 int64_t a = (*(struct case_t**) pa)->v1; 5812 int64_t b = (*(struct case_t**) pb)->v1; 5813 return a < b ? -1 : a > b; 5814 } 5815 5816 static void gcase(struct case_t **base, int len, int *bsym) 5817 { 5818 struct case_t *p; 5819 int e; 5820 int ll = (vtop->type.t & VT_BTYPE) == VT_LLONG; 5821 gv(RC_INT); 5822 while (len > 4) { 5823 /* binary search */ 5824 p = base[len/2]; 5825 vdup(); 5826 if (ll) 5827 vpushll(p->v2); 5828 else 5829 vpushi(p->v2); 5830 gen_op(TOK_LE); 5831 e = gtst(1, 0); 5832 vdup(); 5833 if (ll) 5834 vpushll(p->v1); 5835 else 5836 vpushi(p->v1); 5837 gen_op(TOK_GE); 5838 gtst_addr(0, p->sym); /* v1 <= x <= v2 */ 5839 /* x < v1 */ 5840 gcase(base, len/2, bsym); 5841 if (cur_switch->def_sym) 5842 gjmp_addr(cur_switch->def_sym); 5843 else 5844 *bsym = gjmp(*bsym); 5845 /* x > v2 */ 5846 gsym(e); 5847 e = len/2 + 1; 5848 base += e; len -= e; 5849 } 5850 /* linear scan */ 5851 while (len--) { 5852 p = *base++; 5853 vdup(); 5854 if (ll) 5855 vpushll(p->v2); 5856 else 5857 vpushi(p->v2); 5858 if (p->v1 == p->v2) { 5859 gen_op(TOK_EQ); 5860 gtst_addr(0, p->sym); 5861 } else { 5862 gen_op(TOK_LE); 5863 e = gtst(1, 0); 5864 vdup(); 5865 if (ll) 5866 vpushll(p->v1); 5867 else 5868 vpushi(p->v1); 5869 gen_op(TOK_GE); 5870 gtst_addr(0, p->sym); 5871 gsym(e); 5872 } 5873 } 5874 } 5875 5876 static void block(int *bsym, int *csym, int is_expr) 5877 { 5878 int a, b, c, d, cond; 5879 Sym *s; 4367 5880 4368 5881 /* generate line number info */ 4369 if (tcc_state->do_debug && 4370 (last_line_num != file->line_num || last_ind != ind)) { 4371 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind); 4372 last_ind = ind; 4373 last_line_num = file->line_num; 4374 } 5882 if (tcc_state->do_debug) 5883 tcc_debug_line(tcc_state); 4375 5884 4376 5885 if (is_expr) { … … 4382 5891 if (tok == TOK_IF) { 4383 5892 /* if test */ 5893 int saved_nocode_wanted = nocode_wanted; 4384 5894 next(); 4385 5895 skip('('); 4386 5896 gexpr(); 4387 5897 skip(')'); 4388 a = gtst(1, 0); 4389 block(bsym, csym, case_sym, def_sym, case_reg, 0); 5898 cond = condition_3way(); 5899 if (cond == 1) 5900 a = 0, vpop(); 5901 else 5902 a = gvtst(1, 0); 5903 if (cond == 0) 5904 nocode_wanted |= 0x20000000; 5905 block(bsym, csym, 0); 5906 if (cond != 1) 5907 nocode_wanted = saved_nocode_wanted; 4390 5908 c = tok; 4391 5909 if (c == TOK_ELSE) { … … 4393 5911 d = gjmp(0); 4394 5912 gsym(a); 4395 block(bsym, csym, case_sym, def_sym, case_reg, 0); 5913 if (cond == 1) 5914 nocode_wanted |= 0x20000000; 5915 block(bsym, csym, 0); 4396 5916 gsym(d); /* patch else jmp */ 5917 if (cond != 0) 5918 nocode_wanted = saved_nocode_wanted; 4397 5919 } else 4398 5920 gsym(a); 4399 5921 } else if (tok == TOK_WHILE) { 5922 int saved_nocode_wanted; 5923 nocode_wanted &= ~0x20000000; 4400 5924 next(); 4401 5925 d = ind; 5926 vla_sp_restore(); 4402 5927 skip('('); 4403 5928 gexpr(); 4404 5929 skip(')'); 4405 a = g tst(1, 0);5930 a = gvtst(1, 0); 4406 5931 b = 0; 4407 block(&a, &b, case_sym, def_sym, case_reg, 0); 5932 ++local_scope; 5933 saved_nocode_wanted = nocode_wanted; 5934 block(&a, &b, 0); 5935 nocode_wanted = saved_nocode_wanted; 5936 --local_scope; 4408 5937 gjmp_addr(d); 4409 5938 gsym(a); … … 4411 5940 } else if (tok == '{') { 4412 5941 Sym *llabel; 4413 5942 int block_vla_sp_loc = vla_sp_loc, saved_vlas_in_scope = vlas_in_scope; 5943 4414 5944 next(); 4415 5945 /* record local declaration stack position */ 4416 5946 s = local_stack; 4417 frame_bottom = sym_push2(&local_stack, SYM_FIELD, 0, 0);4418 frame_bottom->next = scope_stack_bottom;4419 scope_stack_bottom = frame_bottom;4420 5947 llabel = local_label_stack; 5948 ++local_scope; 5949 4421 5950 /* handle local labels declarations */ 4422 5951 if (tok == TOK_LABEL) { … … 4436 5965 } 4437 5966 while (tok != '}') { 4438 label_or_decl(VT_LOCAL); 5967 if ((a = is_label())) 5968 unget_tok(a); 5969 else 5970 decl(VT_LOCAL); 4439 5971 if (tok != '}') { 4440 5972 if (is_expr) 4441 5973 vpop(); 4442 block(bsym, csym, case_sym, def_sym, case_reg,is_expr);5974 block(bsym, csym, is_expr); 4443 5975 } 4444 5976 } 4445 5977 /* pop locally defined labels */ 4446 label_pop(&local_label_stack, llabel); 4447 if(is_expr) { 4448 /* XXX: this solution makes only valgrind happy... 4449 triggered by gcc.c-torture/execute/20000917-1.c */ 4450 Sym *p; 4451 switch(vtop->type.t & VT_BTYPE) { 4452 case VT_PTR: 4453 case VT_STRUCT: 4454 case VT_ENUM: 4455 case VT_FUNC: 4456 for(p=vtop->type.ref;p;p=p->prev) 4457 if(p->prev==s) 4458 tcc_error("unsupported expression type"); 4459 } 4460 } 5978 label_pop(&local_label_stack, llabel, is_expr); 4461 5979 /* pop locally defined symbols */ 4462 scope_stack_bottom = scope_stack_bottom->next; 4463 sym_pop(&local_stack, s); 5980 --local_scope; 5981 /* In the is_expr case (a statement expression is finished here), 5982 vtop might refer to symbols on the local_stack. Either via the 5983 type or via vtop->sym. We can't pop those nor any that in turn 5984 might be referred to. To make it easier we don't roll back 5985 any symbols in that case; some upper level call to block() will 5986 do that. We do have to remove such symbols from the lookup 5987 tables, though. sym_pop will do that. */ 5988 sym_pop(&local_stack, s, is_expr); 5989 5990 /* Pop VLA frames and restore stack pointer if required */ 5991 if (vlas_in_scope > saved_vlas_in_scope) { 5992 vla_sp_loc = saved_vlas_in_scope ? block_vla_sp_loc : vla_sp_root_loc; 5993 vla_sp_restore(); 5994 } 5995 vlas_in_scope = saved_vlas_in_scope; 5996 4464 5997 next(); 4465 5998 } else if (tok == TOK_RETURN) { … … 4468 6001 gexpr(); 4469 6002 gen_assign_cast(&func_vt); 4470 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { 4471 CType type; 4472 /* if returning structure, must copy it to implicit 4473 first pointer arg location */ 4474 #ifdef TCC_ARM_EABI 4475 int align, size; 4476 size = type_size(&func_vt,&align); 4477 if(size <= 4) 4478 { 4479 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3)) 4480 && (align & 3)) 4481 { 4482 int addr; 4483 loc = (loc - size) & -4; 4484 addr = loc; 4485 type = func_vt; 4486 vset(&type, VT_LOCAL | VT_LVAL, addr); 4487 vswap(); 4488 vstore(); 4489 vset(&int_type, VT_LOCAL | VT_LVAL, addr); 4490 } 4491 vtop->type = int_type; 4492 gv(RC_IRET); 4493 } else { 4494 #endif 4495 type = func_vt; 4496 mk_pointer(&type); 4497 vset(&type, VT_LOCAL | VT_LVAL, func_vc); 4498 indir(); 4499 vswap(); 4500 /* copy structure value to pointer */ 4501 vstore(); 4502 #ifdef TCC_ARM_EABI 4503 } 4504 #endif 4505 } else if (is_float(func_vt.t)) { 4506 gv(rc_fret(func_vt.t)); 4507 } else { 4508 gv(RC_IRET); 4509 } 4510 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */ 6003 if ((func_vt.t & VT_BTYPE) == VT_VOID) 6004 vtop--; 6005 else 6006 gfunc_return(&func_vt); 4511 6007 } 4512 6008 skip(';'); 4513 rsym = gjmp(rsym); /* jmp */ 6009 /* jump unless last stmt in top-level block */ 6010 if (tok != '}' || local_scope != 1) 6011 rsym = gjmp(rsym); 6012 nocode_wanted |= 0x20000000; 4514 6013 } else if (tok == TOK_BREAK) { 4515 6014 /* compute jump */ … … 4519 6018 next(); 4520 6019 skip(';'); 6020 nocode_wanted |= 0x20000000; 4521 6021 } else if (tok == TOK_CONTINUE) { 4522 6022 /* compute jump */ 4523 6023 if (!csym) 4524 6024 tcc_error("cannot continue"); 6025 vla_sp_restore_root(); 4525 6026 *csym = gjmp(*csym); 4526 6027 next(); … … 4528 6029 } else if (tok == TOK_FOR) { 4529 6030 int e; 6031 int saved_nocode_wanted; 6032 nocode_wanted &= ~0x20000000; 4530 6033 next(); 4531 6034 skip('('); 4532 6035 s = local_stack; 4533 frame_bottom = sym_push2(&local_stack, SYM_FIELD, 0, 0); 4534 frame_bottom->next = scope_stack_bottom; 4535 scope_stack_bottom = frame_bottom; 6036 ++local_scope; 4536 6037 if (tok != ';') { 4537 6038 /* c99 for-loop init decl? */ 4538 if (!decl0(VT_LOCAL, 1 )) {6039 if (!decl0(VT_LOCAL, 1, NULL)) { 4539 6040 /* no, regular for-loop init expr */ 4540 6041 gexpr(); … … 4545 6046 d = ind; 4546 6047 c = ind; 6048 vla_sp_restore(); 4547 6049 a = 0; 4548 6050 b = 0; 4549 6051 if (tok != ';') { 4550 6052 gexpr(); 4551 a = g tst(1, 0);6053 a = gvtst(1, 0); 4552 6054 } 4553 6055 skip(';'); … … 4555 6057 e = gjmp(0); 4556 6058 c = ind; 6059 vla_sp_restore(); 4557 6060 gexpr(); 4558 6061 vpop(); … … 4561 6064 } 4562 6065 skip(')'); 4563 block(&a, &b, case_sym, def_sym, case_reg, 0); 6066 saved_nocode_wanted = nocode_wanted; 6067 block(&a, &b, 0); 6068 nocode_wanted = saved_nocode_wanted; 4564 6069 gjmp_addr(c); 4565 6070 gsym(a); 4566 6071 gsym_addr(b, c); 4567 scope_stack_bottom = scope_stack_bottom->next; 4568 sym_pop(&local_stack, s); 6072 --local_scope; 6073 sym_pop(&local_stack, s, 0); 6074 4569 6075 } else 4570 6076 if (tok == TOK_DO) { 6077 int saved_nocode_wanted; 6078 nocode_wanted &= ~0x20000000; 4571 6079 next(); 4572 6080 a = 0; 4573 6081 b = 0; 4574 6082 d = ind; 4575 block(&a, &b, case_sym, def_sym, case_reg, 0); 6083 vla_sp_restore(); 6084 saved_nocode_wanted = nocode_wanted; 6085 block(&a, &b, 0); 4576 6086 skip(TOK_WHILE); 4577 6087 skip('('); 4578 6088 gsym(b); 4579 gexpr(); 4580 c = gtst(0, 0); 4581 gsym_addr(c, d); 6089 gexpr(); 6090 c = gvtst(0, 0); 6091 gsym_addr(c, d); 6092 nocode_wanted = saved_nocode_wanted; 4582 6093 skip(')'); 4583 6094 gsym(a); … … 4585 6096 } else 4586 6097 if (tok == TOK_SWITCH) { 6098 struct switch_t *saved, sw; 6099 int saved_nocode_wanted = nocode_wanted; 6100 SValue switchval; 4587 6101 next(); 4588 6102 skip('('); 4589 6103 gexpr(); 4590 /* XXX: other types than integer */4591 case_reg = gv(RC_INT);4592 vpop();4593 6104 skip(')'); 6105 switchval = *vtop--; 4594 6106 a = 0; 4595 6107 b = gjmp(0); /* jump to first case */ 4596 c = 0; 4597 block(&a, csym, &b, &c, case_reg, 0); 4598 /* if no default, jmp after switch */ 4599 if (c == 0) 4600 c = ind; 4601 /* default label */ 4602 gsym_addr(b, c); 6108 sw.p = NULL; sw.n = 0; sw.def_sym = 0; 6109 saved = cur_switch; 6110 cur_switch = &sw; 6111 block(&a, csym, 0); 6112 nocode_wanted = saved_nocode_wanted; 6113 a = gjmp(a); /* add implicit break */ 6114 /* case lookup */ 6115 gsym(b); 6116 qsort(sw.p, sw.n, sizeof(void*), case_cmp); 6117 for (b = 1; b < sw.n; b++) 6118 if (sw.p[b - 1]->v2 >= sw.p[b]->v1) 6119 tcc_error("duplicate case value"); 6120 /* Our switch table sorting is signed, so the compared 6121 value needs to be as well when it's 64bit. */ 6122 if ((switchval.type.t & VT_BTYPE) == VT_LLONG) 6123 switchval.type.t &= ~VT_UNSIGNED; 6124 vpushv(&switchval); 6125 gcase(sw.p, sw.n, &a); 6126 vpop(); 6127 if (sw.def_sym) 6128 gjmp_addr(sw.def_sym); 6129 dynarray_reset(&sw.p, &sw.n); 6130 cur_switch = saved; 4603 6131 /* break label */ 4604 6132 gsym(a); 4605 6133 } else 4606 6134 if (tok == TOK_CASE) { 4607 int v1, v2;4608 if (!c ase_sym)6135 struct case_t *cr = tcc_malloc(sizeof(struct case_t)); 6136 if (!cur_switch) 4609 6137 expect("switch"); 6138 nocode_wanted &= ~0x20000000; 4610 6139 next(); 4611 v1 = expr_const(); 4612 v2 = v1; 6140 cr->v1 = cr->v2 = expr_const64(); 4613 6141 if (gnu_ext && tok == TOK_DOTS) { 4614 6142 next(); 4615 v2 = expr_const();4616 if ( v2 <v1)6143 cr->v2 = expr_const64(); 6144 if (cr->v2 < cr->v1) 4617 6145 tcc_warning("empty case range"); 4618 6146 } 4619 /* since a case is like a label, we must skip it with a jmp */ 4620 b = gjmp(0); 4621 gsym(*case_sym); 4622 vseti(case_reg, 0); 4623 vpushi(v1); 4624 if (v1 == v2) { 4625 gen_op(TOK_EQ); 4626 *case_sym = gtst(1, 0); 4627 } else { 4628 gen_op(TOK_GE); 4629 *case_sym = gtst(1, 0); 4630 vseti(case_reg, 0); 4631 vpushi(v2); 4632 gen_op(TOK_LE); 4633 *case_sym = gtst(1, *case_sym); 4634 } 4635 gsym(b); 6147 cr->sym = ind; 6148 dynarray_add(&cur_switch->p, &cur_switch->n, cr); 4636 6149 skip(':'); 4637 6150 is_expr = 0; … … 4641 6154 next(); 4642 6155 skip(':'); 4643 if (! def_sym)6156 if (!cur_switch) 4644 6157 expect("switch"); 4645 if ( *def_sym)6158 if (cur_switch->def_sym) 4646 6159 tcc_error("too many 'default'"); 4647 *def_sym = ind;6160 cur_switch->def_sym = ind; 4648 6161 is_expr = 0; 4649 6162 goto block_after_label; … … 4667 6180 s->r = LABEL_FORWARD; 4668 6181 } 4669 /* label already defined */4670 if (s->r & LABEL_FORWARD) 6182 vla_sp_restore_root(); 6183 if (s->r & LABEL_FORWARD) 4671 6184 s->jnext = gjmp(s->jnext); 4672 6185 else … … 4683 6196 if (b) { 4684 6197 /* label case */ 6198 next(); 4685 6199 s = label_find(b); 4686 6200 if (s) { … … 4693 6207 } 4694 6208 s->jnext = ind; 6209 vla_sp_restore(); 4695 6210 /* we accept this, but it is a mistake */ 4696 6211 block_after_label: 6212 nocode_wanted &= ~0x20000000; 4697 6213 if (tok == '}') { 4698 6214 tcc_warning("deprecated use of label at end of compound statement"); … … 4700 6216 if (is_expr) 4701 6217 vpop(); 4702 block(bsym, csym, case_sym, def_sym, case_reg,is_expr);6218 block(bsym, csym, is_expr); 4703 6219 } 4704 6220 } else { … … 4718 6234 } 4719 6235 4720 /* t is the array or struct type. c is the array or struct 4721 address. cur_index/cur_field is the pointer to the current 4722 value. 'size_only' is true if only size info is needed (only used 4723 in arrays) */ 4724 static void decl_designator(CType *type, Section *sec, unsigned long c, 4725 int *cur_index, Sym **cur_field, 4726 int size_only) 4727 { 4728 Sym *s, *f; 4729 int notfirst, index, index_last, align, l, nb_elems, elem_size; 4730 CType type1; 4731 4732 notfirst = 0; 4733 elem_size = 0; 4734 nb_elems = 1; 4735 if (gnu_ext && (l = is_label()) != 0) 4736 goto struct_field; 4737 while (tok == '[' || tok == '.') { 4738 if (tok == '[') { 4739 if (!(type->t & VT_ARRAY)) 4740 expect("array type"); 4741 s = type->ref; 4742 next(); 4743 index = expr_const(); 4744 if (index < 0 || (s->c >= 0 && index >= s->c)) 4745 expect("invalid index"); 4746 if (tok == TOK_DOTS && gnu_ext) { 4747 next(); 4748 index_last = expr_const(); 4749 if (index_last < 0 || 4750 (s->c >= 0 && index_last >= s->c) || 4751 index_last < index) 4752 expect("invalid index"); 4753 } else { 4754 index_last = index; 4755 } 4756 skip(']'); 4757 if (!notfirst) 4758 *cur_index = index_last; 4759 type = pointed_type(type); 4760 elem_size = type_size(type, &align); 4761 c += index * elem_size; 4762 /* NOTE: we only support ranges for last designator */ 4763 nb_elems = index_last - index + 1; 4764 if (nb_elems != 1) { 4765 notfirst = 1; 4766 break; 4767 } 4768 } else { 4769 next(); 4770 l = tok; 4771 next(); 4772 struct_field: 4773 if ((type->t & VT_BTYPE) != VT_STRUCT) 4774 expect("struct/union type"); 4775 s = type->ref; 4776 l |= SYM_FIELD; 4777 f = s->next; 4778 while (f) { 4779 if (f->v == l) 4780 break; 4781 f = f->next; 4782 } 4783 if (!f) 4784 expect("field"); 4785 if (!notfirst) 4786 *cur_field = f; 4787 /* XXX: fix this mess by using explicit storage field */ 4788 type1 = f->type; 4789 type1.t |= (type->t & ~VT_TYPE); 4790 type = &type1; 4791 c += f->c; 4792 } 4793 notfirst = 1; 4794 } 4795 if (notfirst) { 4796 if (tok == '=') { 4797 next(); 4798 } else { 4799 if (!gnu_ext) 4800 expect("="); 4801 } 4802 } else { 4803 if (type->t & VT_ARRAY) { 4804 index = *cur_index; 4805 type = pointed_type(type); 4806 c += index * type_size(type, &align); 4807 } else { 4808 f = *cur_field; 4809 if (!f) 4810 tcc_error("too many field init"); 4811 /* XXX: fix this mess by using explicit storage field */ 4812 type1 = f->type; 4813 type1.t |= (type->t & ~VT_TYPE); 4814 type = &type1; 4815 c += f->c; 4816 } 4817 } 4818 decl_initializer(type, sec, c, 0, size_only); 4819 4820 /* XXX: make it more general */ 4821 if (!size_only && nb_elems > 1) { 4822 unsigned long c_end; 4823 uint8_t *src, *dst; 4824 int i; 4825 4826 if (!sec) 4827 tcc_error("range init not supported yet for dynamic storage"); 4828 c_end = c + nb_elems * elem_size; 4829 if (c_end > sec->data_allocated) 4830 section_realloc(sec, c_end); 4831 src = sec->data + c; 4832 dst = src; 4833 for(i = 1; i < nb_elems; i++) { 4834 dst += elem_size; 4835 memcpy(dst, src, elem_size); 4836 } 4837 } 4838 } 4839 4840 #define EXPR_VAL 0 6236 /* This skips over a stream of tokens containing balanced {} and () 6237 pairs, stopping at outer ',' ';' and '}' (or matching '}' if we started 6238 with a '{'). If STR then allocates and stores the skipped tokens 6239 in *STR. This doesn't check if () and {} are nested correctly, 6240 i.e. "({)}" is accepted. */ 6241 static void skip_or_save_block(TokenString **str) 6242 { 6243 int braces = tok == '{'; 6244 int level = 0; 6245 if (str) 6246 *str = tok_str_alloc(); 6247 6248 while ((level > 0 || (tok != '}' && tok != ',' && tok != ';' && tok != ')'))) { 6249 int t; 6250 if (tok == TOK_EOF) { 6251 if (str || level > 0) 6252 tcc_error("unexpected end of file"); 6253 else 6254 break; 6255 } 6256 if (str) 6257 tok_str_add_tok(*str); 6258 t = tok; 6259 next(); 6260 if (t == '{' || t == '(') { 6261 level++; 6262 } else if (t == '}' || t == ')') { 6263 level--; 6264 if (level == 0 && braces && t == '}') 6265 break; 6266 } 6267 } 6268 if (str) { 6269 tok_str_add(*str, -1); 6270 tok_str_add(*str, 0); 6271 } 6272 } 6273 4841 6274 #define EXPR_CONST 1 4842 6275 #define EXPR_ANY 2 4843 6276 4844 /* store a value or an expression directly in global data or in local array */ 4845 static void init_putv(CType *type, Section *sec, unsigned long c, 4846 int v, int expr_type) 4847 { 4848 int saved_global_expr, bt, bit_pos, bit_size; 4849 void *ptr; 4850 unsigned long long bit_mask; 4851 CType dtype; 4852 6277 static void parse_init_elem(int expr_type) 6278 { 6279 int saved_global_expr; 4853 6280 switch(expr_type) { 4854 case EXPR_VAL:4855 vpushi(v);4856 break;4857 6281 case EXPR_CONST: 4858 6282 /* compound literals must be allocated globally in this case */ … … 4861 6285 expr_const1(); 4862 6286 global_expr = saved_global_expr; 4863 /* NOTE: symbols are accepted */ 4864 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST) 6287 /* NOTE: symbols are accepted, as well as lvalue for anon symbols 6288 (compound literals). */ 6289 if (((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST 6290 && ((vtop->r & (VT_SYM|VT_LVAL)) != (VT_SYM|VT_LVAL) 6291 || vtop->sym->v < SYM_FIRST_ANOM)) 6292 #ifdef TCC_TARGET_PE 6293 || ((vtop->r & VT_SYM) && vtop->sym->a.dllimport) 6294 #endif 6295 ) 4865 6296 tcc_error("initializer element is not constant"); 4866 6297 break; … … 4869 6300 break; 4870 6301 } 4871 6302 } 6303 6304 /* put zeros for variable based init */ 6305 static void init_putz(Section *sec, unsigned long c, int size) 6306 { 6307 if (sec) { 6308 /* nothing to do because globals are already set to zero */ 6309 } else { 6310 vpush_global_sym(&func_old_type, TOK_memset); 6311 vseti(VT_LOCAL, c); 6312 #ifdef TCC_TARGET_ARM 6313 vpushs(size); 6314 vpushi(0); 6315 #else 6316 vpushi(0); 6317 vpushs(size); 6318 #endif 6319 gfunc_call(3); 6320 } 6321 } 6322 6323 /* t is the array or struct type. c is the array or struct 6324 address. cur_field is the pointer to the current 6325 field, for arrays the 'c' member contains the current start 6326 index. 'size_only' is true if only size info is needed (only used 6327 in arrays). al contains the already initialized length of the 6328 current container (starting at c). This returns the new length of that. */ 6329 static int decl_designator(CType *type, Section *sec, unsigned long c, 6330 Sym **cur_field, int size_only, int al) 6331 { 6332 Sym *s, *f; 6333 int index, index_last, align, l, nb_elems, elem_size; 6334 unsigned long corig = c; 6335 6336 elem_size = 0; 6337 nb_elems = 1; 6338 if (gnu_ext && (l = is_label()) != 0) 6339 goto struct_field; 6340 /* NOTE: we only support ranges for last designator */ 6341 while (nb_elems == 1 && (tok == '[' || tok == '.')) { 6342 if (tok == '[') { 6343 if (!(type->t & VT_ARRAY)) 6344 expect("array type"); 6345 next(); 6346 index = index_last = expr_const(); 6347 if (tok == TOK_DOTS && gnu_ext) { 6348 next(); 6349 index_last = expr_const(); 6350 } 6351 skip(']'); 6352 s = type->ref; 6353 if (index < 0 || (s->c >= 0 && index_last >= s->c) || 6354 index_last < index) 6355 tcc_error("invalid index"); 6356 if (cur_field) 6357 (*cur_field)->c = index_last; 6358 type = pointed_type(type); 6359 elem_size = type_size(type, &align); 6360 c += index * elem_size; 6361 nb_elems = index_last - index + 1; 6362 } else { 6363 next(); 6364 l = tok; 6365 struct_field: 6366 next(); 6367 if ((type->t & VT_BTYPE) != VT_STRUCT) 6368 expect("struct/union type"); 6369 f = find_field(type, l); 6370 if (!f) 6371 expect("field"); 6372 if (cur_field) 6373 *cur_field = f; 6374 type = &f->type; 6375 c += f->c; 6376 } 6377 cur_field = NULL; 6378 } 6379 if (!cur_field) { 6380 if (tok == '=') { 6381 next(); 6382 } else if (!gnu_ext) { 6383 expect("="); 6384 } 6385 } else { 6386 if (type->t & VT_ARRAY) { 6387 index = (*cur_field)->c; 6388 if (type->ref->c >= 0 && index >= type->ref->c) 6389 tcc_error("index too large"); 6390 type = pointed_type(type); 6391 c += index * type_size(type, &align); 6392 } else { 6393 f = *cur_field; 6394 while (f && (f->v & SYM_FIRST_ANOM) && (f->type.t & VT_BITFIELD)) 6395 *cur_field = f = f->next; 6396 if (!f) 6397 tcc_error("too many field init"); 6398 type = &f->type; 6399 c += f->c; 6400 } 6401 } 6402 /* must put zero in holes (note that doing it that way 6403 ensures that it even works with designators) */ 6404 if (!size_only && c - corig > al) 6405 init_putz(sec, corig + al, c - corig - al); 6406 decl_initializer(type, sec, c, 0, size_only); 6407 6408 /* XXX: make it more general */ 6409 if (!size_only && nb_elems > 1) { 6410 unsigned long c_end; 6411 uint8_t *src, *dst; 6412 int i; 6413 6414 if (!sec) { 6415 vset(type, VT_LOCAL|VT_LVAL, c); 6416 for (i = 1; i < nb_elems; i++) { 6417 vset(type, VT_LOCAL|VT_LVAL, c + elem_size * i); 6418 vswap(); 6419 vstore(); 6420 } 6421 vpop(); 6422 } else if (!NODATA_WANTED) { 6423 c_end = c + nb_elems * elem_size; 6424 if (c_end > sec->data_allocated) 6425 section_realloc(sec, c_end); 6426 src = sec->data + c; 6427 dst = src; 6428 for(i = 1; i < nb_elems; i++) { 6429 dst += elem_size; 6430 memcpy(dst, src, elem_size); 6431 } 6432 } 6433 } 6434 c += nb_elems * type_size(type, &align); 6435 if (c - corig > al) 6436 al = c - corig; 6437 return al; 6438 } 6439 6440 /* store a value or an expression directly in global data or in local array */ 6441 static void init_putv(CType *type, Section *sec, unsigned long c) 6442 { 6443 int bt; 6444 void *ptr; 6445 CType dtype; 6446 4872 6447 dtype = *type; 4873 6448 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */ 4874 6449 4875 6450 if (sec) { 6451 int size, align; 4876 6452 /* XXX: not portable */ 4877 6453 /* XXX: generate error if incorrect relocation */ 4878 6454 gen_assign_cast(&dtype); 4879 6455 bt = type->t & VT_BTYPE; 4880 /* we'll write at most 12 bytes */ 4881 if (c + 12 > sec->data_allocated) { 4882 section_realloc(sec, c + 12); 4883 } 6456 6457 if ((vtop->r & VT_SYM) 6458 && bt != VT_PTR 6459 && bt != VT_FUNC 6460 && (bt != (PTR_SIZE == 8 ? VT_LLONG : VT_INT) 6461 || (type->t & VT_BITFIELD)) 6462 && !((vtop->r & VT_CONST) && vtop->sym->v >= SYM_FIRST_ANOM) 6463 ) 6464 tcc_error("initializer element is not computable at load time"); 6465 6466 if (NODATA_WANTED) { 6467 vtop--; 6468 return; 6469 } 6470 6471 size = type_size(type, &align); 6472 section_reserve(sec, c + size); 4884 6473 ptr = sec->data + c; 6474 4885 6475 /* XXX: make code faster ? */ 4886 if (!(type->t & VT_BITFIELD)) { 4887 bit_pos = 0; 4888 bit_size = 32; 4889 bit_mask = -1LL; 4890 } else { 4891 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f; 4892 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f; 4893 bit_mask = (1LL << bit_size) - 1; 4894 } 4895 if ((vtop->r & VT_SYM) && 4896 (bt == VT_BYTE || 4897 bt == VT_SHORT || 4898 bt == VT_DOUBLE || 4899 bt == VT_LDOUBLE || 4900 bt == VT_LLONG || 4901 (bt == VT_INT && bit_size != 32))) 4902 tcc_error("initializer element is not computable at load time"); 4903 switch(bt) { 4904 case VT_BOOL: 4905 vtop->c.i = (vtop->c.i != 0); 4906 case VT_BYTE: 4907 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos; 4908 break; 4909 case VT_SHORT: 4910 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos; 4911 break; 4912 case VT_DOUBLE: 4913 *(double *)ptr = vtop->c.d; 4914 break; 4915 case VT_LDOUBLE: 4916 *(long double *)ptr = vtop->c.ld; 4917 break; 4918 case VT_LLONG: 4919 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos; 4920 break; 4921 default: 4922 if (vtop->r & VT_SYM) { 4923 greloc(sec, vtop->sym, c, R_DATA_PTR); 4924 } 4925 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos; 4926 break; 4927 } 6476 if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) && 6477 vtop->sym->v >= SYM_FIRST_ANOM && 6478 /* XXX This rejects compound literals like 6479 '(void *){ptr}'. The problem is that '&sym' is 6480 represented the same way, which would be ruled out 6481 by the SYM_FIRST_ANOM check above, but also '"string"' 6482 in 'char *p = "string"' is represented the same 6483 with the type being VT_PTR and the symbol being an 6484 anonymous one. That is, there's no difference in vtop 6485 between '(void *){x}' and '&(void *){x}'. Ignore 6486 pointer typed entities here. Hopefully no real code 6487 will every use compound literals with scalar type. */ 6488 (vtop->type.t & VT_BTYPE) != VT_PTR) { 6489 /* These come from compound literals, memcpy stuff over. */ 6490 Section *ssec; 6491 ElfSym *esym; 6492 ElfW_Rel *rel; 6493 esym = elfsym(vtop->sym); 6494 ssec = tcc_state->sections[esym->st_shndx]; 6495 memmove (ptr, ssec->data + esym->st_value, size); 6496 if (ssec->reloc) { 6497 /* We need to copy over all memory contents, and that 6498 includes relocations. Use the fact that relocs are 6499 created it order, so look from the end of relocs 6500 until we hit one before the copied region. */ 6501 int num_relocs = ssec->reloc->data_offset / sizeof(*rel); 6502 rel = (ElfW_Rel*)(ssec->reloc->data + ssec->reloc->data_offset); 6503 while (num_relocs--) { 6504 rel--; 6505 if (rel->r_offset >= esym->st_value + size) 6506 continue; 6507 if (rel->r_offset < esym->st_value) 6508 break; 6509 /* Note: if the same fields are initialized multiple 6510 times (possible with designators) then we possibly 6511 add multiple relocations for the same offset here. 6512 That would lead to wrong code, the last reloc needs 6513 to win. We clean this up later after the whole 6514 initializer is parsed. */ 6515 put_elf_reloca(symtab_section, sec, 6516 c + rel->r_offset - esym->st_value, 6517 ELFW(R_TYPE)(rel->r_info), 6518 ELFW(R_SYM)(rel->r_info), 6519 #if PTR_SIZE == 8 6520 rel->r_addend 6521 #else 6522 0 6523 #endif 6524 ); 6525 } 6526 } 6527 } else { 6528 if (type->t & VT_BITFIELD) { 6529 int bit_pos, bit_size, bits, n; 6530 unsigned char *p, v, m; 6531 bit_pos = BIT_POS(vtop->type.t); 6532 bit_size = BIT_SIZE(vtop->type.t); 6533 p = (unsigned char*)ptr + (bit_pos >> 3); 6534 bit_pos &= 7, bits = 0; 6535 while (bit_size) { 6536 n = 8 - bit_pos; 6537 if (n > bit_size) 6538 n = bit_size; 6539 v = vtop->c.i >> bits << bit_pos; 6540 m = ((1 << n) - 1) << bit_pos; 6541 *p = (*p & ~m) | (v & m); 6542 bits += n, bit_size -= n, bit_pos = 0, ++p; 6543 } 6544 } else 6545 switch(bt) { 6546 /* XXX: when cross-compiling we assume that each type has the 6547 same representation on host and target, which is likely to 6548 be wrong in the case of long double */ 6549 case VT_BOOL: 6550 vtop->c.i = vtop->c.i != 0; 6551 case VT_BYTE: 6552 *(char *)ptr |= vtop->c.i; 6553 break; 6554 case VT_SHORT: 6555 *(short *)ptr |= vtop->c.i; 6556 break; 6557 case VT_FLOAT: 6558 *(float*)ptr = vtop->c.f; 6559 break; 6560 case VT_DOUBLE: 6561 *(double *)ptr = vtop->c.d; 6562 break; 6563 case VT_LDOUBLE: 6564 #if defined TCC_IS_NATIVE_387 6565 if (sizeof (long double) >= 10) /* zero pad ten-byte LD */ 6566 memcpy(ptr, &vtop->c.ld, 10); 6567 #ifdef __TINYC__ 6568 else if (sizeof (long double) == sizeof (double)) 6569 __asm__("fldl %1\nfstpt %0\n" : "=m" (*ptr) : "m" (vtop->c.ld)); 6570 #endif 6571 else if (vtop->c.ld == 0.0) 6572 ; 6573 else 6574 #endif 6575 if (sizeof(long double) == LDOUBLE_SIZE) 6576 *(long double*)ptr = vtop->c.ld; 6577 else if (sizeof(double) == LDOUBLE_SIZE) 6578 *(double *)ptr = (double)vtop->c.ld; 6579 else 6580 tcc_error("can't cross compile long double constants"); 6581 break; 6582 #if PTR_SIZE != 8 6583 case VT_LLONG: 6584 *(long long *)ptr |= vtop->c.i; 6585 break; 6586 #else 6587 case VT_LLONG: 6588 #endif 6589 case VT_PTR: 6590 { 6591 addr_t val = vtop->c.i; 6592 #if PTR_SIZE == 8 6593 if (vtop->r & VT_SYM) 6594 greloca(sec, vtop->sym, c, R_DATA_PTR, val); 6595 else 6596 *(addr_t *)ptr |= val; 6597 #else 6598 if (vtop->r & VT_SYM) 6599 greloc(sec, vtop->sym, c, R_DATA_PTR); 6600 *(addr_t *)ptr |= val; 6601 #endif 6602 break; 6603 } 6604 default: 6605 { 6606 int val = vtop->c.i; 6607 #if PTR_SIZE == 8 6608 if (vtop->r & VT_SYM) 6609 greloca(sec, vtop->sym, c, R_DATA_PTR, val); 6610 else 6611 *(int *)ptr |= val; 6612 #else 6613 if (vtop->r & VT_SYM) 6614 greloc(sec, vtop->sym, c, R_DATA_PTR); 6615 *(int *)ptr |= val; 6616 #endif 6617 break; 6618 } 6619 } 6620 } 4928 6621 vtop--; 4929 6622 } else { … … 4932 6625 vstore(); 4933 6626 vpop(); 4934 }4935 }4936 4937 /* put zeros for variable based init */4938 static void init_putz(CType *t, Section *sec, unsigned long c, int size)4939 {4940 if (sec) {4941 /* nothing to do because globals are already set to zero */4942 } else {4943 vpush_global_sym(&func_old_type, TOK_memset);4944 vseti(VT_LOCAL, c);4945 vpushi(0);4946 vpushi(size);4947 gfunc_call(3);4948 6627 } 4949 6628 } … … 4957 6636 int first, int size_only) 4958 6637 { 4959 int index, array_length, n, no_oblock, nb, parlevel, parlevel1, i; 4960 int size1, align1, expr_type; 6638 int len, n, no_oblock, nb, i; 6639 int size1, align1; 6640 int have_elem; 4961 6641 Sym *s, *f; 6642 Sym indexsym; 4962 6643 CType *t1; 4963 6644 4964 if (type->t & VT_VLA) { 4965 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 4966 int a; 4967 CValue retcval; 4968 4969 vpush_global_sym(&func_old_type, TOK_alloca); 4970 vla_runtime_type_size(type, &a); 4971 gfunc_call(1); 4972 4973 /* return value */ 4974 retcval.i = 0; 4975 vsetc(type, REG_IRET, &retcval); 4976 vset(type, VT_LOCAL|VT_LVAL, c); 4977 vswap(); 4978 vstore(); 4979 vpop(); 4980 #else 4981 tcc_error("variable length arrays unsupported for this target"); 4982 #endif 6645 /* If we currently are at an '}' or ',' we have read an initializer 6646 element in one of our callers, and not yet consumed it. */ 6647 have_elem = tok == '}' || tok == ','; 6648 if (!have_elem && tok != '{' && 6649 /* In case of strings we have special handling for arrays, so 6650 don't consume them as initializer value (which would commit them 6651 to some anonymous symbol). */ 6652 tok != TOK_LSTR && tok != TOK_STR && 6653 !size_only) { 6654 parse_init_elem(!sec ? EXPR_ANY : EXPR_CONST); 6655 have_elem = 1; 6656 } 6657 6658 if (have_elem && 6659 !(type->t & VT_ARRAY) && 6660 /* Use i_c_parameter_t, to strip toplevel qualifiers. 6661 The source type might have VT_CONSTANT set, which is 6662 of course assignable to non-const elements. */ 6663 is_compatible_unqualified_types(type, &vtop->type)) { 6664 init_putv(type, sec, c); 4983 6665 } else if (type->t & VT_ARRAY) { 4984 6666 s = type->ref; 4985 6667 n = s->c; 4986 array_length = 0;4987 6668 t1 = pointed_type(type); 4988 6669 size1 = type_size(t1, &align1); … … 5007 6688 #endif 5008 6689 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) { 6690 len = 0; 5009 6691 while (tok == TOK_STR || tok == TOK_LSTR) { 5010 6692 int cstr_len, ch; 5011 CString *cstr; 5012 5013 cstr = tokc.cstr; 6693 5014 6694 /* compute maximum number of chars wanted */ 5015 6695 if (tok == TOK_STR) 5016 cstr_len = cstr->size;6696 cstr_len = tokc.str.size; 5017 6697 else 5018 cstr_len = cstr->size / sizeof(nwchar_t);6698 cstr_len = tokc.str.size / sizeof(nwchar_t); 5019 6699 cstr_len--; 5020 6700 nb = cstr_len; 5021 if (n >= 0 && nb > (n - array_length))5022 nb = n - array_length;6701 if (n >= 0 && nb > (n - len)) 6702 nb = n - len; 5023 6703 if (!size_only) { 5024 6704 if (cstr_len > nb) … … 5028 6708 specifically */ 5029 6709 if (sec && tok == TOK_STR && size1 == 1) { 5030 memcpy(sec->data + c + array_length, cstr->data, nb); 6710 if (!NODATA_WANTED) 6711 memcpy(sec->data + c + len, tokc.str.data, nb); 5031 6712 } else { 5032 6713 for(i=0;i<nb;i++) { 5033 6714 if (tok == TOK_STR) 5034 ch = ((unsigned char *) cstr->data)[i];6715 ch = ((unsigned char *)tokc.str.data)[i]; 5035 6716 else 5036 ch = ((nwchar_t *) cstr->data)[i];5037 init_putv(t1, sec, c + (array_length + i) * size1, 5038 ch, EXPR_VAL);6717 ch = ((nwchar_t *)tokc.str.data)[i]; 6718 vpushi(ch); 6719 init_putv(t1, sec, c + (len + i) * size1); 5039 6720 } 5040 6721 } 5041 6722 } 5042 array_length+= nb;6723 len += nb; 5043 6724 next(); 5044 6725 } 5045 6726 /* only add trailing zero if enough storage (no 5046 6727 warning in this case since it is standard) */ 5047 if (n < 0 || array_length< n) {6728 if (n < 0 || len < n) { 5048 6729 if (!size_only) { 5049 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL); 6730 vpushi(0); 6731 init_putv(t1, sec, c + (len * size1)); 5050 6732 } 5051 array_length++; 5052 } 6733 len++; 6734 } 6735 len *= size1; 5053 6736 } else { 5054 index = 0; 5055 while (tok != '}') { 5056 decl_designator(type, sec, c, &index, NULL, size_only); 5057 if (n >= 0 && index >= n) 5058 tcc_error("index too large"); 5059 /* must put zero in holes (note that doing it that way 5060 ensures that it even works with designators) */ 5061 if (!size_only && array_length < index) { 5062 init_putz(t1, sec, c + array_length * size1, 5063 (index - array_length) * size1); 5064 } 5065 index++; 5066 if (index > array_length) 5067 array_length = index; 5068 /* special test for multi dimensional arrays (may not 5069 be strictly correct if designators are used at the 5070 same time) */ 5071 if (index >= n && no_oblock) 5072 break; 5073 if (tok == '}') 5074 break; 5075 skip(','); 5076 } 5077 } 6737 indexsym.c = 0; 6738 f = &indexsym; 6739 6740 do_init_list: 6741 len = 0; 6742 while (tok != '}' || have_elem) { 6743 len = decl_designator(type, sec, c, &f, size_only, len); 6744 have_elem = 0; 6745 if (type->t & VT_ARRAY) { 6746 ++indexsym.c; 6747 /* special test for multi dimensional arrays (may not 6748 be strictly correct if designators are used at the 6749 same time) */ 6750 if (no_oblock && len >= n*size1) 6751 break; 6752 } else { 6753 if (s->type.t == VT_UNION) 6754 f = NULL; 6755 else 6756 f = f->next; 6757 if (no_oblock && f == NULL) 6758 break; 6759 } 6760 6761 if (tok == '}') 6762 break; 6763 skip(','); 6764 } 6765 } 6766 /* put zeros at the end */ 6767 if (!size_only && len < n*size1) 6768 init_putz(sec, c + len, n*size1 - len); 5078 6769 if (!no_oblock) 5079 6770 skip('}'); 5080 /* put zeros at the end */ 5081 if (!size_only && n >= 0 && array_length < n) { 5082 init_putz(t1, sec, c + array_length * size1, 5083 (n - array_length) * size1); 5084 } 5085 /* patch type size if needed */ 6771 /* patch type size if needed, which happens only for array types */ 5086 6772 if (n < 0) 5087 s->c = array_length; 5088 } else if ((type->t & VT_BTYPE) == VT_STRUCT && 5089 (sec || !first || tok == '{')) { 5090 int par_count; 5091 5092 /* NOTE: the previous test is a specific case for automatic 5093 struct/union init */ 5094 /* XXX: union needs only one init */ 5095 5096 /* XXX: this test is incorrect for local initializers 5097 beginning with ( without {. It would be much more difficult 5098 to do it correctly (ideally, the expression parser should 5099 be used in all cases) */ 5100 par_count = 0; 5101 if (tok == '(') { 5102 AttributeDef ad1; 5103 CType type1; 5104 next(); 5105 while (tok == '(') { 5106 par_count++; 5107 next(); 5108 } 5109 if (!parse_btype(&type1, &ad1)) 5110 expect("cast"); 5111 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); 5112 #if 0 5113 if (!is_assignable_types(type, &type1)) 5114 tcc_error("invalid type for cast"); 5115 #endif 5116 skip(')'); 5117 } 6773 s->c = size1 == 1 ? len : ((len + size1 - 1)/size1); 6774 } else if ((type->t & VT_BTYPE) == VT_STRUCT) { 6775 size1 = 1; 5118 6776 no_oblock = 1; 5119 6777 if (first || tok == '{') { … … 5123 6781 s = type->ref; 5124 6782 f = s->next; 5125 array_length = 0;5126 index = 0;5127 6783 n = s->c; 5128 while (tok != '}') { 5129 decl_designator(type, sec, c, NULL, &f, size_only); 5130 index = f->c; 5131 if (!size_only && array_length < index) { 5132 init_putz(type, sec, c + array_length, 5133 index - array_length); 5134 } 5135 index = index + type_size(&f->type, &align1); 5136 if (index > array_length) 5137 array_length = index; 5138 5139 /* gr: skip fields from same union - ugly. */ 5140 while (f->next) { 5141 ///printf("index: %2d %08x -- %2d %08x\n", f->c, f->type.t, f->next->c, f->next->type.t); 5142 /* test for same offset */ 5143 if (f->next->c != f->c) 5144 break; 5145 /* if yes, test for bitfield shift */ 5146 if ((f->type.t & VT_BITFIELD) && (f->next->type.t & VT_BITFIELD)) { 5147 int bit_pos_1 = (f->type.t >> VT_STRUCT_SHIFT) & 0x3f; 5148 int bit_pos_2 = (f->next->type.t >> VT_STRUCT_SHIFT) & 0x3f; 5149 //printf("bitfield %d %d\n", bit_pos_1, bit_pos_2); 5150 if (bit_pos_1 != bit_pos_2) 5151 break; 5152 } 5153 f = f->next; 5154 } 5155 5156 f = f->next; 5157 if (no_oblock && f == NULL) 5158 break; 5159 if (tok == '}') 5160 break; 5161 skip(','); 5162 } 5163 /* put zeros at the end */ 5164 if (!size_only && array_length < n) { 5165 init_putz(type, sec, c + array_length, 5166 n - array_length); 5167 } 5168 if (!no_oblock) 5169 skip('}'); 5170 while (par_count) { 5171 skip(')'); 5172 par_count--; 5173 } 6784 goto do_init_list; 5174 6785 } else if (tok == '{') { 5175 6786 next(); … … 5177 6788 skip('}'); 5178 6789 } else if (size_only) { 6790 /* If we supported only ISO C we wouldn't have to accept calling 6791 this on anything than an array size_only==1 (and even then 6792 only on the outermost level, so no recursion would be needed), 6793 because initializing a flex array member isn't supported. 6794 But GNU C supports it, so we need to recurse even into 6795 subfields of structs and arrays when size_only is set. */ 5179 6796 /* just skip expression */ 5180 parlevel = parlevel1 = 0; 5181 while ((parlevel > 0 || parlevel1 > 0 || 5182 (tok != '}' && tok != ',')) && tok != -1) { 5183 if (tok == '(') 5184 parlevel++; 5185 else if (tok == ')') 5186 parlevel--; 5187 else if (tok == '{') 5188 parlevel1++; 5189 else if (tok == '}') 5190 parlevel1--; 5191 next(); 5192 } 6797 skip_or_save_block(NULL); 5193 6798 } else { 5194 /* currently, we always use constant expression for globals 5195 (may change for scripting case) */ 5196 expr_type = EXPR_CONST; 5197 if (!sec) 5198 expr_type = EXPR_ANY; 5199 init_putv(type, sec, c, 0, expr_type); 6799 if (!have_elem) { 6800 /* This should happen only when we haven't parsed 6801 the init element above for fear of committing a 6802 string constant to memory too early. */ 6803 if (tok != TOK_STR && tok != TOK_LSTR) 6804 expect("string constant"); 6805 parse_init_elem(!sec ? EXPR_ANY : EXPR_CONST); 6806 } 6807 init_putv(type, sec, c); 5200 6808 } 5201 6809 } … … 5204 6812 allocate space in local or global data space ('r' is either 5205 6813 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated 5206 variable 'v' with an associated name represented by 'asm_label' of 5207 scope 'scope' is declared before initializers are parsed. If 'v' is 5208 zero, then a reference to the new object is put in the value stack. 5209 If 'has_init' is 2, a special parsing is done to handle string 5210 constants. */ 6814 variable 'v' of scope 'scope' is declared before initializers 6815 are parsed. If 'v' is zero, then a reference to the new object 6816 is put in the value stack. If 'has_init' is 2, a special parsing 6817 is done to handle string constants. */ 5211 6818 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, 5212 int has_init, int v, char *asm_label, 5213 int scope) 5214 { 5215 int size, align, addr, data_offset; 5216 int level; 5217 ParseState saved_parse_state = {0}; 5218 TokenString init_str; 6819 int has_init, int v, int scope) 6820 { 6821 int size, align, addr; 6822 TokenString *init_str = NULL; 6823 5219 6824 Section *sec; 5220 6825 Sym *flexible_array; 6826 Sym *sym = NULL; 6827 int saved_nocode_wanted = nocode_wanted; 6828 #ifdef CONFIG_TCC_BCHECK 6829 int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED; 6830 #endif 6831 6832 if (type->t & VT_STATIC) 6833 nocode_wanted |= NODATA_WANTED ? 0x40000000 : 0x80000000; 5221 6834 5222 6835 flexible_array = NULL; 5223 6836 if ((type->t & VT_BTYPE) == VT_STRUCT) { 5224 Sym *field; 5225 field = type->ref; 5226 while (field && field->next) 5227 field = field->next; 5228 if (field->type.t & VT_ARRAY && field->type.ref->c < 0) 5229 flexible_array = field; 6837 Sym *field = type->ref->next; 6838 if (field) { 6839 while (field->next) 6840 field = field->next; 6841 if (field->type.t & VT_ARRAY && field->type.ref->c < 0) 6842 flexible_array = field; 6843 } 5230 6844 } 5231 6845 … … 5237 6851 literals). It also simplifies local 5238 6852 initializers handling */ 5239 tok_str_new(&init_str);5240 6853 if (size < 0 || (flexible_array && has_init)) { 5241 6854 if (!has_init) … … 5243 6856 /* get all init string */ 5244 6857 if (has_init == 2) { 6858 init_str = tok_str_alloc(); 5245 6859 /* only get strings */ 5246 6860 while (tok == TOK_STR || tok == TOK_LSTR) { 5247 tok_str_add_tok( &init_str);6861 tok_str_add_tok(init_str); 5248 6862 next(); 5249 6863 } 6864 tok_str_add(init_str, -1); 6865 tok_str_add(init_str, 0); 5250 6866 } else { 5251 level = 0; 5252 while (level > 0 || (tok != ',' && tok != ';')) { 5253 if (tok < 0) 5254 tcc_error("unexpected end of file in initializer"); 5255 tok_str_add_tok(&init_str); 5256 if (tok == '{') 5257 level++; 5258 else if (tok == '}') { 5259 level--; 5260 if (level <= 0) { 5261 next(); 5262 break; 5263 } 5264 } 5265 next(); 5266 } 5267 } 5268 tok_str_add(&init_str, -1); 5269 tok_str_add(&init_str, 0); 5270 6867 skip_or_save_block(&init_str); 6868 } 6869 unget_tok(0); 6870 5271 6871 /* compute size */ 5272 save_parse_state(&saved_parse_state); 5273 5274 macro_ptr = init_str.str; 6872 begin_macro(init_str, 1); 5275 6873 next(); 5276 6874 decl_initializer(type, NULL, 0, 1, 1); 5277 6875 /* prepare second initializer parsing */ 5278 macro_ptr = init_str .str;6876 macro_ptr = init_str->str; 5279 6877 next(); 5280 6878 … … 5284 6882 tcc_error("unknown type size"); 5285 6883 } 5286 if (flexible_array) 5287 size += flexible_array->type.ref->c * pointed_size(&flexible_array->type); 6884 /* If there's a flex member and it was used in the initializer 6885 adjust size. */ 6886 if (flexible_array && 6887 flexible_array->type.ref->c > 0) 6888 size += flexible_array->type.ref->c 6889 * pointed_size(&flexible_array->type); 5288 6890 /* take into account specified alignment if bigger */ 5289 if (ad->aligned) { 5290 if (ad->aligned > align) 5291 align = ad->aligned; 5292 } else if (ad->packed) { 6891 if (ad->a.aligned) { 6892 int speca = 1 << (ad->a.aligned - 1); 6893 if (speca > align) 6894 align = speca; 6895 } else if (ad->a.packed) { 5293 6896 align = 1; 5294 6897 } 6898 6899 if (NODATA_WANTED) 6900 size = 0, align = 1; 6901 5295 6902 if ((r & VT_VALMASK) == VT_LOCAL) { 5296 6903 sec = NULL; 5297 6904 #ifdef CONFIG_TCC_BCHECK 5298 if ( tcc_state->do_bounds_check && (type->t & VT_ARRAY)) {6905 if (bcheck && (type->t & VT_ARRAY)) { 5299 6906 loc--; 5300 6907 } … … 5306 6913 /* XXX: currently, since we do only one pass, we cannot track 5307 6914 '&' operators, so we add only arrays */ 5308 if ( tcc_state->do_bounds_check && (type->t & VT_ARRAY)) {5309 unsigned long*bounds_ptr;6915 if (bcheck && (type->t & VT_ARRAY)) { 6916 addr_t *bounds_ptr; 5310 6917 /* add padding between regions */ 5311 6918 loc--; 5312 6919 /* then add local bound info */ 5313 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof( unsigned long));6920 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(addr_t)); 5314 6921 bounds_ptr[0] = addr; 5315 6922 bounds_ptr[1] = size; … … 5318 6925 if (v) { 5319 6926 /* local variable */ 5320 sym_push(v, type, r, addr); 6927 #ifdef CONFIG_TCC_ASM 6928 if (ad->asm_label) { 6929 int reg = asm_parse_regvar(ad->asm_label); 6930 if (reg >= 0) 6931 r = (r & ~VT_VALMASK) | reg; 6932 } 6933 #endif 6934 sym = sym_push(v, type, r, addr); 6935 sym->a = ad->a; 5321 6936 } else { 5322 6937 /* push local reference */ … … 5324 6939 } 5325 6940 } else { 5326 Sym *sym;5327 5328 sym = NULL;5329 6941 if (v && scope == VT_CONST) { 5330 6942 /* see if the symbol was already defined */ 5331 6943 sym = sym_find(v); 5332 6944 if (sym) { 5333 if (!is_compatible_types(&sym->type, type)) 5334 tcc_error("incompatible types for redefinition of '%s'", 5335 get_tok_str(v, NULL)); 5336 if (sym->type.t & VT_EXTERN) { 5337 /* if the variable is extern, it was not allocated */ 5338 sym->type.t &= ~VT_EXTERN; 5339 /* set array size if it was ommited in extern 5340 declaration */ 5341 if ((sym->type.t & VT_ARRAY) && 5342 sym->type.ref->c < 0 && 5343 type->ref->c >= 0) 5344 sym->type.ref->c = type->ref->c; 5345 } else { 5346 /* we accept several definitions of the same 5347 global variable. this is tricky, because we 5348 must play with the SHN_COMMON type of the symbol */ 5349 /* XXX: should check if the variable was already 5350 initialized. It is incorrect to initialized it 5351 twice */ 5352 /* no init data, we won't add more to the symbol */ 5353 if (!has_init) 5354 goto no_alloc; 5355 } 6945 patch_storage(sym, ad, type); 6946 /* we accept several definitions of the same global variable. */ 6947 if (!has_init && sym->c && elfsym(sym)->st_shndx != SHN_UNDEF) 6948 goto no_alloc; 5356 6949 } 5357 6950 } … … 5365 6958 sec = bss_section; 5366 6959 } 6960 5367 6961 if (sec) { 5368 data_offset = sec->data_offset; 5369 data_offset = (data_offset + align - 1) & -align; 5370 addr = data_offset; 5371 /* very important to increment global pointer at this time 5372 because initializers themselves can create new initializers */ 5373 data_offset += size; 6962 addr = section_add(sec, size, align); 5374 6963 #ifdef CONFIG_TCC_BCHECK 5375 6964 /* add padding if bound check */ 5376 if (tcc_state->do_bounds_check) 5377 data_offset++; 5378 #endif 5379 sec->data_offset = data_offset; 5380 /* allocate section space to put the data */ 5381 if (sec->sh_type != SHT_NOBITS && 5382 data_offset > sec->data_allocated) 5383 section_realloc(sec, data_offset); 5384 /* align section if needed */ 5385 if (align > sec->sh_addralign) 5386 sec->sh_addralign = align; 6965 if (bcheck) 6966 section_add(sec, 1, 1); 6967 #endif 5387 6968 } else { 5388 addr = 0; /* avoid warning */ 6969 addr = align; /* SHN_COMMON is special, symbol value is align */ 6970 sec = common_section; 5389 6971 } 5390 6972 5391 6973 if (v) { 5392 if ( scope != VT_CONST ||!sym) {6974 if (!sym) { 5393 6975 sym = sym_push(v, type, r | VT_SYM, 0); 5394 sym->asm_label = asm_label; 5395 } 6976 patch_storage(sym, ad, NULL); 6977 } 6978 /* Local statics have a scope until now (for 6979 warnings), remove it here. */ 6980 sym->sym_scope = 0; 5396 6981 /* update symbol definition */ 5397 if (sec) { 5398 put_extern_sym(sym, sec, addr, size); 5399 } else { 5400 ElfW(Sym) *esym; 5401 /* put a common area */ 5402 put_extern_sym(sym, NULL, align, size); 5403 /* XXX: find a nicer way */ 5404 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; 5405 esym->st_shndx = SHN_COMMON; 5406 } 6982 put_extern_sym(sym, sec, addr, size); 5407 6983 } else { 5408 CValue cval;5409 5410 6984 /* push global reference */ 5411 6985 sym = get_sym_ref(type, sec, addr, size); 5412 cval.ul = 0; 5413 vsetc(type, VT_CONST | VT_SYM, &cval); 5414 vtop->sym = sym; 5415 } 5416 /* patch symbol weakness */ 5417 if (type->t & VT_WEAK) 5418 weaken_symbol(sym); 6986 vpushsym(type, sym); 6987 vtop->r |= r; 6988 } 6989 5419 6990 #ifdef CONFIG_TCC_BCHECK 5420 6991 /* handles bounds now because the symbol must be defined 5421 6992 before for the relocation */ 5422 if ( tcc_state->do_bounds_check) {5423 unsigned long*bounds_ptr;5424 5425 greloc (bounds_section, sym, bounds_section->data_offset, R_DATA_PTR);6993 if (bcheck) { 6994 addr_t *bounds_ptr; 6995 6996 greloca(bounds_section, sym, bounds_section->data_offset, R_DATA_PTR, 0); 5426 6997 /* then add global bound info */ 5427 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof( long));6998 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(addr_t)); 5428 6999 bounds_ptr[0] = 0; /* relocated */ 5429 7000 bounds_ptr[1] = size; … … 5431 7002 #endif 5432 7003 } 5433 if (has_init || (type->t & VT_VLA)) { 7004 7005 if (type->t & VT_VLA) { 7006 int a; 7007 7008 if (NODATA_WANTED) 7009 goto no_alloc; 7010 7011 /* save current stack pointer */ 7012 if (vlas_in_scope == 0) { 7013 if (vla_sp_root_loc == -1) 7014 vla_sp_root_loc = (loc -= PTR_SIZE); 7015 gen_vla_sp_save(vla_sp_root_loc); 7016 } 7017 7018 vla_runtime_type_size(type, &a); 7019 gen_vla_alloc(type, a); 7020 #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64 7021 /* on _WIN64, because of the function args scratch area, the 7022 result of alloca differs from RSP and is returned in RAX. */ 7023 gen_vla_result(addr), addr = (loc -= PTR_SIZE); 7024 #endif 7025 gen_vla_sp_save(addr); 7026 vla_sp_loc = addr; 7027 vlas_in_scope++; 7028 7029 } else if (has_init) { 7030 size_t oldreloc_offset = 0; 7031 if (sec && sec->reloc) 7032 oldreloc_offset = sec->reloc->data_offset; 5434 7033 decl_initializer(type, sec, addr, 1, 0); 5435 /* restore parse state if needed */ 5436 if (init_str.str) { 5437 tok_str_free(init_str.str); 5438 restore_parse_state(&saved_parse_state); 5439 } 7034 if (sec && sec->reloc) 7035 squeeze_multi_relocs(sec, oldreloc_offset); 5440 7036 /* patch flexible array member size back to -1, */ 5441 7037 /* for possible subsequent similar declarations */ … … 5443 7039 flexible_array->type.ref->c = -1; 5444 7040 } 5445 no_alloc: ; 5446 } 5447 5448 static void put_func_debug(Sym *sym) 5449 { 5450 char buf[512]; 5451 5452 /* stabs info */ 5453 /* XXX: we put here a dummy type */ 5454 snprintf(buf, sizeof(buf), "%s:%c1", 5455 funcname, sym->type.t & VT_STATIC ? 'f' : 'F'); 5456 put_stabs_r(buf, N_FUN, 0, file->line_num, 0, 5457 cur_text_section, sym->c); 5458 /* //gr gdb wants a line at the function */ 5459 put_stabn(N_SLINE, 0, file->line_num, 0); 5460 last_ind = 0; 5461 last_line_num = 0; 5462 } 5463 5464 /* parse an old style function declaration list */ 5465 /* XXX: check multiple parameter */ 5466 static void func_decl_list(Sym *func_sym) 5467 { 5468 AttributeDef ad; 5469 int v; 5470 Sym *s; 5471 CType btype, type; 5472 5473 /* parse each declaration */ 5474 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF && 5475 tok != TOK_ASM1 && tok != TOK_ASM2 && tok != TOK_ASM3) { 5476 if (!parse_btype(&btype, &ad)) 5477 expect("declaration list"); 5478 if (((btype.t & VT_BTYPE) == VT_ENUM || 5479 (btype.t & VT_BTYPE) == VT_STRUCT) && 5480 tok == ';') { 5481 /* we accept no variable after */ 5482 } else { 5483 for(;;) { 5484 type = btype; 5485 type_decl(&type, &ad, &v, TYPE_DIRECT); 5486 /* find parameter in function parameter list */ 5487 s = func_sym->next; 5488 while (s != NULL) { 5489 if ((s->v & ~SYM_FIELD) == v) 5490 goto found; 5491 s = s->next; 5492 } 5493 tcc_error("declaration for parameter '%s' but no such parameter", 5494 get_tok_str(v, NULL)); 5495 found: 5496 /* check that no storage specifier except 'register' was given */ 5497 if (type.t & VT_STORAGE) 5498 tcc_error("storage class specified for '%s'", get_tok_str(v, NULL)); 5499 convert_parameter_type(&type); 5500 /* we can add the type (NOTE: it could be local to the function) */ 5501 s->type = type; 5502 /* accept other parameters */ 5503 if (tok == ',') 5504 next(); 5505 else 5506 break; 5507 } 5508 } 5509 skip(';'); 5510 } 7041 7042 no_alloc: 7043 /* restore parse state if needed */ 7044 if (init_str) { 7045 end_macro(); 7046 next(); 7047 } 7048 7049 nocode_wanted = saved_nocode_wanted; 5511 7050 } 5512 7051 … … 5515 7054 static void gen_function(Sym *sym) 5516 7055 { 5517 int saved_nocode_wanted = nocode_wanted;5518 7056 nocode_wanted = 0; 5519 7057 ind = cur_text_section->data_offset; … … 5522 7060 funcname = get_tok_str(sym->v, NULL); 5523 7061 func_ind = ind; 7062 /* Initialize VLA state */ 7063 vla_sp_loc = -1; 7064 vla_sp_root_loc = -1; 5524 7065 /* put debug symbol */ 5525 if (tcc_state->do_debug) 5526 put_func_debug(sym); 7066 tcc_debug_funcstart(tcc_state, sym); 5527 7067 /* push a dummy symbol to enable local sym storage */ 5528 7068 sym_push2(&local_stack, SYM_FIELD, 0, 0); 7069 local_scope = 1; /* for function parameters */ 5529 7070 gfunc_prolog(&sym->type); 7071 local_scope = 0; 5530 7072 rsym = 0; 5531 block(NULL, NULL, NULL, NULL, 0, 0); 7073 block(NULL, NULL, 0); 7074 nocode_wanted = 0; 5532 7075 gsym(rsym); 5533 7076 gfunc_epilog(); 5534 7077 cur_text_section->data_offset = ind; 5535 label_pop(&global_label_stack, NULL );7078 label_pop(&global_label_stack, NULL, 0); 5536 7079 /* reset local stack */ 5537 scope_stack_bottom = NULL;5538 sym_pop(&local_stack, NULL );7080 local_scope = 0; 7081 sym_pop(&local_stack, NULL, 0); 5539 7082 /* end of function */ 5540 7083 /* patch symbol size */ 5541 ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size = 5542 ind - func_ind; 5543 /* patch symbol weakness (this definition overrules any prototype) */ 5544 if (sym->type.t & VT_WEAK) 5545 weaken_symbol(sym); 5546 if (tcc_state->do_debug) { 5547 put_stabn(N_FUN, 0, 0, ind - func_ind); 5548 } 7084 elfsym(sym)->st_size = ind - func_ind; 7085 tcc_debug_funcend(tcc_state, ind - func_ind); 5549 7086 /* It's better to crash than to generate wrong code */ 5550 7087 cur_text_section = NULL; 5551 7088 funcname = ""; /* for safety */ 5552 7089 func_vt.t = VT_VOID; /* for safety */ 7090 func_var = 0; /* for safety */ 5553 7091 ind = 0; /* for safety */ 5554 nocode_wanted = saved_nocode_wanted; 5555 } 5556 5557 ST_FUNC void gen_inline_functions(void) 7092 nocode_wanted = 0x80000000; 7093 check_vstack(); 7094 } 7095 7096 static void gen_inline_functions(TCCState *s) 5558 7097 { 5559 7098 Sym *sym; 5560 int *str, inline_generated, i;7099 int inline_generated, i, ln; 5561 7100 struct InlineFunc *fn; 5562 7101 7102 ln = file->line_num; 5563 7103 /* iterate while inline function are referenced */ 5564 for(;;){7104 do { 5565 7105 inline_generated = 0; 5566 for (i = 0; i < tcc_state->nb_inline_fns; ++i) {5567 fn = tcc_state->inline_fns[i];7106 for (i = 0; i < s->nb_inline_fns; ++i) { 7107 fn = s->inline_fns[i]; 5568 7108 sym = fn->sym; 5569 7109 if (sym && sym->c) { 5570 7110 /* the function was used: generate its code and 5571 7111 convert it to a normal function */ 5572 str = fn->token_str;5573 7112 fn->sym = NULL; 5574 7113 if (file) 5575 7114 pstrcpy(file->filename, sizeof file->filename, fn->filename); 5576 sym->r = VT_SYM | VT_CONST;5577 7115 sym->type.t &= ~VT_INLINE; 5578 7116 5579 macro_ptr = str;7117 begin_macro(fn->func_str, 1); 5580 7118 next(); 5581 7119 cur_text_section = text_section; 5582 7120 gen_function(sym); 5583 macro_ptr = NULL; /* fail safe */7121 end_macro(); 5584 7122 5585 7123 inline_generated = 1; 5586 7124 } 5587 7125 } 5588 if (!inline_generated) 5589 break; 5590 } 5591 for (i = 0; i < tcc_state->nb_inline_fns; ++i) { 5592 fn = tcc_state->inline_fns[i]; 5593 str = fn->token_str; 5594 tok_str_free(str); 5595 } 5596 dynarray_reset(&tcc_state->inline_fns, &tcc_state->nb_inline_fns); 5597 } 5598 5599 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */ 5600 static int decl0(int l, int is_for_loop_init) 7126 } while (inline_generated); 7127 file->line_num = ln; 7128 } 7129 7130 ST_FUNC void free_inline_functions(TCCState *s) 7131 { 7132 int i; 7133 /* free tokens of unused inline functions */ 7134 for (i = 0; i < s->nb_inline_fns; ++i) { 7135 struct InlineFunc *fn = s->inline_fns[i]; 7136 if (fn->sym) 7137 tok_str_free(fn->func_str); 7138 } 7139 dynarray_reset(&s->inline_fns, &s->nb_inline_fns); 7140 } 7141 7142 /* 'l' is VT_LOCAL or VT_CONST to define default storage type, or VT_CMP 7143 if parsing old style parameter decl list (and FUNC_SYM is set then) */ 7144 static int decl0(int l, int is_for_loop_init, Sym *func_sym) 5601 7145 { 5602 7146 int v, has_init, r; … … 5609 7153 if (is_for_loop_init) 5610 7154 return 0; 5611 /* skip redundant ';' */ 5612 /* XXX: find more elegant solution */ 5613 if (tok == ';') { 7155 /* skip redundant ';' if not in old parameter decl scope */ 7156 if (tok == ';' && l != VT_CMP) { 5614 7157 next(); 5615 7158 continue; 5616 7159 } 5617 if (l == VT_CONST && 5618 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) { 7160 if (l != VT_CONST) 7161 break; 7162 if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) { 5619 7163 /* global asm block */ 5620 7164 asm_global_instr(); 5621 7165 continue; 5622 7166 } 5623 /* special test for old K&R protos without explicit int 5624 type. Only accepted when defining global data */ 5625 if (l == VT_LOCAL || tok < TOK_DEFINE) 7167 if (tok >= TOK_UIDENT) { 7168 /* special test for old K&R protos without explicit int 7169 type. Only accepted when defining global data */ 7170 btype.t = VT_INT; 7171 } else { 7172 if (tok != TOK_EOF) 7173 expect("declaration"); 5626 7174 break; 5627 btype.t = VT_INT; 5628 } 5629 if (((btype.t & VT_BTYPE) == VT_ENUM || 5630 (btype.t & VT_BTYPE) == VT_STRUCT) && 5631 tok == ';') { 5632 /* we accept no variable after */ 5633 next(); 5634 continue; 7175 } 7176 } 7177 if (tok == ';') { 7178 if ((btype.t & VT_BTYPE) == VT_STRUCT) { 7179 int v = btype.ref->v; 7180 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM) 7181 tcc_warning("unnamed struct/union that defines no instances"); 7182 next(); 7183 continue; 7184 } 7185 if (IS_ENUM(btype.t)) { 7186 next(); 7187 continue; 7188 } 5635 7189 } 5636 7190 while (1) { /* iterate thru each declaration */ 5637 char *asm_label; // associated asm label5638 7191 type = btype; 7192 /* If the base type itself was an array type of unspecified 7193 size (like in 'typedef int arr[]; arr x = {1};') then 7194 we will overwrite the unknown size by the real one for 7195 this decl. We need to unshare the ref symbol holding 7196 that size. */ 7197 if ((type.t & VT_ARRAY) && type.ref->c < 0) { 7198 type.ref = sym_push(SYM_FIELD, &type.ref->type, 0, type.ref->c); 7199 } 5639 7200 type_decl(&type, &ad, &v, TYPE_DIRECT); 5640 7201 #if 0 5641 7202 { 5642 7203 char buf[500]; 5643 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));7204 type_to_str(buf, sizeof(buf), &type, get_tok_str(v, NULL)); 5644 7205 printf("type = '%s'\n", buf); 5645 7206 } … … 5652 7213 declaration list */ 5653 7214 sym = type.ref; 5654 if (sym->c == FUNC_OLD) 5655 func_decl_list(sym); 5656 } 5657 5658 asm_label = NULL; 7215 if (sym->f.func_type == FUNC_OLD && l == VT_CONST) 7216 decl0(VT_CMP, 0, sym); 7217 } 7218 5659 7219 if (gnu_ext && (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) { 5660 CString astr; 5661 5662 asm_label_instr(&astr); 5663 asm_label = tcc_strdup(astr.data); 5664 cstr_free(&astr); 5665 7220 ad.asm_label = asm_label_instr(); 5666 7221 /* parse one last attribute list, after asm label */ 5667 7222 parse_attribute(&ad); 5668 }5669 5670 if (ad.weak)5671 type.t |= VT_WEAK; 7223 if (tok == '{') 7224 expect(";"); 7225 } 7226 5672 7227 #ifdef TCC_TARGET_PE 5673 if (ad.func_import) 5674 type.t |= VT_IMPORT; 5675 if (ad.func_export) 5676 type.t |= VT_EXPORT; 7228 if (ad.a.dllimport || ad.a.dllexport) { 7229 if (type.t & (VT_STATIC|VT_TYPEDEF)) 7230 tcc_error("cannot have dll linkage with static or typedef"); 7231 if (ad.a.dllimport) { 7232 if ((type.t & VT_BTYPE) == VT_FUNC) 7233 ad.a.dllimport = 0; 7234 else 7235 type.t |= VT_EXTERN; 7236 } 7237 } 5677 7238 #endif 5678 7239 if (tok == '{') { 5679 if (l == VT_LOCAL)7240 if (l != VT_CONST) 5680 7241 tcc_error("cannot use local functions"); 5681 7242 if ((type.t & VT_BTYPE) != VT_FUNC) 5682 7243 expect("function definition"); 5683 7244 5684 /* reject abstract declarators in function definition */ 7245 /* reject abstract declarators in function definition 7246 make old style params without decl have int type */ 5685 7247 sym = type.ref; 5686 while ((sym = sym->next) != NULL) 7248 while ((sym = sym->next) != NULL) { 5687 7249 if (!(sym->v & ~SYM_FIELD)) 5688 expect("identifier"); 7250 expect("identifier"); 7251 if (sym->type.t == VT_VOID) 7252 sym->type = int_type; 7253 } 5689 7254 5690 7255 /* XXX: cannot do better now: convert extern line to static inline */ 5691 7256 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE)) 5692 7257 type.t = (type.t & ~VT_EXTERN) | VT_STATIC; 5693 5694 sym = sym_find(v); 5695 if (sym) { 5696 if ((sym->type.t & VT_BTYPE) != VT_FUNC) 5697 goto func_error1; 5698 5699 r = sym->type.ref->r; 5700 /* use func_call from prototype if not defined */ 5701 if (FUNC_CALL(r) != FUNC_CDECL 5702 && FUNC_CALL(type.ref->r) == FUNC_CDECL) 5703 FUNC_CALL(type.ref->r) = FUNC_CALL(r); 5704 5705 /* use export from prototype */ 5706 if (FUNC_EXPORT(r)) 5707 FUNC_EXPORT(type.ref->r) = 1; 5708 5709 /* use static from prototype */ 5710 if (sym->type.t & VT_STATIC) 5711 type.t = (type.t & ~VT_EXTERN) | VT_STATIC; 5712 5713 if (!is_compatible_types(&sym->type, &type)) { 5714 func_error1: 5715 tcc_error("incompatible types for redefinition of '%s'", 5716 get_tok_str(v, NULL)); 5717 } 5718 /* if symbol is already defined, then put complete type */ 5719 sym->type = type; 5720 } else { 5721 /* put function symbol */ 5722 sym = global_identifier_push(v, type.t, 0); 5723 sym->type.ref = type.ref; 5724 } 7258 7259 /* put function symbol */ 7260 sym = external_global_sym(v, &type, 0); 7261 type.t &= ~VT_EXTERN; 7262 patch_storage(sym, &ad, &type); 5725 7263 5726 7264 /* static inline functions are just recorded as a kind … … 5729 7267 if ((type.t & (VT_INLINE | VT_STATIC)) == 5730 7268 (VT_INLINE | VT_STATIC)) { 5731 TokenString func_str;5732 int block_level;5733 7269 struct InlineFunc *fn; 5734 7270 const char *filename; 5735 7271 5736 tok_str_new(&func_str);5737 5738 block_level = 0;5739 for(;;) {5740 int t;5741 if (tok == TOK_EOF)5742 tcc_error("unexpected end of file");5743 tok_str_add_tok(&func_str);5744 t = tok;5745 next();5746 if (t == '{') {5747 block_level++;5748 } else if (t == '}') {5749 block_level--;5750 if (block_level == 0)5751 break;5752 }5753 }5754 tok_str_add(&func_str, -1);5755 tok_str_add(&func_str, 0);5756 7272 filename = file ? file->filename : ""; 5757 7273 fn = tcc_malloc(sizeof *fn + strlen(filename)); 5758 7274 strcpy(fn->filename, filename); 5759 7275 fn->sym = sym; 5760 fn->token_str = func_str.str;5761 dynarray_add( (void ***)&tcc_state->inline_fns, &tcc_state->nb_inline_fns, fn);5762 7276 skip_or_save_block(&fn->func_str); 7277 dynarray_add(&tcc_state->inline_fns, 7278 &tcc_state->nb_inline_fns, fn); 5763 7279 } else { 5764 7280 /* compute text section */ … … 5766 7282 if (!cur_text_section) 5767 7283 cur_text_section = text_section; 5768 sym->r = VT_SYM | VT_CONST;5769 7284 gen_function(sym); 5770 7285 } 5771 7286 break; 5772 7287 } else { 5773 if (btype.t & VT_TYPEDEF) { 7288 if (l == VT_CMP) { 7289 /* find parameter in function parameter list */ 7290 for (sym = func_sym->next; sym; sym = sym->next) 7291 if ((sym->v & ~SYM_FIELD) == v) 7292 goto found; 7293 tcc_error("declaration for parameter '%s' but no such parameter", 7294 get_tok_str(v, NULL)); 7295 found: 7296 if (type.t & VT_STORAGE) /* 'register' is okay */ 7297 tcc_error("storage class specified for '%s'", 7298 get_tok_str(v, NULL)); 7299 if (sym->type.t != VT_VOID) 7300 tcc_error("redefinition of parameter '%s'", 7301 get_tok_str(v, NULL)); 7302 convert_parameter_type(&type); 7303 sym->type = type; 7304 } else if (type.t & VT_TYPEDEF) { 5774 7305 /* save typedefed type */ 5775 7306 /* XXX: test storage specifiers ? */ 5776 sym = sym_push(v, &type, INT_ATTR(&ad), 0); 5777 sym->type.t |= VT_TYPEDEF; 7307 sym = sym_find(v); 7308 if (sym && sym->sym_scope == local_scope) { 7309 if (!is_compatible_types(&sym->type, &type) 7310 || !(sym->type.t & VT_TYPEDEF)) 7311 tcc_error("incompatible redefinition of '%s'", 7312 get_tok_str(v, NULL)); 7313 sym->type = type; 7314 } else { 7315 sym = sym_push(v, &type, 0, 0); 7316 } 7317 sym->a = ad.a; 7318 sym->f = ad.f; 5778 7319 } else { 5779 7320 r = 0; … … 5781 7322 /* external function definition */ 5782 7323 /* specific case for func_call attribute */ 5783 type.ref-> r = INT_ATTR(&ad);7324 type.ref->f = ad.f; 5784 7325 } else if (!(type.t & VT_ARRAY)) { 5785 7326 /* not lvalue if array */ … … 5788 7329 has_init = (tok == '='); 5789 7330 if (has_init && (type.t & VT_VLA)) 5790 tcc_error("Variable length array cannot be initialized"); 5791 if ((btype.t & VT_EXTERN) || ((type.t & VT_BTYPE) == VT_FUNC) || 7331 tcc_error("variable length array cannot be initialized"); 7332 if (((type.t & VT_EXTERN) && (!has_init || l != VT_CONST)) || 7333 ((type.t & VT_BTYPE) == VT_FUNC) || 5792 7334 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) && 5793 7335 !has_init && l == VT_CONST && type.ref->c < 0)) { … … 5796 7338 arrays of null size are considered as 5797 7339 extern */ 5798 sym = external_sym(v, &type, r, asm_label); 5799 5800 if (type.t & VT_WEAK) 5801 weaken_symbol(sym); 5802 7340 type.t |= VT_EXTERN; 7341 sym = external_sym(v, &type, r, &ad); 5803 7342 if (ad.alias_target) { 5804 Section tsec; 5805 Elf32_Sym *esym; 7343 ElfSym *esym; 5806 7344 Sym *alias_target; 5807 5808 7345 alias_target = sym_find(ad.alias_target); 5809 if (!alias_target || !alias_target->c) 7346 esym = elfsym(alias_target); 7347 if (!esym) 5810 7348 tcc_error("unsupported forward __alias__ attribute"); 5811 esym = &((Elf32_Sym *)symtab_section->data)[alias_target->c]; 5812 tsec.sh_num = esym->st_shndx; 5813 put_extern_sym2(sym, &tsec, esym->st_value, esym->st_size, 0); 7349 /* Local statics have a scope until now (for 7350 warnings), remove it here. */ 7351 sym->sym_scope = 0; 7352 put_extern_sym2(sym, esym->st_shndx, esym->st_value, esym->st_size, 0); 5814 7353 } 5815 7354 } else { 5816 type.t |= (btype.t & VT_STATIC); /* Retain "static". */5817 7355 if (type.t & VT_STATIC) 5818 7356 r |= VT_CONST; … … 5821 7359 if (has_init) 5822 7360 next(); 5823 decl_initializer_alloc(&type, &ad, r, has_init, v, asm_label, l); 7361 else if (l == VT_CONST) 7362 /* uninitialized global variables may be overridden */ 7363 type.t |= VT_EXTERN; 7364 decl_initializer_alloc(&type, &ad, r, has_init, v, l); 5824 7365 } 5825 7366 } … … 5832 7373 next(); 5833 7374 } 5834 ad.a ligned = 0;7375 ad.a.aligned = 0; 5835 7376 } 5836 7377 } … … 5838 7379 } 5839 7380 5840 ST_FUNC void decl(int l) 5841 { 5842 decl0(l, 0); 5843 } 7381 static void decl(int l) 7382 { 7383 decl0(l, 0, NULL); 7384 } 7385 7386 /* ------------------------------------------------------------------------- */ -
EcnlProtoTool/trunk/tcc-0.9.27/tccpe.c
r321 r331 21 21 #include "tcc.h" 22 22 23 #define PE_MERGE_DATA 24 /* #define PE_PRINT_SECTIONS */ 25 23 26 #ifndef _WIN32 24 27 #define stricmp strcasecmp 25 28 #define strnicmp strncasecmp 26 #endif 27 28 #ifndef MAX_PATH 29 #define MAX_PATH 260 30 #endif 31 32 #define PE_MERGE_DATA 33 // #define PE_PRINT_SECTIONS 29 #include <sys/stat.h> /* chmod() */ 30 #endif 34 31 35 32 #ifdef TCC_TARGET_X86_64 36 33 # define ADDR3264 ULONGLONG 37 #else 34 # define PE_IMAGE_REL IMAGE_REL_BASED_DIR64 35 # define REL_TYPE_DIRECT R_X86_64_64 36 # define R_XXX_THUNKFIX R_X86_64_PC32 37 # define R_XXX_RELATIVE R_X86_64_RELATIVE 38 # define IMAGE_FILE_MACHINE 0x8664 39 # define RSRC_RELTYPE 3 40 41 #elif defined TCC_TARGET_ARM 38 42 # define ADDR3264 DWORD 39 #endif 40 41 #ifdef _WIN32 42 void dbg_printf (const char *fmt, ...) 43 { 44 char buffer[4000]; 45 va_list arg; 46 int x; 47 va_start(arg, fmt); 48 x = vsprintf (buffer, fmt, arg); 49 strcpy(buffer+x, "\n"); 50 OutputDebugString(buffer); 51 } 52 #endif 53 54 /* ----------------------------------------------------------- */ 43 # define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW 44 # define REL_TYPE_DIRECT R_ARM_ABS32 45 # define R_XXX_THUNKFIX R_ARM_ABS32 46 # define R_XXX_RELATIVE R_ARM_RELATIVE 47 # define IMAGE_FILE_MACHINE 0x01C0 48 # define RSRC_RELTYPE 7 /* ??? (not tested) */ 49 50 #elif defined TCC_TARGET_I386 51 # define ADDR3264 DWORD 52 # define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW 53 # define REL_TYPE_DIRECT R_386_32 54 # define R_XXX_THUNKFIX R_386_32 55 # define R_XXX_RELATIVE R_386_RELATIVE 56 # define IMAGE_FILE_MACHINE 0x014C 57 # define RSRC_RELTYPE 7 /* DIR32NB */ 58 59 #endif 60 55 61 #ifndef IMAGE_NT_SIGNATURE 56 62 /* ----------------------------------------------------------- */ … … 224 230 #define IMAGE_REL_BASED_SECTION 6 225 231 #define IMAGE_REL_BASED_REL32 7 232 #define IMAGE_REL_BASED_DIR64 10 226 233 227 234 #pragma pack(pop) … … 230 237 #endif /* ndef IMAGE_NT_SIGNATURE */ 231 238 /* ----------------------------------------------------------- */ 239 240 #ifndef IMAGE_REL_BASED_DIR64 241 # define IMAGE_REL_BASED_DIR64 10 242 #endif 243 232 244 #pragma pack(push, 1) 233 234 245 struct pe_header 235 246 { … … 264 275 WORD type; 265 276 }; 266 267 277 #pragma pack(pop) 268 278 … … 337 347 DWORD sizeofheaders; 338 348 ADDR3264 imagebase; 349 const char *start_symbol; 339 350 DWORD start_addr; 340 351 DWORD imp_offs; … … 363 374 static const char *pe_export_name(TCCState *s1, ElfW(Sym) *sym) 364 375 { 365 const char *name = symtab_section->link->data + sym->st_name;366 if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & 2))376 const char *name = (char*)symtab_section->link->data + sym->st_name; 377 if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL)) 367 378 return name + 1; 368 379 return name; … … 374 385 const char *s, *p; 375 386 int sym_index = 0, n = 0; 387 int a, err = 0; 376 388 377 389 do { 378 390 s = pe_export_name(s1, sym); 391 a = 0; 379 392 if (n) { 380 393 /* second try: */ 381 if (sym->st_other & 2) {394 if (sym->st_other & ST_PE_STDCALL) { 382 395 /* try w/0 stdcall deco (windows API convention) */ 383 396 p = strrchr(s, '@'); … … 387 400 } else if (s[0] != '_') { /* try non-ansi function */ 388 401 buffer[0] = '_', strcpy(buffer + 1, s); 389 } else if (0 == memcmp(s, "__imp_ _", 7)) { /* mingw 2.0 */390 strcpy(buffer, s + 6) ;391 } else if (0 == memcmp(s, "_imp__ _", 7)) { /* mingw 3.7 */392 strcpy(buffer, s + 6) ;402 } else if (0 == memcmp(s, "__imp_", 6)) { /* mingw 2.0 */ 403 strcpy(buffer, s + 6), a = 1; 404 } else if (0 == memcmp(s, "_imp__", 6)) { /* mingw 3.7 */ 405 strcpy(buffer, s + 6), a = 1; 393 406 } else { 394 break;407 continue; 395 408 } 396 409 s = buffer; … … 398 411 sym_index = find_elf_sym(s1->dynsymtab_section, s); 399 412 // printf("find (%d) %d %s\n", n, sym_index, s); 413 if (sym_index 414 && ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT 415 && 0 == (sym->st_other & ST_PE_IMPORT) 416 && 0 == a 417 ) err = -1, sym_index = 0; 400 418 } while (0 == sym_index && ++n < 2); 401 return sym_index;419 return n == 2 ? err : sym_index; 402 420 } 403 421 … … 508 526 { 509 527 /* IMAGE_FILE_HEADER filehdr */ 510 #if defined(TCC_TARGET_I386) 511 0x014C, /*WORD Machine; */ 512 #elif defined(TCC_TARGET_X86_64) 513 0x8664, /*WORD Machine; */ 514 #elif defined(TCC_TARGET_ARM) 515 0x01C0, /*WORD Machine; */ 516 #endif 528 IMAGE_FILE_MACHINE, /*WORD Machine; */ 517 529 0x0003, /*WORD NumberOfSections; */ 518 530 0x00000000, /*DWORD TimeDateStamp; */ … … 623 635 case sec_text: 624 636 pe_header.opthdr.BaseOfCode = addr; 625 pe_header.opthdr.AddressOfEntryPoint = addr + pe->start_addr;626 637 break; 627 638 … … 664 675 } 665 676 666 pstrcpy((char*)psh->Name, sizeof psh->Name, sh_name);677 strncpy((char*)psh->Name, sh_name, sizeof psh->Name); 667 678 668 679 psh->Characteristics = pe_sec_flags[si->cls]; … … 676 687 file_offset = pe_file_align(pe, file_offset + si->data_size); 677 688 psh->SizeOfRawData = file_offset - psh->PointerToRawData; 689 if (si->cls == sec_text) 690 pe_header.opthdr.SizeOfCode += psh->SizeOfRawData; 691 else 692 pe_header.opthdr.SizeOfInitializedData += psh->SizeOfRawData; 678 693 } 679 694 } … … 681 696 //pe_header.filehdr.TimeDateStamp = time(NULL); 682 697 pe_header.filehdr.NumberOfSections = pe->sec_count; 698 pe_header.opthdr.AddressOfEntryPoint = pe->start_addr; 683 699 pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders; 684 700 pe_header.opthdr.ImageBase = pe->imagebase; … … 688 704 if (PE_DLL == pe->type) 689 705 pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL; 706 pe_header.filehdr.Characteristics |= pe->s1->pe_characteristics; 690 707 691 708 sum = 0; … … 708 725 pe_fwrite(&pe_header.opthdr.CheckSum, sizeof pe_header.opthdr.CheckSum, op, NULL); 709 726 fclose (op); 727 #ifndef _WIN32 728 chmod(pe->filename, 0777); 729 #endif 710 730 711 731 if (2 == pe->s1->verbose) … … 717 737 } 718 738 719 /*----------------------------------------------------------------------------*/720 721 #if defined(TCC_TARGET_X86_64)722 #define REL_TYPE_DIRECT R_X86_64_64723 #define R_XXX_THUNKFIX R_X86_64_PC32724 #define R_XXX_RELATIVE R_X86_64_RELATIVE725 726 #elif defined(TCC_TARGET_I386)727 #define REL_TYPE_DIRECT R_386_32728 #define R_XXX_THUNKFIX R_386_32729 #define R_XXX_RELATIVE R_386_RELATIVE730 731 #elif defined(TCC_TARGET_ARM)732 #define REL_TYPE_DIRECT R_ARM_ABS32733 #define R_XXX_THUNKFIX R_ARM_ABS32734 #define R_XXX_RELATIVE R_ARM_RELATIVE735 736 #endif737 739 /*----------------------------------------------------------------------------*/ 738 740 … … 755 757 p = tcc_mallocz(sizeof *p); 756 758 p->dll_index = dll_index; 757 dynarray_add( (void***)&pe->imp_info, &pe->imp_count, p);759 dynarray_add(&pe->imp_info, &pe->imp_count, p); 758 760 759 761 found_dll: … … 763 765 764 766 s = tcc_mallocz(sizeof *s); 765 dynarray_add( (void***)&p->symbols, &p->sym_count, s);767 dynarray_add(&p->symbols, &p->sym_count, s); 766 768 s->sym_index = sym_index; 767 769 return s; 770 } 771 772 void pe_free_imports(struct pe_info *pe) 773 { 774 int i; 775 for (i = 0; i < pe->imp_count; ++i) { 776 struct pe_import_info *p = pe->imp_info[i]; 777 dynarray_reset(&p->symbols, &p->sym_count); 778 } 779 dynarray_reset(&pe->imp_info, &pe->imp_count); 768 780 } 769 781 … … 819 831 ElfW(Sym) *imp_sym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index; 820 832 ElfW(Sym) *org_sym = (ElfW(Sym) *)symtab_section->data + iat_index; 821 const char *name = pe->s1->dynsymtab_section->link->data + imp_sym->st_name; 833 const char *name = (char*)pe->s1->dynsymtab_section->link->data + imp_sym->st_name; 834 int ordinal; 822 835 823 836 org_sym->st_value = thk_ptr; 824 837 org_sym->st_shndx = pe->thunk->sh_num; 825 v = pe->thunk->data_offset + rva_base; 826 section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */ 827 put_elf_str(pe->thunk, name); 838 839 if (dllref) 840 v = 0, ordinal = imp_sym->st_value; /* ordinal from pe_load_def */ 841 else 842 ordinal = 0, v = imp_sym->st_value; /* address from tcc_add_symbol() */ 843 828 844 #ifdef TCC_IS_NATIVE 829 845 if (pe->type == PE_RUN) { 830 v = imp_sym->st_value;831 846 if (dllref) { 832 847 if ( !dllref->handle ) 833 848 dllref->handle = LoadLibrary(dllref->name); 834 v = (ADDR3264)GetProcAddress(dllref->handle, name);849 v = (ADDR3264)GetProcAddress(dllref->handle, ordinal?(char*)0+ordinal:name); 835 850 } 836 851 if (!v) 837 tcc_error_noabort("undefined symbol '%s'", name); 852 tcc_error_noabort("can't build symbol '%s'", name); 853 } else 854 #endif 855 if (ordinal) { 856 v = ordinal | (ADDR3264)1 << (sizeof(ADDR3264)*8 - 1); 857 } else { 858 v = pe->thunk->data_offset + rva_base; 859 section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */ 860 put_elf_str(pe->thunk, name); 838 861 } 839 #endif 862 840 863 } else { 841 864 v = 0; /* last entry is zero */ 842 865 } 866 843 867 *(ADDR3264*)(pe->thunk->data+thk_ptr) = 844 868 *(ADDR3264*)(pe->thunk->data+ent_ptr) = v; … … 847 871 } 848 872 dll_ptr += sizeof(IMAGE_IMPORT_DESCRIPTOR); 849 dynarray_reset(&p->symbols, &p->sym_count); 850 } 851 dynarray_reset(&pe->imp_info, &pe->imp_count); 873 } 852 874 } 853 875 … … 877 899 878 900 FILE *op; 879 char buf[ MAX_PATH];901 char buf[260]; 880 902 const char *dllname; 881 903 const char *name; … … 888 910 sym = (ElfW(Sym)*)symtab_section->data + sym_index; 889 911 name = pe_export_name(pe->s1, sym); 890 if ((sym->st_other & 1)912 if ((sym->st_other & ST_PE_EXPORT) 891 913 /* export only symbols from actually written sections */ 892 914 && pe->s1->sections[sym->st_shndx]->sh_addr) { … … 894 916 p->index = sym_index; 895 917 p->name = name; 896 dynarray_add( (void***)&sorted, &sym_count, p);918 dynarray_add(&sorted, &sym_count, p); 897 919 } 898 920 #if 0 899 if (sym->st_other & 1)921 if (sym->st_other & ST_PE_EXPORT) 900 922 printf("export: %s\n", name); 901 if (sym->st_other & 2)923 if (sym->st_other & ST_PE_STDCALL) 902 924 printf("stdcall: %s\n", name); 903 925 #endif … … 933 955 pstrcpy(buf, sizeof buf, pe->filename); 934 956 strcpy(tcc_fileextension(buf), ".def"); 935 op = fopen(buf, "w ");957 op = fopen(buf, "wb"); 936 958 if (NULL == op) { 937 959 tcc_error_noabort("could not create '%s': %s", buf, strerror(errno)); … … 939 961 fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname); 940 962 if (pe->s1->verbose) 941 printf("<- %s (%d symbol s)\n", buf, sym_count);963 printf("<- %s (%d symbol%s)\n", buf, sym_count, &"s"[sym_count < 2]); 942 964 } 943 965 #endif … … 946 968 { 947 969 p = sorted[ord], sym_index = p->index, name = p->name; 948 /* insert actual address later in pe_relocate_rva*/970 /* insert actual address later in relocate_section() */ 949 971 put_elf_reloc(symtab_section, pe->thunk, 950 972 func_o, R_XXX_RELATIVE, sym_index); … … 991 1013 if ((addr -= offset) < (1<<12)) { /* one block spans 4k addresses */ 992 1014 WORD *wp = section_ptr_add(pe->reloc, sizeof (WORD)); 993 *wp = addr | IMAGE_REL_BASED_HIGHLOW<<12;1015 *wp = addr | PE_IMAGE_REL<<12; 994 1016 ++count; 995 1017 continue; … … 1065 1087 Section *s; 1066 1088 1089 if (PE_DLL == pe->type) 1090 pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0); 1091 1067 1092 // pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC); 1068 1093 … … 1157 1182 } 1158 1183 1159 /* ------------------------------------------------------------- */1160 static void pe_relocate_rva (struct pe_info *pe, Section *s)1161 {1162 Section *sr = s->reloc;1163 ElfW_Rel *rel, *rel_end;1164 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);1165 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {1166 if (ELFW(R_TYPE)(rel->r_info) == R_XXX_RELATIVE) {1167 int sym_index = ELFW(R_SYM)(rel->r_info);1168 DWORD addr = s->sh_addr;1169 if (sym_index) {1170 ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;1171 addr = sym->st_value;1172 }1173 // printf("reloc rva %08x %08x %s\n", (DWORD)rel->r_offset, addr, s->name);1174 *(DWORD*)(s->data + rel->r_offset) += addr - pe->imagebase;1175 }1176 }1177 }1178 1179 1184 /*----------------------------------------------------------------------------*/ 1180 1185 … … 1208 1213 if (sym->st_shndx == SHN_UNDEF) { 1209 1214 1210 const char *name = symtab_section->link->data + sym->st_name;1215 const char *name = (char*)symtab_section->link->data + sym->st_name; 1211 1216 unsigned type = ELFW(ST_TYPE)(sym->st_info); 1212 1217 int imp_sym = pe_find_import(pe->s1, sym); 1213 1218 struct import_symbol *is; 1214 1219 1215 if ( 0 == imp_sym)1220 if (imp_sym <= 0) 1216 1221 goto not_found; 1217 1222 … … 1271 1276 sym->st_value = offset; 1272 1277 sym->st_shndx = text_section->sh_num; 1273 sym->st_other &= ~ 1; /* do not export */1278 sym->st_other &= ~ST_PE_EXPORT; /* do not export */ 1274 1279 continue; 1275 1280 } … … 1284 1289 1285 1290 not_found: 1286 tcc_error_noabort("undefined symbol '%s'", name); 1291 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) 1292 /* STB_WEAK undefined symbols are accepted */ 1293 continue; 1294 tcc_error_noabort("undefined symbol '%s'%s", name, 1295 imp_sym < 0 ? ", missing __declspec(dllimport)?":""); 1287 1296 ret = -1; 1288 1297 … … 1290 1299 && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { 1291 1300 /* if -rdynamic option, then export all non local symbols */ 1292 sym->st_other |= 1;1301 sym->st_other |= ST_PE_EXPORT; 1293 1302 } 1294 1303 } … … 1300 1309 static void pe_print_section(FILE * f, Section * s) 1301 1310 { 1302 /* just if you'r curious */1311 /* just if you're curious */ 1303 1312 BYTE *p, *e, b; 1304 1313 int i, n, l, m; … … 1438 1447 /* helper function for load/store to insert one more indirection */ 1439 1448 1449 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 1440 1450 ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2) 1441 1451 { 1442 Sym *sym;1443 ElfW(Sym) *esym;1444 1452 int r2; 1445 1446 1453 if ((sv->r & (VT_VALMASK|VT_SYM)) != (VT_CONST|VT_SYM) || (sv->r2 != VT_CONST)) 1447 1454 return sv; 1448 sym = sv->sym; 1449 if ((sym->type.t & (VT_EXTERN|VT_STATIC)) != VT_EXTERN) 1455 if (!sv->sym->a.dllimport) 1450 1456 return sv; 1451 if (!sym->c) 1452 put_extern_sym(sym, NULL, 0, 0); 1453 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; 1454 if (!(esym->st_other & 4)) 1455 return sv; 1456 1457 // printf("import %04x %04x %04x %s\n", sv->type.t, sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL)); 1458 1457 // printf("import %04x %04x %04x %s\n", sv->type.t, sv->sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL)); 1459 1458 memset(v2, 0, sizeof *v2); 1460 1459 v2->type.t = VT_PTR; … … 1465 1464 load(r2, v2); 1466 1465 v2->r = r2; 1467 1468 if (sv->c.ui) { 1466 if ((uint32_t)sv->c.i) { 1469 1467 vpushv(v2); 1470 vpushi(sv->c. ui);1468 vpushi(sv->c.i); 1471 1469 gen_opi('+'); 1472 1470 *v2 = *vtop--; 1473 1471 } 1474 1475 1472 v2->type.t = sv->type.t; 1476 1473 v2->r |= sv->r & VT_LVAL; 1477 1474 return v2; 1478 1475 } 1476 #endif 1479 1477 1480 1478 ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value) 1481 1479 { 1482 return add_elf_sym(1480 return set_elf_sym( 1483 1481 s1->dynsymtab_section, 1484 1482 value, … … 1500 1498 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname)); 1501 1499 strcpy(dllref->name, dllname); 1502 dynarray_add( (void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);1500 dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); 1503 1501 return s1->nb_loaded_dlls; 1504 1502 } … … 1510 1508 lseek(fd, offset, SEEK_SET); 1511 1509 return len == read(fd, buffer, len); 1510 } 1511 1512 /* ------------------------------------------------------------- */ 1513 1514 PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp) 1515 { 1516 int l, i, n, n0, ret; 1517 char *p; 1518 int fd; 1519 1520 IMAGE_SECTION_HEADER ish; 1521 IMAGE_EXPORT_DIRECTORY ied; 1522 IMAGE_DOS_HEADER dh; 1523 IMAGE_FILE_HEADER ih; 1524 DWORD sig, ref, addr, ptr, namep; 1525 1526 int pef_hdroffset, opt_hdroffset, sec_hdroffset; 1527 1528 n = n0 = 0; 1529 p = NULL; 1530 ret = -1; 1531 1532 fd = open(filename, O_RDONLY | O_BINARY); 1533 if (fd < 0) 1534 goto the_end_1; 1535 ret = 1; 1536 if (!read_mem(fd, 0, &dh, sizeof dh)) 1537 goto the_end; 1538 if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig)) 1539 goto the_end; 1540 if (sig != 0x00004550) 1541 goto the_end; 1542 pef_hdroffset = dh.e_lfanew + sizeof sig; 1543 if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih)) 1544 goto the_end; 1545 opt_hdroffset = pef_hdroffset + sizeof ih; 1546 if (ih.Machine == 0x014C) { 1547 IMAGE_OPTIONAL_HEADER32 oh; 1548 sec_hdroffset = opt_hdroffset + sizeof oh; 1549 if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) 1550 goto the_end; 1551 if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) 1552 goto the_end_0; 1553 addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 1554 } else if (ih.Machine == 0x8664) { 1555 IMAGE_OPTIONAL_HEADER64 oh; 1556 sec_hdroffset = opt_hdroffset + sizeof oh; 1557 if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) 1558 goto the_end; 1559 if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) 1560 goto the_end_0; 1561 addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 1562 } else 1563 goto the_end; 1564 1565 //printf("addr: %08x\n", addr); 1566 for (i = 0; i < ih.NumberOfSections; ++i) { 1567 if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish)) 1568 goto the_end; 1569 //printf("vaddr: %08x\n", ish.VirtualAddress); 1570 if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData) 1571 goto found; 1572 } 1573 goto the_end_0; 1574 1575 found: 1576 ref = ish.VirtualAddress - ish.PointerToRawData; 1577 if (!read_mem(fd, addr - ref, &ied, sizeof ied)) 1578 goto the_end; 1579 1580 namep = ied.AddressOfNames - ref; 1581 for (i = 0; i < ied.NumberOfNames; ++i) { 1582 if (!read_mem(fd, namep, &ptr, sizeof ptr)) 1583 goto the_end; 1584 namep += sizeof ptr; 1585 for (l = 0;;) { 1586 if (n+1 >= n0) 1587 p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256); 1588 if (!read_mem(fd, ptr - ref + l++, p + n, 1)) { 1589 tcc_free(p), p = NULL; 1590 goto the_end; 1591 } 1592 if (p[n++] == 0) 1593 break; 1594 } 1595 } 1596 if (p) 1597 p[n] = 0; 1598 the_end_0: 1599 ret = 0; 1600 the_end: 1601 close(fd); 1602 the_end_1: 1603 *pp = p; 1604 return ret; 1512 1605 } 1513 1606 … … 1521 1614 struct pe_rsrc_header hdr; 1522 1615 Section *rsrc_section; 1523 int i, ret = -1 ;1616 int i, ret = -1, sym_index; 1524 1617 BYTE *ptr; 1525 1618 unsigned offs; … … 1528 1621 goto quit; 1529 1622 1530 if (hdr.filehdr.Machine != 0x014C1623 if (hdr.filehdr.Machine != IMAGE_FILE_MACHINE 1531 1624 || hdr.filehdr.NumberOfSections != 1 1532 || strcmp( hdr.sectionhdr.Name, ".rsrc") != 0)1625 || strcmp((char*)hdr.sectionhdr.Name, ".rsrc") != 0) 1533 1626 goto quit; 1534 1627 … … 1539 1632 goto quit; 1540 1633 offs = hdr.sectionhdr.PointerToRelocations; 1541 for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i)1542 {1634 sym_index = put_elf_sym(symtab_section, 0, 0, 0, 0, rsrc_section->sh_num, ".rsrc"); 1635 for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i) { 1543 1636 struct pe_rsrc_reloc rel; 1544 1637 if (!read_mem(fd, offs, &rel, sizeof rel)) 1545 1638 goto quit; 1546 1639 // printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type); 1547 if (rel.type != 7) /* DIR32NB */1640 if (rel.type != RSRC_RELTYPE) 1548 1641 goto quit; 1549 1642 put_elf_reloc(symtab_section, rsrc_section, 1550 rel.offset, R_XXX_RELATIVE, 0);1643 rel.offset, R_XXX_RELATIVE, sym_index); 1551 1644 offs += sizeof rel; 1552 1645 } … … 1557 1650 1558 1651 /* ------------------------------------------------------------- */ 1652 1559 1653 static char *trimfront(char *p) 1560 1654 { 1561 1655 while (*p && (unsigned char)*p <= ' ') 1562 1656 ++p; 1563 1657 return p; 1564 1658 } … … 1567 1661 { 1568 1662 while (e > a && (unsigned char)e[-1] <= ' ') 1569 1663 --e; 1570 1664 *e = 0;; 1571 1665 return a; 1572 1666 } 1573 1667 1574 static char *get_line(char *line, int size, int fd)1575 {1576 int n;1577 for (n = 0; n < size - 1; )1578 if (read(fd, line + n, 1) < 1 || line[n++] == '\n')1579 break;1580 if (0 == n)1581 return NULL;1582 trimback(line, line + n);1583 return trimfront(line);1584 }1585 1586 1668 /* ------------------------------------------------------------- */ 1587 1669 static int pe_load_def(TCCState *s1, int fd) 1588 1670 { 1589 int state = 0, ret = -1, dllindex = 0; 1590 char line[400], dllname[80], *p; 1591 1592 for (;;) { 1593 p = get_line(line, sizeof line, fd); 1594 if (NULL == p) 1595 break; 1671 int state = 0, ret = -1, dllindex = 0, ord; 1672 char line[400], dllname[80], *p, *x; 1673 FILE *fp; 1674 1675 fp = fdopen(dup(fd), "rb"); 1676 while (fgets(line, sizeof line, fp)) 1677 { 1678 p = trimfront(trimback(line, strchr(line, 0))); 1596 1679 if (0 == *p || ';' == *p) 1597 1680 continue; 1681 1598 1682 switch (state) { 1599 1683 case 0: … … 1613 1697 dllindex = add_dllref(s1, dllname); 1614 1698 ++state; 1615 1699 /* fall through */ 1616 1700 default: 1617 pe_putimport(s1, dllindex, p, 0); 1701 /* get ordinal and will store in sym->st_value */ 1702 ord = 0; 1703 x = strchr(p, ' '); 1704 if (x) { 1705 *x = 0, x = strrchr(x + 1, '@'); 1706 if (x) { 1707 char *d; 1708 ord = (int)strtol(x + 1, &d, 10); 1709 if (*d) 1710 ord = 0; 1711 } 1712 } 1713 pe_putimport(s1, dllindex, p, ord); 1618 1714 continue; 1619 1715 } … … 1621 1717 ret = 0; 1622 1718 quit: 1719 fclose(fp); 1623 1720 return ret; 1624 1721 } 1625 1722 1626 1723 /* ------------------------------------------------------------- */ 1627 #define TINY_IMPDEF_GET_EXPORT_NAMES_ONLY 1628 #include "win32/tools/tiny_impdef.c" 1629 1630 static int pe_load_dll(TCCState *s1, const char *dllname, int fd) 1724 static int pe_load_dll(TCCState *s1, const char *filename) 1631 1725 { 1632 1726 char *p, *q; 1633 int index; 1634 p = get_export_names(fd); 1635 if (!p) 1727 int index, ret; 1728 1729 ret = tcc_get_dllexports(filename, &p); 1730 if (ret) { 1636 1731 return -1; 1637 index = add_dllref(s1, dllname); 1638 for (q = p; *q; q += 1 + strlen(q)) 1639 pe_putimport(s1, index, q, 0); 1640 tcc_free(p); 1732 } else if (p) { 1733 index = add_dllref(s1, tcc_basename(filename)); 1734 for (q = p; *q; q += 1 + strlen(q)) 1735 pe_putimport(s1, index, q, 0); 1736 tcc_free(p); 1737 } 1641 1738 return 0; 1642 1739 } … … 1651 1748 else if (pe_load_res(s1, fd) == 0) 1652 1749 ret = 0; 1653 else if (read_mem(fd, 0, buf, sizeof buf) && 0 == strncmp(buf, "MZ", 2))1654 ret = pe_load_dll(s1, tcc_basename(filename), fd);1750 else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ\220", 4)) 1751 ret = pe_load_dll(s1, filename); 1655 1752 return ret; 1656 1753 } … … 1663 1760 s1->uw_pdata = find_section(tcc_state, ".pdata"); 1664 1761 s1->uw_pdata->sh_addralign = 4; 1665 s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, NULL);1666 }1667 1762 } 1763 if (0 == s1->uw_sym) 1764 s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, ".uw_base"); 1668 1765 if (0 == s1->uw_offs) { 1669 1766 /* As our functions all have the same stackframe, we use one entry for all */ … … 1714 1811 /* put relocations on it */ 1715 1812 for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress) 1716 put_elf_reloc(symtab_section, pd, o, R_X86_64_RELATIVE, s1->uw_sym);1813 put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym); 1717 1814 } 1718 1815 #endif … … 1727 1824 { 1728 1825 const char *start_symbol; 1729 ADDR3264 addr = 0;1730 1826 int pe_type = 0; 1827 int unicode_entry = 0; 1731 1828 1732 1829 if (find_elf_sym(symtab_section, PE_STDSYM("WinMain","@16"))) 1733 1830 pe_type = PE_GUI; 1831 else 1832 if (find_elf_sym(symtab_section, PE_STDSYM("wWinMain","@16"))) { 1833 pe_type = PE_GUI; 1834 unicode_entry = PE_GUI; 1835 } 1734 1836 else 1735 1837 if (TCC_OUTPUT_DLL == s1->output_type) { … … 1738 1840 s1->output_type = TCC_OUTPUT_EXE; 1739 1841 } 1740 else 1842 else { 1741 1843 pe_type = PE_EXE; 1844 if (find_elf_sym(symtab_section, "wmain")) 1845 unicode_entry = PE_EXE; 1846 } 1742 1847 1743 1848 start_symbol = 1744 1849 TCC_OUTPUT_MEMORY == s1->output_type 1745 ? PE_GUI == pe_type ? "__runwinmain" : "_main" 1850 ? PE_GUI == pe_type ? (unicode_entry ? "__runwwinmain" : "__runwinmain") 1851 : (unicode_entry ? "__runwmain" : "__runmain") 1746 1852 : PE_DLL == pe_type ? PE_STDSYM("__dllstart","@12") 1747 : PE_GUI == pe_type ? "__winstart" : "__start" 1853 : PE_GUI == pe_type ? (unicode_entry ? "__wwinstart": "__winstart") 1854 : (unicode_entry ? "__wstart" : "__start") 1748 1855 ; 1749 1856 1750 if (!s1->leading_underscore || strchr(start_symbol, '@')) {1857 if (!s1->leading_underscore || strchr(start_symbol, '@')) 1751 1858 ++start_symbol; 1752 if (start_symbol[0] != '_')1753 start_symbol = NULL;1754 }1755 1859 1756 1860 /* grab the startup code from libtcc1 */ 1757 if (start_symbol) 1758 add_elf_sym(symtab_section, 1759 0, 0, 1760 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1761 SHN_UNDEF, start_symbol); 1861 #ifdef TCC_IS_NATIVE 1862 if (TCC_OUTPUT_MEMORY != s1->output_type || s1->runtime_main) 1863 #endif 1864 set_elf_sym(symtab_section, 1865 0, 0, 1866 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, 1867 SHN_UNDEF, start_symbol); 1868 1869 tcc_add_pragma_libs(s1); 1762 1870 1763 1871 if (0 == s1->nostdlib) { 1764 1872 static const char *libs[] = { 1765 "libtcc1.a", "msvcrt", "kernel32", "", "user32", "gdi32", NULL1873 TCC_LIBTCC1, "msvcrt", "kernel32", "", "user32", "gdi32", NULL 1766 1874 }; 1767 1875 const char **pp, *p; … … 1770 1878 if (PE_DLL != pe_type && PE_GUI != pe_type) 1771 1879 break; 1772 } else if (pp == libs ? tcc_add_dll(s1, p, 0) : tcc_add_library(s1, p)) { 1773 tcc_error_noabort("cannot find library: %s", p); 1774 break; 1880 } else if (pp == libs && tcc_add_dll(s1, p, 0) >= 0) { 1881 continue; 1882 } else { 1883 tcc_add_library_err(s1, p); 1775 1884 } 1776 1885 } … … 1779 1888 if (TCC_OUTPUT_MEMORY == s1->output_type) 1780 1889 pe_type = PE_RUN; 1781 1782 if (start_symbol) {1783 addr = get_elf_sym_addr(s1, start_symbol, 1);1784 if (PE_RUN == pe_type && addr)1785 /* for -run GUI's, put '_runwinmain' instead of 'main' */1786 add_elf_sym(symtab_section,1787 addr, 0,1788 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,1789 text_section->sh_num, "main");1790 }1791 1792 1890 pe->type = pe_type; 1793 pe->start_addr = addr; 1794 } 1795 1796 ST_FUNC int pe_output_file(TCCState * s1, const char *filename) 1891 pe->start_symbol = start_symbol; 1892 } 1893 1894 static void pe_set_options(TCCState * s1, struct pe_info *pe) 1895 { 1896 if (PE_DLL == pe->type) { 1897 /* XXX: check if is correct for arm-pe target */ 1898 pe->imagebase = 0x10000000; 1899 } else { 1900 #if defined(TCC_TARGET_ARM) 1901 pe->imagebase = 0x00010000; 1902 #else 1903 pe->imagebase = 0x00400000; 1904 #endif 1905 } 1906 1907 #if defined(TCC_TARGET_ARM) 1908 /* we use "console" subsystem by default */ 1909 pe->subsystem = 9; 1910 #else 1911 if (PE_DLL == pe->type || PE_GUI == pe->type) 1912 pe->subsystem = 2; 1913 else 1914 pe->subsystem = 3; 1915 #endif 1916 /* Allow override via -Wl,-subsystem=... option */ 1917 if (s1->pe_subsystem != 0) 1918 pe->subsystem = s1->pe_subsystem; 1919 1920 /* set default file/section alignment */ 1921 if (pe->subsystem == 1) { 1922 pe->section_align = 0x20; 1923 pe->file_align = 0x20; 1924 } else { 1925 pe->section_align = 0x1000; 1926 pe->file_align = 0x200; 1927 } 1928 1929 if (s1->section_align != 0) 1930 pe->section_align = s1->section_align; 1931 if (s1->pe_file_align != 0) 1932 pe->file_align = s1->pe_file_align; 1933 1934 if ((pe->subsystem >= 10) && (pe->subsystem <= 12)) 1935 pe->imagebase = 0; 1936 1937 if (s1->has_text_addr) 1938 pe->imagebase = s1->text_addr; 1939 } 1940 1941 ST_FUNC int pe_output_file(TCCState *s1, const char *filename) 1797 1942 { 1798 1943 int ret; … … 1806 1951 tcc_add_bcheck(s1); 1807 1952 pe_add_runtime(s1, &pe); 1808 re locate_common_syms(); /* assign bss adresses */1809 tcc_add_linker_symbols(s1);1953 resolve_common_syms(s1); 1954 pe_set_options(s1, &pe); 1810 1955 1811 1956 ret = pe_check_symbols(&pe); … … 1813 1958 ; 1814 1959 else if (filename) { 1815 if (PE_DLL == pe.type) {1816 pe.reloc = new_section(pe.s1, ".reloc", SHT_PROGBITS, 0);1817 /* XXX: check if is correct for arm-pe target */1818 pe.imagebase = 0x10000000;1819 } else {1820 #if defined(TCC_TARGET_ARM)1821 pe.imagebase = 0x00010000;1822 #else1823 pe.imagebase = 0x00400000;1824 #endif1825 }1826 1827 #if defined(TCC_TARGET_ARM)1828 /* we use "console" subsystem by default */1829 pe.subsystem = 9;1830 #else1831 if (PE_DLL == pe.type || PE_GUI == pe.type)1832 pe.subsystem = 2;1833 else1834 pe.subsystem = 3;1835 #endif1836 /* Allow override via -Wl,-subsystem=... option */1837 if (s1->pe_subsystem != 0)1838 pe.subsystem = s1->pe_subsystem;1839 1840 /* set default file/section alignment */1841 if (pe.subsystem == 1) {1842 pe.section_align = 0x20;1843 pe.file_align = 0x20;1844 } else {1845 pe.section_align = 0x1000;1846 pe.file_align = 0x200;1847 }1848 1849 if (s1->section_align != 0)1850 pe.section_align = s1->section_align;1851 if (s1->pe_file_align != 0)1852 pe.file_align = s1->pe_file_align;1853 1854 if ((pe.subsystem >= 10) && (pe.subsystem <= 12))1855 pe.imagebase = 0;1856 1857 if (s1->has_text_addr)1858 pe.imagebase = s1->text_addr;1859 1860 1960 pe_assign_addresses(&pe); 1861 relocate_syms(s1, 0); 1961 relocate_syms(s1, s1->symtab, 0); 1962 s1->pe_imagebase = pe.imagebase; 1862 1963 for (i = 1; i < s1->nb_sections; ++i) { 1863 1964 Section *s = s1->sections[i]; 1864 1965 if (s->reloc) { 1865 1966 relocate_section(s1, s); 1866 pe_relocate_rva(&pe, s);1867 1967 } 1868 1968 } 1969 pe.start_addr = (DWORD) 1970 ((uintptr_t)tcc_get_symbol_err(s1, pe.start_symbol) 1971 - pe.imagebase); 1869 1972 if (s1->nb_errors) 1870 1973 ret = -1; … … 1876 1979 pe.thunk = data_section; 1877 1980 pe_build_imports(&pe); 1878 #endif 1879 } 1981 s1->runtime_main = pe.start_symbol; 1982 #ifdef TCC_TARGET_X86_64 1983 s1->uw_pdata = find_section(s1, ".pdata"); 1984 #endif 1985 #endif 1986 } 1987 1988 pe_free_imports(&pe); 1880 1989 1881 1990 #ifdef PE_PRINT_SECTIONS -
EcnlProtoTool/trunk/tcc-0.9.27/tccpp.c
r321 r331 25 25 26 26 ST_DATA int tok_flags; 27 /* additional informations about token */28 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */29 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */30 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */31 #define TOK_FLAG_EOF 0x0008 /* end of file */32 33 27 ST_DATA int parse_flags; 34 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */35 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */36 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a37 token. line feed is also38 returned at eof */39 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */40 #define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */41 28 42 29 ST_DATA struct BufferedFile *file; … … 54 41 /* ------------------------------------------------------------------------- */ 55 42 56 static int *macro_ptr_allocated;57 static const int *unget_saved_macro_ptr;58 static int unget_saved_buffer[TOK_MAX_SIZE + 1];59 static int unget_buffer_enabled;60 43 static TokenSym *hash_ident[TOK_HASH_SIZE]; 61 44 static char token_buf[STRING_MAX_SIZE + 1]; 62 /* true if isid(c) || isnum(c) */ 63 static unsigned char isidnum_table[256-CH_EOF]; 45 static CString cstr_buf; 46 static CString macro_equal_buf; 47 static TokenString tokstr_buf; 48 static unsigned char isidnum_table[256 - CH_EOF]; 49 static int pp_debug_tok, pp_debug_symv; 50 static int pp_once; 51 static int pp_expr; 52 static int pp_counter; 53 static void tok_print(const char *msg, const int *str); 54 55 static struct TinyAlloc *toksym_alloc; 56 static struct TinyAlloc *tokstr_alloc; 57 static struct TinyAlloc *cstr_alloc; 58 59 static TokenString *macro_stack; 64 60 65 61 static const char tcc_keywords[] = … … 71 67 /* WARNING: the content of this string encodes token numbers */ 72 68 static const unsigned char tok_two_chars[] = 69 /* outdated -- gr 73 70 "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253" 74 71 "-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266"; 75 76 struct macro_level { 77 struct macro_level *prev; 78 const int *p; 72 */{ 73 '<','=', TOK_LE, 74 '>','=', TOK_GE, 75 '!','=', TOK_NE, 76 '&','&', TOK_LAND, 77 '|','|', TOK_LOR, 78 '+','+', TOK_INC, 79 '-','-', TOK_DEC, 80 '=','=', TOK_EQ, 81 '<','<', TOK_SHL, 82 '>','>', TOK_SAR, 83 '+','=', TOK_A_ADD, 84 '-','=', TOK_A_SUB, 85 '*','=', TOK_A_MUL, 86 '/','=', TOK_A_DIV, 87 '%','=', TOK_A_MOD, 88 '&','=', TOK_A_AND, 89 '^','=', TOK_A_XOR, 90 '|','=', TOK_A_OR, 91 '-','>', TOK_ARROW, 92 '.','.', TOK_TWODOTS, 93 '#','#', TOK_TWOSHARPS, 94 0 79 95 }; 80 96 81 ST_FUNC void next_nomacro(void);82 97 static void next_nomacro_spc(void); 83 static void macro_subst(84 TokenString *tok_str,85 Sym **nested_list,86 const int *macro_str,87 struct macro_level **can_read_stream88 );89 98 90 99 ST_FUNC void skip(int c) … … 101 110 102 111 /* ------------------------------------------------------------------------- */ 112 /* Custom allocator for tiny objects */ 113 114 //#define USE_TAL 115 116 #ifndef USE_TAL 117 #define tal_free(al, p) tcc_free(p) 118 #define tal_realloc(al, p, size) tcc_realloc(p, size) 119 #define tal_new(a,b,c) 120 #define tal_delete(a) 121 #else 122 #if !defined(MEM_DEBUG) 123 #define tal_free(al, p) tal_free_impl(al, p) 124 #define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size) 125 #define TAL_DEBUG_PARAMS 126 #else 127 #define TAL_DEBUG 1 128 //#define TAL_INFO 1 /* collect and dump allocators stats */ 129 #define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__) 130 #define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size, __FILE__, __LINE__) 131 #define TAL_DEBUG_PARAMS , const char *file, int line 132 #define TAL_DEBUG_FILE_LEN 40 133 #endif 134 135 #define TOKSYM_TAL_SIZE (768 * 1024) /* allocator for tiny TokenSym in table_ident */ 136 #define TOKSTR_TAL_SIZE (768 * 1024) /* allocator for tiny TokenString instances */ 137 #define CSTR_TAL_SIZE (256 * 1024) /* allocator for tiny CString instances */ 138 #define TOKSYM_TAL_LIMIT 256 /* prefer unique limits to distinguish allocators debug msgs */ 139 #define TOKSTR_TAL_LIMIT 128 /* 32 * sizeof(int) */ 140 #define CSTR_TAL_LIMIT 1024 141 142 typedef struct TinyAlloc { 143 unsigned limit; 144 unsigned size; 145 uint8_t *buffer; 146 uint8_t *p; 147 unsigned nb_allocs; 148 struct TinyAlloc *next, *top; 149 #ifdef TAL_INFO 150 unsigned nb_peak; 151 unsigned nb_total; 152 unsigned nb_missed; 153 uint8_t *peak_p; 154 #endif 155 } TinyAlloc; 156 157 typedef struct tal_header_t { 158 unsigned size; 159 #ifdef TAL_DEBUG 160 int line_num; /* negative line_num used for double free check */ 161 char file_name[TAL_DEBUG_FILE_LEN + 1]; 162 #endif 163 } tal_header_t; 164 165 /* ------------------------------------------------------------------------- */ 166 167 static TinyAlloc *tal_new(TinyAlloc **pal, unsigned limit, unsigned size) 168 { 169 TinyAlloc *al = tcc_mallocz(sizeof(TinyAlloc)); 170 al->p = al->buffer = tcc_malloc(size); 171 al->limit = limit; 172 al->size = size; 173 if (pal) *pal = al; 174 return al; 175 } 176 177 static void tal_delete(TinyAlloc *al) 178 { 179 TinyAlloc *next; 180 181 tail_call: 182 if (!al) 183 return; 184 #ifdef TAL_INFO 185 fprintf(stderr, "limit=%5d, size=%5g MB, nb_peak=%6d, nb_total=%8d, nb_missed=%6d, usage=%5.1f%%\n", 186 al->limit, al->size / 1024.0 / 1024.0, al->nb_peak, al->nb_total, al->nb_missed, 187 (al->peak_p - al->buffer) * 100.0 / al->size); 188 #endif 189 #ifdef TAL_DEBUG 190 if (al->nb_allocs > 0) { 191 uint8_t *p; 192 fprintf(stderr, "TAL_DEBUG: memory leak %d chunk(s) (limit= %d)\n", 193 al->nb_allocs, al->limit); 194 p = al->buffer; 195 while (p < al->p) { 196 tal_header_t *header = (tal_header_t *)p; 197 if (header->line_num > 0) { 198 fprintf(stderr, "%s:%d: chunk of %d bytes leaked\n", 199 header->file_name, header->line_num, header->size); 200 } 201 p += header->size + sizeof(tal_header_t); 202 } 203 #if MEM_DEBUG-0 == 2 204 exit(2); 205 #endif 206 } 207 #endif 208 next = al->next; 209 tcc_free(al->buffer); 210 tcc_free(al); 211 al = next; 212 goto tail_call; 213 } 214 215 static void tal_free_impl(TinyAlloc *al, void *p TAL_DEBUG_PARAMS) 216 { 217 if (!p) 218 return; 219 tail_call: 220 if (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size) { 221 #ifdef TAL_DEBUG 222 tal_header_t *header = (((tal_header_t *)p) - 1); 223 if (header->line_num < 0) { 224 fprintf(stderr, "%s:%d: TAL_DEBUG: double frees chunk from\n", 225 file, line); 226 fprintf(stderr, "%s:%d: %d bytes\n", 227 header->file_name, (int)-header->line_num, (int)header->size); 228 } else 229 header->line_num = -header->line_num; 230 #endif 231 al->nb_allocs--; 232 if (!al->nb_allocs) 233 al->p = al->buffer; 234 } else if (al->next) { 235 al = al->next; 236 goto tail_call; 237 } 238 else 239 tcc_free(p); 240 } 241 242 static void *tal_realloc_impl(TinyAlloc **pal, void *p, unsigned size TAL_DEBUG_PARAMS) 243 { 244 tal_header_t *header; 245 void *ret; 246 int is_own; 247 unsigned adj_size = (size + 3) & -4; 248 TinyAlloc *al = *pal; 249 250 tail_call: 251 is_own = (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size); 252 if ((!p || is_own) && size <= al->limit) { 253 if (al->p + adj_size + sizeof(tal_header_t) < al->buffer + al->size) { 254 header = (tal_header_t *)al->p; 255 header->size = adj_size; 256 #ifdef TAL_DEBUG 257 { int ofs = strlen(file) - TAL_DEBUG_FILE_LEN; 258 strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), TAL_DEBUG_FILE_LEN); 259 header->file_name[TAL_DEBUG_FILE_LEN] = 0; 260 header->line_num = line; } 261 #endif 262 ret = al->p + sizeof(tal_header_t); 263 al->p += adj_size + sizeof(tal_header_t); 264 if (is_own) { 265 header = (((tal_header_t *)p) - 1); 266 memcpy(ret, p, header->size); 267 #ifdef TAL_DEBUG 268 header->line_num = -header->line_num; 269 #endif 270 } else { 271 al->nb_allocs++; 272 } 273 #ifdef TAL_INFO 274 if (al->nb_peak < al->nb_allocs) 275 al->nb_peak = al->nb_allocs; 276 if (al->peak_p < al->p) 277 al->peak_p = al->p; 278 al->nb_total++; 279 #endif 280 return ret; 281 } else if (is_own) { 282 al->nb_allocs--; 283 ret = tal_realloc(*pal, 0, size); 284 header = (((tal_header_t *)p) - 1); 285 memcpy(ret, p, header->size); 286 #ifdef TAL_DEBUG 287 header->line_num = -header->line_num; 288 #endif 289 return ret; 290 } 291 if (al->next) { 292 al = al->next; 293 } else { 294 TinyAlloc *bottom = al, *next = al->top ? al->top : al; 295 296 al = tal_new(pal, next->limit, next->size * 2); 297 al->next = next; 298 bottom->top = al; 299 } 300 goto tail_call; 301 } 302 if (is_own) { 303 al->nb_allocs--; 304 ret = tcc_malloc(size); 305 header = (((tal_header_t *)p) - 1); 306 memcpy(ret, p, header->size); 307 #ifdef TAL_DEBUG 308 header->line_num = -header->line_num; 309 #endif 310 } else if (al->next) { 311 al = al->next; 312 goto tail_call; 313 } else 314 ret = tcc_realloc(p, size); 315 #ifdef TAL_INFO 316 al->nb_missed++; 317 #endif 318 return ret; 319 } 320 321 #endif /* USE_TAL */ 322 323 /* ------------------------------------------------------------------------- */ 103 324 /* CString handling */ 104 325 static void cstr_realloc(CString *cstr, int new_size) 105 326 { 106 327 int size; 107 void *data;108 328 109 329 size = cstr->size_allocated; 110 if (size == 0)330 if (size < 8) 111 331 size = 8; /* no need to allocate a too small first string */ 112 332 while (size < new_size) 113 333 size = size * 2; 114 data = tcc_realloc(cstr->data_allocated, size); 115 cstr->data_allocated = data; 334 cstr->data = tal_realloc(cstr_alloc, cstr->data, size); 116 335 cstr->size_allocated = size; 117 cstr->data = data;118 336 } 119 337 120 338 /* add a byte */ 121 ST_ FUNCvoid cstr_ccat(CString *cstr, int ch)339 ST_INLN void cstr_ccat(CString *cstr, int ch) 122 340 { 123 341 int size; … … 129 347 } 130 348 131 ST_FUNC void cstr_cat(CString *cstr, const char *str )132 { 133 int c;134 for(;;) {135 c = *str;136 if (c == '\0')137 break;138 cstr_ ccat(cstr, c);139 str++;140 }349 ST_FUNC void cstr_cat(CString *cstr, const char *str, int len) 350 { 351 int size; 352 if (len <= 0) 353 len = strlen(str) + 1 + len; 354 size = cstr->size + len; 355 if (size > cstr->size_allocated) 356 cstr_realloc(cstr, size); 357 memmove(((unsigned char *)cstr->data) + cstr->size, str, len); 358 cstr->size = size; 141 359 } 142 360 … … 160 378 ST_FUNC void cstr_free(CString *cstr) 161 379 { 162 t cc_free(cstr->data_allocated);380 tal_free(cstr_alloc, cstr->data); 163 381 cstr_new(cstr); 164 382 } … … 199 417 200 418 if (tok_ident >= SYM_FIRST_ANOM) 201 tcc_error("memory full ");419 tcc_error("memory full (symbols)"); 202 420 203 421 /* expand token table if needed */ … … 208 426 } 209 427 210 ts = t cc_malloc(sizeof(TokenSym) + len);428 ts = tal_realloc(toksym_alloc, 0, sizeof(TokenSym) + len); 211 429 table_ident[i] = ts; 212 430 ts->tok = tok_ident++; … … 224 442 225 443 #define TOK_HASH_INIT 1 226 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c)) 444 #define TOK_HASH_FUNC(h, c) ((h) + ((h) << 5) + ((h) >> 27) + (c)) 445 227 446 228 447 /* find a token and add it if not found */ … … 252 471 /* XXX: buffer overflow */ 253 472 /* XXX: float tokens */ 254 ST_FUNC char *get_tok_str(int v, CValue *cv) 255 { 256 static char buf[STRING_MAX_SIZE + 1]; 257 static CString cstr_buf; 258 CString *cstr; 473 ST_FUNC const char *get_tok_str(int v, CValue *cv) 474 { 259 475 char *p; 260 476 int i, len; 261 477 262 /* NOTE: to go faster, we give a fixed buffer for small strings */263 478 cstr_reset(&cstr_buf); 264 cstr_buf.data = buf; 265 cstr_buf.size_allocated = sizeof(buf); 266 p = buf; 479 p = cstr_buf.data; 267 480 268 481 switch(v) { 269 482 case TOK_CINT: 270 483 case TOK_CUINT: 271 /* XXX: not quite exact, but only useful for testing */ 272 sprintf(p, "%u", cv->ui); 273 break; 484 case TOK_CLONG: 485 case TOK_CULONG: 274 486 case TOK_CLLONG: 275 487 case TOK_CULLONG: 276 488 /* XXX: not quite exact, but only useful for testing */ 277 489 #ifdef _WIN32 278 sprintf(p, "%u", (unsigned)cv-> ull);490 sprintf(p, "%u", (unsigned)cv->i); 279 491 #else 280 sprintf(p, "% Lu", cv->ull);492 sprintf(p, "%llu", (unsigned long long)cv->i); 281 493 #endif 282 494 break; … … 290 502 break; 291 503 case TOK_PPNUM: 292 cstr = cv->cstr; 293 len = cstr->size - 1; 294 for(i=0;i<len;i++) 295 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]); 296 cstr_ccat(&cstr_buf, '\0'); 297 break; 504 case TOK_PPSTR: 505 return (char*)cv->str.data; 298 506 case TOK_LSTR: 299 507 cstr_ccat(&cstr_buf, 'L'); 300 508 case TOK_STR: 301 cstr = cv->cstr;302 509 cstr_ccat(&cstr_buf, '\"'); 303 510 if (v == TOK_STR) { 304 len = c str->size - 1;511 len = cv->str.size - 1; 305 512 for(i=0;i<len;i++) 306 add_char(&cstr_buf, ((unsigned char *)c str->data)[i]);513 add_char(&cstr_buf, ((unsigned char *)cv->str.data)[i]); 307 514 } else { 308 len = (c str->size / sizeof(nwchar_t)) - 1;515 len = (cv->str.size / sizeof(nwchar_t)) - 1; 309 516 for(i=0;i<len;i++) 310 add_char(&cstr_buf, ((nwchar_t *)c str->data)[i]);517 add_char(&cstr_buf, ((nwchar_t *)cv->str.data)[i]); 311 518 } 312 519 cstr_ccat(&cstr_buf, '\"'); 313 520 cstr_ccat(&cstr_buf, '\0'); 314 521 break; 522 523 case TOK_CFLOAT: 524 cstr_cat(&cstr_buf, "<float>", 0); 525 break; 526 case TOK_CDOUBLE: 527 cstr_cat(&cstr_buf, "<double>", 0); 528 break; 529 case TOK_CLDOUBLE: 530 cstr_cat(&cstr_buf, "<long double>", 0); 531 break; 532 case TOK_LINENUM: 533 cstr_cat(&cstr_buf, "<linenumber>", 0); 534 break; 535 536 /* above tokens have value, the ones below don't */ 315 537 case TOK_LT: 316 538 v = '<'; … … 325 547 case TOK_A_SAR: 326 548 return strcpy(p, ">>="); 549 case TOK_EOF: 550 return strcpy(p, "<eof>"); 327 551 default: 328 552 if (v < TOK_IDENT) { … … 334 558 *p++ = q[1]; 335 559 *p = '\0'; 336 return buf;560 return cstr_buf.data; 337 561 } 338 562 q += 3; 339 563 } 564 if (v >= 127) { 565 sprintf(cstr_buf.data, "<%02x>", v); 566 return cstr_buf.data; 567 } 340 568 addv: 341 569 *p++ = v; … … 355 583 } 356 584 357 /* fill input buffer and peek next char */ 358 static int tcc_peekc_slow(BufferedFile *bf) 359 { 585 /* return the current character, handling end of block if necessary 586 (but not stray) */ 587 ST_FUNC int handle_eob(void) 588 { 589 BufferedFile *bf = file; 360 590 int len; 591 361 592 /* only tries to read if really end of buffer */ 362 593 if (bf->buf_ptr >= bf->buf_end) { 363 if (bf->fd != -1) {594 if (bf->fd >= 0) { 364 595 #if defined(PARSE_DEBUG) 365 len = 8;596 len = 1; 366 597 #else 367 598 len = IO_BUF_SIZE; … … 384 615 return CH_EOF; 385 616 } 386 }387 388 /* return the current character, handling end of block if necessary389 (but not stray) */390 ST_FUNC int handle_eob(void)391 {392 return tcc_peekc_slow(file);393 617 } 394 618 … … 436 660 int c; 437 661 662 file->buf_ptr = p; 438 663 if (p >= file->buf_end) { 439 file->buf_ptr = p;440 664 c = handle_eob(); 665 if (c != '\\') 666 return c; 441 667 p = file->buf_ptr; 442 if (c == '\\') 443 goto parse_stray; 444 } else { 445 parse_stray: 446 file->buf_ptr = p; 447 ch = *p; 448 handle_stray(); 449 p = file->buf_ptr; 450 c = *p; 451 } 668 } 669 ch = *p; 670 if (handle_stray_noerror()) { 671 if (!(parse_flags & PARSE_FLAG_ACCEPT_STRAYS)) 672 tcc_error("stray '\\' in program"); 673 *--file->buf_ptr = '\\'; 674 } 675 p = file->buf_ptr; 676 c = *p; 452 677 return c; 453 678 } … … 485 710 handle_stray(); 486 711 } 487 488 712 489 713 /* single line C++ comments */ … … 528 752 { 529 753 int c; 530 754 531 755 p++; 532 756 for(;;) { … … 558 782 c = handle_eob(); 559 783 p = file->buf_ptr; 784 if (c == CH_EOF) 785 tcc_error("unexpected end of file in comment"); 560 786 if (c == '\\') { 561 787 /* skip '\[\r]\n', otherwise just skip the stray */ … … 598 824 } 599 825 826 ST_FUNC int set_idnum(int c, int val) 827 { 828 int prev = isidnum_table[c - CH_EOF]; 829 isidnum_table[c - CH_EOF] = val; 830 return prev; 831 } 832 600 833 #define cinp minp 601 834 602 835 static inline void skip_spaces(void) 603 836 { 604 while (is _space(ch))837 while (isidnum_table[ch - CH_EOF] & IS_SPC) 605 838 cinp(); 606 839 } … … 608 841 static inline int check_space(int t, int *spc) 609 842 { 610 if ( is_space(t)) {843 if (t < 256 && (isidnum_table[t - CH_EOF] & IS_SPC)) { 611 844 if (*spc) 612 845 return 1; … … 756 989 else if (tok == TOK_LINEFEED) 757 990 goto redo_start; 758 } 991 else if (parse_flags & PARSE_FLAG_ASM_FILE) 992 p = parse_line_comment(p - 1); 993 } else if (parse_flags & PARSE_FLAG_ASM_FILE) 994 p = parse_line_comment(p - 1); 759 995 break; 760 996 _default: … … 769 1005 } 770 1006 771 /* ParseState handling */ 772 773 /* XXX: currently, no include file info is stored. Thus, we cannot display 774 accurate messages if the function or data definition spans multiple 775 files */ 776 777 /* save current parse state in 's' */ 778 ST_FUNC void save_parse_state(ParseState *s) 779 { 780 s->line_num = file->line_num; 781 s->macro_ptr = macro_ptr; 782 s->tok = tok; 783 s->tokc = tokc; 784 } 785 786 /* restore parse state from 's' */ 787 ST_FUNC void restore_parse_state(ParseState *s) 788 { 789 file->line_num = s->line_num; 790 macro_ptr = s->macro_ptr; 791 tok = s->tok; 792 tokc = s->tokc; 793 } 794 1007 #if 0 795 1008 /* return the number of additional 'ints' necessary to store the 796 1009 token */ 797 static inline int tok_ ext_size(int t)798 { 799 switch( t) {1010 static inline int tok_size(const int *p) 1011 { 1012 switch(*p) { 800 1013 /* 4 bytes */ 801 1014 case TOK_CINT: … … 805 1018 case TOK_CFLOAT: 806 1019 case TOK_LINENUM: 807 return 1 ;1020 return 1 + 1; 808 1021 case TOK_STR: 809 1022 case TOK_LSTR: 810 1023 case TOK_PPNUM: 811 tcc_error("unsupported token"); 812 return 1; 1024 case TOK_PPSTR: 1025 return 1 + ((sizeof(CString) + ((CString *)(p+1))->size + 3) >> 2); 1026 case TOK_CLONG: 1027 case TOK_CULONG: 1028 return 1 + LONG_SIZE / 4; 813 1029 case TOK_CDOUBLE: 814 1030 case TOK_CLLONG: 815 1031 case TOK_CULLONG: 816 return 2;1032 return 1 + 2; 817 1033 case TOK_CLDOUBLE: 818 return LDOUBLE_SIZE / 4;1034 return 1 + LDOUBLE_SIZE / 4; 819 1035 default: 820 return 0; 821 } 822 } 1036 return 1 + 0; 1037 } 1038 } 1039 #endif 823 1040 824 1041 /* token string handling */ 825 826 1042 ST_INLN void tok_str_new(TokenString *s) 827 1043 { 828 1044 s->str = NULL; 829 s->len = 0;1045 s->len = s->lastlen = 0; 830 1046 s->allocated_len = 0; 831 1047 s->last_line_num = -1; 832 1048 } 833 1049 834 ST_FUNC void tok_str_free(int *str) 835 { 836 tcc_free(str); 837 } 838 839 static int *tok_str_realloc(TokenString *s) 840 { 841 int *str, len; 842 843 if (s->allocated_len == 0) { 844 len = 8; 845 } else { 846 len = s->allocated_len * 2; 847 } 848 str = tcc_realloc(s->str, len * sizeof(int)); 849 s->allocated_len = len; 850 s->str = str; 1050 ST_FUNC TokenString *tok_str_alloc(void) 1051 { 1052 TokenString *str = tal_realloc(tokstr_alloc, 0, sizeof *str); 1053 tok_str_new(str); 851 1054 return str; 1055 } 1056 1057 ST_FUNC int *tok_str_dup(TokenString *s) 1058 { 1059 int *str; 1060 1061 str = tal_realloc(tokstr_alloc, 0, s->len * sizeof(int)); 1062 memcpy(str, s->str, s->len * sizeof(int)); 1063 return str; 1064 } 1065 1066 ST_FUNC void tok_str_free_str(int *str) 1067 { 1068 tal_free(tokstr_alloc, str); 1069 } 1070 1071 ST_FUNC void tok_str_free(TokenString *str) 1072 { 1073 tok_str_free_str(str->str); 1074 tal_free(tokstr_alloc, str); 1075 } 1076 1077 ST_FUNC int *tok_str_realloc(TokenString *s, int new_size) 1078 { 1079 int *str, size; 1080 1081 size = s->allocated_len; 1082 if (size < 16) 1083 size = 16; 1084 while (size < new_size) 1085 size = size * 2; 1086 if (size > s->allocated_len) { 1087 str = tal_realloc(tokstr_alloc, s->str, size * sizeof(int)); 1088 s->allocated_len = size; 1089 s->str = str; 1090 } 1091 return s->str; 852 1092 } 853 1093 … … 859 1099 str = s->str; 860 1100 if (len >= s->allocated_len) 861 str = tok_str_realloc(s );1101 str = tok_str_realloc(s, len + 1); 862 1102 str[len++] = t; 863 1103 s->len = len; 864 1104 } 865 1105 1106 ST_FUNC void begin_macro(TokenString *str, int alloc) 1107 { 1108 str->alloc = alloc; 1109 str->prev = macro_stack; 1110 str->prev_ptr = macro_ptr; 1111 str->save_line_num = file->line_num; 1112 macro_ptr = str->str; 1113 macro_stack = str; 1114 } 1115 1116 ST_FUNC void end_macro(void) 1117 { 1118 TokenString *str = macro_stack; 1119 macro_stack = str->prev; 1120 macro_ptr = str->prev_ptr; 1121 file->line_num = str->save_line_num; 1122 if (str->alloc == 2) { 1123 str->alloc = 3; /* just mark as finished */ 1124 } else { 1125 tok_str_free(str); 1126 } 1127 } 1128 866 1129 static void tok_str_add2(TokenString *s, int t, CValue *cv) 867 1130 { 868 1131 int len, *str; 869 1132 870 len = s->l en;1133 len = s->lastlen = s->len; 871 1134 str = s->str; 872 1135 873 1136 /* allocate space for worst case */ 874 if (len + TOK_MAX_SIZE > s->allocated_len)875 str = tok_str_realloc(s );1137 if (len + TOK_MAX_SIZE >= s->allocated_len) 1138 str = tok_str_realloc(s, len + TOK_MAX_SIZE + 1); 876 1139 str[len++] = t; 877 1140 switch(t) { … … 882 1145 case TOK_CFLOAT: 883 1146 case TOK_LINENUM: 1147 #if LONG_SIZE == 4 1148 case TOK_CLONG: 1149 case TOK_CULONG: 1150 #endif 884 1151 str[len++] = cv->tab[0]; 885 1152 break; 886 1153 case TOK_PPNUM: 1154 case TOK_PPSTR: 887 1155 case TOK_STR: 888 1156 case TOK_LSTR: 889 1157 { 890 int nb_words; 891 CString *cstr; 892 893 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2; 894 while ((len + nb_words) > s->allocated_len) 895 str = tok_str_realloc(s); 896 cstr = (CString *)(str + len); 897 cstr->data = NULL; 898 cstr->size = cv->cstr->size; 899 cstr->data_allocated = NULL; 900 cstr->size_allocated = cstr->size; 901 memcpy((char *)cstr + sizeof(CString), 902 cv->cstr->data, cstr->size); 1158 /* Insert the string into the int array. */ 1159 size_t nb_words = 1160 1 + (cv->str.size + sizeof(int) - 1) / sizeof(int); 1161 if (len + nb_words >= s->allocated_len) 1162 str = tok_str_realloc(s, len + nb_words + 1); 1163 str[len] = cv->str.size; 1164 memcpy(&str[len + 1], cv->str.data, cv->str.size); 903 1165 len += nb_words; 904 1166 } … … 907 1169 case TOK_CLLONG: 908 1170 case TOK_CULLONG: 1171 #if LONG_SIZE == 8 1172 case TOK_CLONG: 1173 case TOK_CULONG: 1174 #endif 909 1175 #if LDOUBLE_SIZE == 8 910 1176 case TOK_CLDOUBLE: … … 957 1223 tab = cv->tab; 958 1224 switch(*t = *p++) { 1225 #if LONG_SIZE == 4 1226 case TOK_CLONG: 1227 #endif 959 1228 case TOK_CINT: 960 case TOK_CUINT:961 1229 case TOK_CCHAR: 962 1230 case TOK_LCHAR: 1231 case TOK_LINENUM: 1232 cv->i = *p++; 1233 break; 1234 #if LONG_SIZE == 4 1235 case TOK_CULONG: 1236 #endif 1237 case TOK_CUINT: 1238 cv->i = (unsigned)*p++; 1239 break; 963 1240 case TOK_CFLOAT: 964 case TOK_LINENUM: 965 tab[0] = *p++; 966 break; 1241 tab[0] = *p++; 1242 break; 967 1243 case TOK_STR: 968 1244 case TOK_LSTR: 969 1245 case TOK_PPNUM: 970 cv->cstr = (CString *)p; 971 cv->cstr->data = (char *)p + sizeof(CString); 972 p += (sizeof(CString) + cv->cstr->size + 3) >> 2; 1246 case TOK_PPSTR: 1247 cv->str.size = *p++; 1248 cv->str.data = p; 1249 p += (cv->str.size + sizeof(int) - 1) / sizeof(int); 973 1250 break; 974 1251 case TOK_CDOUBLE: 975 1252 case TOK_CLLONG: 976 1253 case TOK_CULLONG: 1254 #if LONG_SIZE == 8 1255 case TOK_CLONG: 1256 case TOK_CULONG: 1257 #endif 977 1258 n = 2; 978 1259 goto copy; … … 1000 1281 static int macro_is_equal(const int *a, const int *b) 1001 1282 { 1002 char buf[STRING_MAX_SIZE + 1];1003 1283 CValue cv; 1004 1284 int t; 1285 1286 if (!a || !b) 1287 return 1; 1288 1005 1289 while (*a && *b) { 1290 /* first time preallocate macro_equal_buf, next time only reset position to start */ 1291 cstr_reset(¯o_equal_buf); 1006 1292 TOK_GET(&t, &a, &cv); 1007 pstrcpy(buf, sizeof buf, get_tok_str(t, &cv));1293 cstr_cat(¯o_equal_buf, get_tok_str(t, &cv), 0); 1008 1294 TOK_GET(&t, &b, &cv); 1009 if (strcmp( buf, get_tok_str(t, &cv)))1295 if (strcmp(macro_equal_buf.data, get_tok_str(t, &cv))) 1010 1296 return 0; 1011 1297 } … … 1016 1302 ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg) 1017 1303 { 1018 Sym *s; 1019 1020 s = define_find(v); 1021 if (s && !macro_is_equal(s->d, str)) 1022 tcc_warning("%s redefined", get_tok_str(v, NULL)); 1023 1304 Sym *s, *o; 1305 1306 o = define_find(v); 1024 1307 s = sym_push2(&define_stack, v, macro_type, 0); 1025 1308 s->d = str; 1026 1309 s->next = first_arg; 1027 1310 table_ident[v - TOK_IDENT]->sym_define = s; 1311 1312 if (o && !macro_is_equal(o->d, s->d)) 1313 tcc_warning("%s redefined", get_tok_str(v, NULL)); 1028 1314 } 1029 1315 … … 1031 1317 ST_FUNC void define_undef(Sym *s) 1032 1318 { 1033 int v; 1034 v = s->v; 1319 int v = s->v; 1035 1320 if (v >= TOK_IDENT && v < tok_ident) 1036 1321 table_ident[v - TOK_IDENT]->sym_define = NULL; 1037 s->v = 0;1038 1322 } 1039 1323 … … 1049 1333 ST_FUNC void free_defines(Sym *b) 1050 1334 { 1051 Sym *top, *top1; 1052 int v; 1053 1054 top = define_stack; 1055 while (top != b) { 1056 top1 = top->prev; 1057 /* do not free args or predefined defines */ 1058 if (top->d) 1059 tok_str_free(top->d); 1060 v = top->v; 1061 if (v >= TOK_IDENT && v < tok_ident) 1062 table_ident[v - TOK_IDENT]->sym_define = NULL; 1335 while (define_stack != b) { 1336 Sym *top = define_stack; 1337 define_stack = top->prev; 1338 tok_str_free_str(top->d); 1339 define_undef(top); 1063 1340 sym_free(top); 1064 top = top1; 1065 } 1066 define_stack = b; 1341 } 1342 1343 /* restore remaining (-D or predefined) symbols if they were 1344 #undef'd in the file */ 1345 while (b) { 1346 int v = b->v; 1347 if (v >= TOK_IDENT && v < tok_ident) { 1348 Sym **d = &table_ident[v - TOK_IDENT]->sym_define; 1349 if (!*d) 1350 *d = b; 1351 } 1352 b = b->prev; 1353 } 1067 1354 } 1068 1355 … … 1095 1382 /* pop labels until element last is reached. Look if any labels are 1096 1383 undefined. Define symbols if '&&label' was used. */ 1097 ST_FUNC void label_pop(Sym **ptop, Sym *slast )1384 ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep) 1098 1385 { 1099 1386 Sym *s, *s1; … … 1114 1401 /* remove label */ 1115 1402 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok; 1116 sym_free(s); 1117 } 1118 *ptop = slast; 1403 if (!keep) 1404 sym_free(s); 1405 } 1406 if (!keep) 1407 *ptop = slast; 1408 } 1409 1410 /* fake the nth "#if defined test_..." for tcc -dt -run */ 1411 static void maybe_run_test(TCCState *s) 1412 { 1413 const char *p; 1414 if (s->include_stack_ptr != s->include_stack) 1415 return; 1416 p = get_tok_str(tok, NULL); 1417 if (0 != memcmp(p, "test_", 5)) 1418 return; 1419 if (0 != --s->run_test) 1420 return; 1421 fprintf(s->ppfp, "\n[%s]\n" + !(s->dflag & 32), p), fflush(s->ppfp); 1422 define_push(tok, MACRO_OBJ, NULL, NULL); 1119 1423 } 1120 1424 … … 1123 1427 { 1124 1428 int c, t; 1125 TokenString str;1429 TokenString *str; 1126 1430 1127 tok_str_new(&str); 1431 str = tok_str_alloc(); 1432 pp_expr = 1; 1128 1433 while (tok != TOK_LINEFEED && tok != TOK_EOF) { 1129 1434 next(); /* do macro subst */ … … 1133 1438 if (t == '(') 1134 1439 next_nomacro(); 1440 if (tok < TOK_IDENT) 1441 expect("identifier"); 1442 if (tcc_state->run_test) 1443 maybe_run_test(tcc_state); 1135 1444 c = define_find(tok) != 0; 1136 if (t == '(') 1445 if (t == '(') { 1137 1446 next_nomacro(); 1447 if (tok != ')') 1448 expect("')'"); 1449 } 1138 1450 tok = TOK_CINT; 1139 1451 tokc.i = c; … … 1143 1455 tokc.i = 0; 1144 1456 } 1145 tok_str_add_tok(&str); 1146 } 1147 tok_str_add(&str, -1); /* simulate end of file */ 1148 tok_str_add(&str, 0); 1457 tok_str_add_tok(str); 1458 } 1459 pp_expr = 0; 1460 tok_str_add(str, -1); /* simulate end of file */ 1461 tok_str_add(str, 0); 1149 1462 /* now evaluate C constant expression */ 1150 macro_ptr = str.str;1463 begin_macro(str, 1); 1151 1464 next(); 1152 1465 c = expr_const(); 1153 macro_ptr = NULL; 1154 tok_str_free(str.str); 1466 end_macro(); 1155 1467 return c != 0; 1156 1468 } 1157 1469 1158 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)1159 static void tok_print(int *str)1160 {1161 int t;1162 CValue cval;1163 1164 printf("<");1165 while (1) {1166 TOK_GET(&t, &str, &cval);1167 if (!t)1168 break;1169 printf("%s", get_tok_str(t, &cval));1170 }1171 printf(">\n");1172 }1173 #endif1174 1470 1175 1471 /* parse after #define */ … … 1178 1474 Sym *s, *first, **ps; 1179 1475 int v, t, varg, is_vaargs, spc; 1180 TokenString str;1181 1476 int saved_parse_flags = parse_flags; 1477 1182 1478 v = tok; 1183 if (v < TOK_IDENT )1479 if (v < TOK_IDENT || v == TOK_DEFINED) 1184 1480 tcc_error("invalid macro name '%s'", get_tok_str(tok, &tokc)); 1185 1481 /* XXX: should check if same macro (ANSI) */ 1186 1482 first = NULL; 1187 1483 t = MACRO_OBJ; 1484 /* We have to parse the whole define as if not in asm mode, in particular 1485 no line comment with '#' must be ignored. Also for function 1486 macros the argument list must be parsed without '.' being an ID 1487 character. */ 1488 parse_flags = ((parse_flags & ~PARSE_FLAG_ASM_FILE) | PARSE_FLAG_SPACES); 1188 1489 /* '(' must be just after macro definition for MACRO_FUNC */ 1189 1490 next_nomacro_spc(); 1190 1491 if (tok == '(') { 1492 int dotid = set_idnum('.', 0); 1191 1493 next_nomacro(); 1192 1494 ps = &first; 1193 while (tok != ')') {1495 if (tok != ')') for (;;) { 1194 1496 varg = tok; 1195 1497 next_nomacro(); … … 1203 1505 } 1204 1506 if (varg < TOK_IDENT) 1205 tcc_error("badly punctuated parameter list"); 1507 bad_list: 1508 tcc_error("bad macro parameter list"); 1206 1509 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0); 1207 1510 *ps = s; 1208 1511 ps = &s->next; 1209 if (tok != ',')1512 if (tok == ')') 1210 1513 break; 1514 if (tok != ',' || is_vaargs) 1515 goto bad_list; 1211 1516 next_nomacro(); 1212 1517 } 1213 if (tok == ')') 1214 next_nomacro_spc(); 1518 next_nomacro_spc(); 1215 1519 t = MACRO_FUNC; 1216 } 1217 tok_str_new(&str); 1520 set_idnum('.', dotid); 1521 } 1522 1523 tokstr_buf.len = 0; 1218 1524 spc = 2; 1219 /* EOF testing necessary for '-D' handling */ 1525 parse_flags |= PARSE_FLAG_ACCEPT_STRAYS | PARSE_FLAG_SPACES | PARSE_FLAG_LINEFEED; 1526 /* The body of a macro definition should be parsed such that identifiers 1527 are parsed like the file mode determines (i.e. with '.' being an 1528 ID character in asm mode). But '#' should be retained instead of 1529 regarded as line comment leader, so still don't set ASM_FILE 1530 in parse_flags. */ 1220 1531 while (tok != TOK_LINEFEED && tok != TOK_EOF) { 1221 /* remove spaces around ## and after '#' */ 1532 /* remove spaces around ## and after '#' */ 1222 1533 if (TOK_TWOSHARPS == tok) { 1534 if (2 == spc) 1535 goto bad_twosharp; 1223 1536 if (1 == spc) 1224 --str.len; 1225 spc = 2; 1537 --tokstr_buf.len; 1538 spc = 3; 1539 tok = TOK_PPJOIN; 1226 1540 } else if ('#' == tok) { 1227 spc = 2;1541 spc = 4; 1228 1542 } else if (check_space(tok, &spc)) { 1229 1543 goto skip; 1230 1544 } 1231 tok_str_add2(& str, tok, &tokc);1545 tok_str_add2(&tokstr_buf, tok, &tokc); 1232 1546 skip: 1233 1547 next_nomacro_spc(); 1234 1548 } 1549 1550 parse_flags = saved_parse_flags; 1235 1551 if (spc == 1) 1236 --str.len; /* remove trailing space */ 1237 tok_str_add(&str, 0); 1238 #ifdef PP_DEBUG 1239 printf("define %s %d: ", get_tok_str(v, NULL), t); 1240 tok_print(str.str); 1241 #endif 1242 define_push(v, t, str.str, first); 1243 } 1244 1245 static inline int hash_cached_include(const char *filename) 1552 --tokstr_buf.len; /* remove trailing space */ 1553 tok_str_add(&tokstr_buf, 0); 1554 if (3 == spc) 1555 bad_twosharp: 1556 tcc_error("'##' cannot appear at either end of macro"); 1557 define_push(v, t, tok_str_dup(&tokstr_buf), first); 1558 } 1559 1560 static CachedInclude *search_cached_include(TCCState *s1, const char *filename, int add) 1246 1561 { 1247 1562 const unsigned char *s; 1248 1563 unsigned int h; 1564 CachedInclude *e; 1565 int i; 1249 1566 1250 1567 h = TOK_HASH_INIT; 1251 s = filename;1568 s = (unsigned char *) filename; 1252 1569 while (*s) { 1570 #ifdef _WIN32 1571 h = TOK_HASH_FUNC(h, toup(*s)); 1572 #else 1253 1573 h = TOK_HASH_FUNC(h, *s); 1574 #endif 1254 1575 s++; 1255 1576 } 1256 1577 h &= (CACHED_INCLUDES_HASH_SIZE - 1); 1257 return h; 1258 } 1259 1260 static CachedInclude *search_cached_include(TCCState *s1, const char *filename) 1261 { 1262 CachedInclude *e; 1263 int i, h; 1264 h = hash_cached_include(filename); 1578 1265 1579 i = s1->cached_includes_hash[h]; 1266 1580 for(;;) { … … 1272 1586 i = e->hash_next; 1273 1587 } 1274 return NULL; 1275 } 1276 1277 static inline void add_cached_include(TCCState *s1, const char *filename, int ifndef_macro) 1278 { 1279 CachedInclude *e; 1280 int h; 1281 1282 if (search_cached_include(s1, filename)) 1283 return; 1284 #ifdef INC_DEBUG 1285 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL)); 1286 #endif 1588 if (!add) 1589 return NULL; 1590 1287 1591 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename)); 1288 1592 strcpy(e->filename, filename); 1289 e->ifndef_macro = ifndef_macro;1290 dynarray_add( (void ***)&s1->cached_includes, &s1->nb_cached_includes, e);1593 e->ifndef_macro = e->once = 0; 1594 dynarray_add(&s1->cached_includes, &s1->nb_cached_includes, e); 1291 1595 /* add in hash table */ 1292 h = hash_cached_include(filename);1293 1596 e->hash_next = s1->cached_includes_hash[h]; 1294 1597 s1->cached_includes_hash[h] = s1->nb_cached_includes; 1598 #ifdef INC_DEBUG 1599 printf("adding cached '%s'\n", filename); 1600 #endif 1601 return e; 1295 1602 } 1296 1603 1297 1604 static void pragma_parse(TCCState *s1) 1298 1605 { 1299 int val; 1300 1301 next(); 1302 if (tok == TOK_pack) { 1303 /* 1304 This may be: 1305 #pragma pack(1) // set 1306 #pragma pack() // reset to default 1307 #pragma pack(push,1) // push & set 1308 #pragma pack(pop) // restore previous 1309 */ 1606 next_nomacro(); 1607 if (tok == TOK_push_macro || tok == TOK_pop_macro) { 1608 int t = tok, v; 1609 Sym *s; 1610 1611 if (next(), tok != '(') 1612 goto pragma_err; 1613 if (next(), tok != TOK_STR) 1614 goto pragma_err; 1615 v = tok_alloc(tokc.str.data, tokc.str.size - 1)->tok; 1616 if (next(), tok != ')') 1617 goto pragma_err; 1618 if (t == TOK_push_macro) { 1619 while (NULL == (s = define_find(v))) 1620 define_push(v, 0, NULL, NULL); 1621 s->type.ref = s; /* set push boundary */ 1622 } else { 1623 for (s = define_stack; s; s = s->prev) 1624 if (s->v == v && s->type.ref == s) { 1625 s->type.ref = NULL; 1626 break; 1627 } 1628 } 1629 if (s) 1630 table_ident[v - TOK_IDENT]->sym_define = s->d ? s : NULL; 1631 else 1632 tcc_warning("unbalanced #pragma pop_macro"); 1633 pp_debug_tok = t, pp_debug_symv = v; 1634 1635 } else if (tok == TOK_once) { 1636 search_cached_include(s1, file->filename, 1)->once = pp_once; 1637 1638 } else if (s1->output_type == TCC_OUTPUT_PREPROCESS) { 1639 /* tcc -E: keep pragmas below unchanged */ 1640 unget_tok(' '); 1641 unget_tok(TOK_PRAGMA); 1642 unget_tok('#'); 1643 unget_tok(TOK_LINEFEED); 1644 1645 } else if (tok == TOK_pack) { 1646 /* This may be: 1647 #pragma pack(1) // set 1648 #pragma pack() // reset to default 1649 #pragma pack(push,1) // push & set 1650 #pragma pack(pop) // restore previous */ 1310 1651 next(); 1311 1652 skip('('); … … 1318 1659 s1->pack_stack_ptr--; 1319 1660 } else { 1320 val = 0;1661 int val = 0; 1321 1662 if (tok != ')') { 1322 1663 if (tok == TOK_ASM_push) { … … 1327 1668 skip(','); 1328 1669 } 1329 if (tok != TOK_CINT) { 1330 pack_error: 1331 tcc_error("invalid pack pragma"); 1332 } 1670 if (tok != TOK_CINT) 1671 goto pragma_err; 1333 1672 val = tokc.i; 1334 1673 if (val < 1 || val > 16 || (val & (val - 1)) != 0) 1335 goto p ack_error;1674 goto pragma_err; 1336 1675 next(); 1337 1676 } 1338 1677 *s1->pack_stack_ptr = val; 1339 skip(')'); 1340 } 1341 } 1678 } 1679 if (tok != ')') 1680 goto pragma_err; 1681 1682 } else if (tok == TOK_comment) { 1683 char *p; int t; 1684 next(); 1685 skip('('); 1686 t = tok; 1687 next(); 1688 skip(','); 1689 if (tok != TOK_STR) 1690 goto pragma_err; 1691 p = tcc_strdup((char *)tokc.str.data); 1692 next(); 1693 if (tok != ')') 1694 goto pragma_err; 1695 if (t == TOK_lib) { 1696 dynarray_add(&s1->pragma_libs, &s1->nb_pragma_libs, p); 1697 } else { 1698 if (t == TOK_option) 1699 tcc_set_options(s1, p); 1700 tcc_free(p); 1701 } 1702 1703 } else if (s1->warn_unsupported) { 1704 tcc_warning("#pragma %s is ignored", get_tok_str(tok, &tokc)); 1705 } 1706 return; 1707 1708 pragma_err: 1709 tcc_error("malformed #pragma directive"); 1710 return; 1342 1711 } 1343 1712 … … 1351 1720 1352 1721 saved_parse_flags = parse_flags; 1353 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | 1354 PARSE_FLAG_LINEFEED; 1722 parse_flags = PARSE_FLAG_PREPROCESS 1723 | PARSE_FLAG_TOK_NUM 1724 | PARSE_FLAG_TOK_STR 1725 | PARSE_FLAG_LINEFEED 1726 | (parse_flags & PARSE_FLAG_ASM_FILE) 1727 ; 1728 1355 1729 next_nomacro(); 1356 1730 redo: 1357 1731 switch(tok) { 1358 1732 case TOK_DEFINE: 1733 pp_debug_tok = tok; 1359 1734 next_nomacro(); 1735 pp_debug_symv = tok; 1360 1736 parse_define(); 1361 1737 break; 1362 1738 case TOK_UNDEF: 1739 pp_debug_tok = tok; 1363 1740 next_nomacro(); 1741 pp_debug_symv = tok; 1364 1742 s = define_find(tok); 1365 1743 /* undefine symbol by putting an invalid name */ … … 1398 1776 #endif 1399 1777 } else { 1400 /* computed #include : either we have only strings or 1401 we have anything enclosed in '<>' */ 1778 int len; 1779 /* computed #include : concatenate everything up to linefeed, 1780 the result must be one of the two accepted forms. 1781 Don't convert pp-tokens to tokens here. */ 1782 parse_flags = (PARSE_FLAG_PREPROCESS 1783 | PARSE_FLAG_LINEFEED 1784 | (parse_flags & PARSE_FLAG_ASM_FILE)); 1402 1785 next(); 1403 1786 buf[0] = '\0'; 1404 if (tok == TOK_STR) { 1405 while (tok != TOK_LINEFEED) { 1406 if (tok != TOK_STR) { 1407 include_syntax: 1408 tcc_error("'#include' expects \"FILENAME\" or <FILENAME>"); 1409 } 1410 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data); 1411 next(); 1412 } 1413 c = '\"'; 1414 } else { 1415 int len; 1416 while (tok != TOK_LINEFEED) { 1417 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc)); 1418 next(); 1419 } 1420 len = strlen(buf); 1421 /* check syntax and remove '<>' */ 1422 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>') 1423 goto include_syntax; 1424 memmove(buf, buf + 1, len - 2); 1425 buf[len - 2] = '\0'; 1426 c = '>'; 1427 } 1787 while (tok != TOK_LINEFEED) { 1788 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc)); 1789 next(); 1790 } 1791 len = strlen(buf); 1792 /* check syntax and remove '<>|""' */ 1793 if ((len < 2 || ((buf[0] != '"' || buf[len-1] != '"') && 1794 (buf[0] != '<' || buf[len-1] != '>')))) 1795 tcc_error("'#include' expects \"FILENAME\" or <FILENAME>"); 1796 c = buf[len-1]; 1797 memmove(buf, buf + 1, len - 2); 1798 buf[len - 2] = '\0'; 1428 1799 } 1429 1800 … … 1432 1803 /* store current file in stack, but increment stack later below */ 1433 1804 *s1->include_stack_ptr = file; 1434 1435 n = s1->nb_include_paths + s1->nb_sysinclude_paths;1436 for ( i = -2; i < n; ++i) {1805 i = tok == TOK_INCLUDE_NEXT ? file->include_next_index : 0; 1806 n = 2 + s1->nb_include_paths + s1->nb_sysinclude_paths; 1807 for (; i < n; ++i) { 1437 1808 char buf1[sizeof file->filename]; 1438 1809 CachedInclude *e; 1439 BufferedFile **f;1440 1810 const char *path; 1441 1811 1442 if (i == -2) {1812 if (i == 0) { 1443 1813 /* check absolute include path */ 1444 1814 if (!IS_ABSPATH(buf)) 1445 1815 continue; 1446 1816 buf1[0] = 0; 1447 i = n; /* force end loop */ 1448 1449 } else if (i == -1) { 1450 /* search in current dir if "header.h" */ 1817 1818 } else if (i == 1) { 1819 /* search in file's dir if "header.h" */ 1451 1820 if (c != '\"') 1452 1821 continue; 1453 path = file->filename; 1822 /* https://savannah.nongnu.org/bugs/index.php?50847 */ 1823 path = file->true_filename; 1454 1824 pstrncpy(buf1, path, tcc_basename(path) - path); 1455 1825 1456 1826 } else { 1457 1827 /* search in all the include paths */ 1458 if (i < s1->nb_include_paths) 1459 path = s1->include_paths[i]; 1460 else 1461 path = s1->sysinclude_paths[i - s1->nb_include_paths]; 1828 int j = i - 2, k = j - s1->nb_include_paths; 1829 path = k < 0 ? s1->include_paths[j] : s1->sysinclude_paths[k]; 1462 1830 pstrcpy(buf1, sizeof(buf1), path); 1463 1831 pstrcat(buf1, sizeof(buf1), "/"); … … 1465 1833 1466 1834 pstrcat(buf1, sizeof(buf1), buf); 1467 1468 if (tok == TOK_INCLUDE_NEXT) 1469 for (f = s1->include_stack_ptr; f >= s1->include_stack; --f) 1470 if (0 == PATHCMP((*f)->filename, buf1)) { 1471 #ifdef INC_DEBUG 1472 printf("%s: #include_next skipping %s\n", file->filename, buf1); 1473 #endif 1474 goto include_trynext; 1475 } 1476 1477 e = search_cached_include(s1, buf1); 1478 if (e && define_find(e->ifndef_macro)) { 1835 e = search_cached_include(s1, buf1, 0); 1836 if (e && (define_find(e->ifndef_macro) || e->once == pp_once)) { 1479 1837 /* no need to parse the include because the 'ifndef macro' 1480 is defined */1838 is defined (or had #pragma once) */ 1481 1839 #ifdef INC_DEBUG 1482 1840 printf("%s: skipping cached %s\n", file->filename, buf1); … … 1486 1844 1487 1845 if (tcc_open(s1, buf1) < 0) 1488 include_trynext:1489 1846 continue; 1490 1847 1848 file->include_next_index = i + 1; 1491 1849 #ifdef INC_DEBUG 1492 1850 printf("%s: including %s\n", file->prev->filename, file->filename); 1493 1851 #endif 1494 1852 /* update target deps */ 1495 dynarray_add( (void ***)&s1->target_deps, &s1->nb_target_deps,1853 dynarray_add(&s1->target_deps, &s1->nb_target_deps, 1496 1854 tcc_strdup(buf1)); 1497 1855 /* push current file in stack */ … … 1530 1888 do_if: 1531 1889 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE) 1532 tcc_error("memory full ");1890 tcc_error("memory full (ifdef)"); 1533 1891 *s1->ifdef_stack_ptr++ = c; 1534 1892 goto test_skip; … … 1547 1905 tcc_error("#elif after #else"); 1548 1906 /* last #if/#elif expression was true: we skip */ 1549 if (c == 1) 1550 goto skip; 1551 c = expr_preprocess(); 1552 s1->ifdef_stack_ptr[-1] = c; 1907 if (c == 1) { 1908 c = 0; 1909 } else { 1910 c = expr_preprocess(); 1911 s1->ifdef_stack_ptr[-1] = c; 1912 } 1553 1913 test_else: 1554 1914 if (s1->ifdef_stack_ptr == file->ifdef_stack_ptr + 1) … … 1556 1916 test_skip: 1557 1917 if (!(c & 1)) { 1558 skip:1559 1918 preprocess_skip(); 1560 1919 is_bof = 0; … … 1580 1939 } 1581 1940 break; 1941 case TOK_PPNUM: 1942 n = strtoul((char*)tokc.str.data, &q, 10); 1943 goto _line_num; 1582 1944 case TOK_LINE: 1583 1945 next(); 1584 1946 if (tok != TOK_CINT) 1585 tcc_error("#line"); 1586 file->line_num = tokc.i - 1; /* the line number will be incremented after */ 1947 _line_err: 1948 tcc_error("wrong #line format"); 1949 n = tokc.i; 1950 _line_num: 1587 1951 next(); 1588 1952 if (tok != TOK_LINEFEED) { 1589 if (tok != TOK_STR) 1590 tcc_error("#line"); 1591 pstrcpy(file->filename, sizeof(file->filename), 1592 (char *)tokc.cstr->data); 1593 } 1953 if (tok == TOK_STR) { 1954 if (file->true_filename == file->filename) 1955 file->true_filename = tcc_strdup(file->filename); 1956 pstrcpy(file->filename, sizeof(file->filename), (char *)tokc.str.data); 1957 } else if (parse_flags & PARSE_FLAG_ASM_FILE) 1958 break; 1959 else 1960 goto _line_err; 1961 --n; 1962 } 1963 if (file->fd > 0) 1964 total_lines += file->line_num - n; 1965 file->line_num = n; 1966 if (s1->do_debug) 1967 put_stabs(file->filename, N_BINCL, 0, 0, 0); 1594 1968 break; 1595 1969 case TOK_ERROR: … … 1617 1991 pragma_parse(s1); 1618 1992 break; 1993 case TOK_LINEFEED: 1994 goto the_end; 1619 1995 default: 1620 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_PPNUM) { 1621 /* '!' is ignored to allow C scripts. numbers are ignored 1622 to emulate cpp behaviour */ 1623 } else { 1624 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS)) 1625 tcc_warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc)); 1626 else { 1627 /* this is a gas line comment in an 'S' file. */ 1628 file->buf_ptr = parse_line_comment(file->buf_ptr); 1629 goto the_end; 1630 } 1631 } 1632 break; 1996 /* ignore gas line comment in an 'S' file. */ 1997 if (saved_parse_flags & PARSE_FLAG_ASM_FILE) 1998 goto ignore; 1999 if (tok == '!' && is_bof) 2000 /* '!' is ignored at beginning to allow C scripts. */ 2001 goto ignore; 2002 tcc_warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc)); 2003 ignore: 2004 file->buf_ptr = parse_line_comment(file->buf_ptr - 1); 2005 goto the_end; 1633 2006 } 1634 2007 /* ignore other preprocess commands or #! for C scripts */ … … 1731 2104 break; 1732 2105 } 2106 } else if (is_long && c >= 0x80) { 2107 /* assume we are processing UTF-8 sequence */ 2108 /* reference: The Unicode Standard, Version 10.0, ch3.9 */ 2109 2110 int cont; /* count of continuation bytes */ 2111 int skip; /* how many bytes should skip when error occurred */ 2112 int i; 2113 2114 /* decode leading byte */ 2115 if (c < 0xC2) { 2116 skip = 1; goto invalid_utf8_sequence; 2117 } else if (c <= 0xDF) { 2118 cont = 1; n = c & 0x1f; 2119 } else if (c <= 0xEF) { 2120 cont = 2; n = c & 0xf; 2121 } else if (c <= 0xF4) { 2122 cont = 3; n = c & 0x7; 2123 } else { 2124 skip = 1; goto invalid_utf8_sequence; 2125 } 2126 2127 /* decode continuation bytes */ 2128 for (i = 1; i <= cont; i++) { 2129 int l = 0x80, h = 0xBF; 2130 2131 /* adjust limit for second byte */ 2132 if (i == 1) { 2133 switch (c) { 2134 case 0xE0: l = 0xA0; break; 2135 case 0xED: h = 0x9F; break; 2136 case 0xF0: l = 0x90; break; 2137 case 0xF4: h = 0x8F; break; 2138 } 2139 } 2140 2141 if (p[i] < l || p[i] > h) { 2142 skip = i; goto invalid_utf8_sequence; 2143 } 2144 2145 n = (n << 6) | (p[i] & 0x3f); 2146 } 2147 2148 /* advance pointer */ 2149 p += 1 + cont; 2150 c = n; 2151 goto add_char_nonext; 2152 2153 /* error handling */ 2154 invalid_utf8_sequence: 2155 tcc_warning("ill-formed UTF-8 subsequence starting with: \'\\x%x\'", c); 2156 c = 0xFFFD; 2157 p += skip; 2158 goto add_char_nonext; 2159 1733 2160 } 1734 2161 p++; … … 1736 2163 if (!is_long) 1737 2164 cstr_ccat(outstr, c); 1738 else 2165 else { 2166 #ifdef TCC_TARGET_PE 2167 /* store as UTF-16 */ 2168 if (c < 0x10000) { 2169 cstr_wccat(outstr, c); 2170 } else { 2171 c -= 0x10000; 2172 cstr_wccat(outstr, (c >> 10) + 0xD800); 2173 cstr_wccat(outstr, (c & 0x3FF) + 0xDC00); 2174 } 2175 #else 1739 2176 cstr_wccat(outstr, c); 2177 #endif 2178 } 1740 2179 } 1741 2180 /* add a trailing '\0' */ … … 1744 2183 else 1745 2184 cstr_wccat(outstr, '\0'); 2185 } 2186 2187 static void parse_string(const char *s, int len) 2188 { 2189 uint8_t buf[1000], *p = buf; 2190 int is_long, sep; 2191 2192 if ((is_long = *s == 'L')) 2193 ++s, --len; 2194 sep = *s++; 2195 len -= 2; 2196 if (len >= sizeof buf) 2197 p = tcc_malloc(len + 1); 2198 memcpy(p, s, len); 2199 p[len] = 0; 2200 2201 cstr_reset(&tokcstr); 2202 parse_escape_string(&tokcstr, p, is_long); 2203 if (p != buf) 2204 tcc_free(p); 2205 2206 if (sep == '\'') { 2207 int char_size, i, n, c; 2208 /* XXX: make it portable */ 2209 if (!is_long) 2210 tok = TOK_CCHAR, char_size = 1; 2211 else 2212 tok = TOK_LCHAR, char_size = sizeof(nwchar_t); 2213 n = tokcstr.size / char_size - 1; 2214 if (n < 1) 2215 tcc_error("empty character constant"); 2216 if (n > 1) 2217 tcc_warning("multi-character character constant"); 2218 for (c = i = 0; i < n; ++i) { 2219 if (is_long) 2220 c = ((nwchar_t *)tokcstr.data)[i]; 2221 else 2222 c = (c << 8) | ((char *)tokcstr.data)[i]; 2223 } 2224 tokc.i = c; 2225 } else { 2226 tokc.str.size = tokcstr.size; 2227 tokc.str.data = tokcstr.data; 2228 if (!is_long) 2229 tok = TOK_STR; 2230 else 2231 tok = TOK_LSTR; 2232 } 1746 2233 } 1747 2234 … … 1831 2318 shift = 4; 1832 2319 else 1833 shift = 2;2320 shift = 1; 1834 2321 bn_zero(bn); 1835 2322 q = token_buf; … … 1969 2456 } else { 1970 2457 unsigned long long n, n1; 1971 int lcount, ucount; 2458 int lcount, ucount, ov = 0; 2459 const char *p1; 1972 2460 1973 2461 /* integer number */ … … 1982 2470 t = *q++; 1983 2471 /* no need for checks except for base 10 / 8 errors */ 1984 if (t == '\0') {2472 if (t == '\0') 1985 2473 break; 1986 } else if (t >= 'a') {2474 else if (t >= 'a') 1987 2475 t = t - 'a' + 10; 1988 } else if (t >= 'A') {2476 else if (t >= 'A') 1989 2477 t = t - 'A' + 10; 1990 } else {2478 else 1991 2479 t = t - '0'; 1992 if (t >= b) 1993 tcc_error("invalid digit"); 1994 } 2480 if (t >= b) 2481 tcc_error("invalid digit"); 1995 2482 n1 = n; 1996 2483 n = n * b + t; 1997 2484 /* detect overflow */ 1998 /* XXX: this test is not reliable */ 1999 if (n < n1) 2000 tcc_error("integer constant overflow"); 2001 } 2002 2003 /* XXX: not exactly ANSI compliant */ 2004 if ((n & 0xffffffff00000000LL) != 0) { 2005 if ((n >> 63) != 0) 2006 tok = TOK_CULLONG; 2007 else 2008 tok = TOK_CLLONG; 2009 } else if (n > 0x7fffffff) { 2010 tok = TOK_CUINT; 2011 } else { 2012 tok = TOK_CINT; 2013 } 2014 lcount = 0; 2015 ucount = 0; 2485 if (n1 >= 0x1000000000000000ULL && n / b != n1) 2486 ov = 1; 2487 } 2488 2489 /* Determine the characteristics (unsigned and/or 64bit) the type of 2490 the constant must have according to the constant suffix(es) */ 2491 lcount = ucount = 0; 2492 p1 = p; 2016 2493 for(;;) { 2017 2494 t = toup(ch); … … 2019 2496 if (lcount >= 2) 2020 2497 tcc_error("three 'l's in integer constant"); 2498 if (lcount && *(p - 1) != ch) 2499 tcc_error("incorrect integer suffix: %s", p1); 2021 2500 lcount++; 2022 #if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE2023 if (lcount == 2) {2024 #endif2025 if (tok == TOK_CINT)2026 tok = TOK_CLLONG;2027 else if (tok == TOK_CUINT)2028 tok = TOK_CULLONG;2029 #if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE2030 }2031 #endif2032 2501 ch = *p++; 2033 2502 } else if (t == 'U') { … … 2035 2504 tcc_error("two 'u's in integer constant"); 2036 2505 ucount++; 2037 if (tok == TOK_CINT)2038 tok = TOK_CUINT;2039 else if (tok == TOK_CLLONG)2040 tok = TOK_CULLONG;2041 2506 ch = *p++; 2042 2507 } else { … … 2044 2509 } 2045 2510 } 2046 if (tok == TOK_CINT || tok == TOK_CUINT) 2047 tokc.ui = n; 2048 else 2049 tokc.ull = n; 2511 2512 /* Determine if it needs 64 bits and/or unsigned in order to fit */ 2513 if (ucount == 0 && b == 10) { 2514 if (lcount <= (LONG_SIZE == 4)) { 2515 if (n >= 0x80000000U) 2516 lcount = (LONG_SIZE == 4) + 1; 2517 } 2518 if (n >= 0x8000000000000000ULL) 2519 ov = 1, ucount = 1; 2520 } else { 2521 if (lcount <= (LONG_SIZE == 4)) { 2522 if (n >= 0x100000000ULL) 2523 lcount = (LONG_SIZE == 4) + 1; 2524 else if (n >= 0x80000000U) 2525 ucount = 1; 2526 } 2527 if (n >= 0x8000000000000000ULL) 2528 ucount = 1; 2529 } 2530 2531 if (ov) 2532 tcc_warning("integer constant overflow"); 2533 2534 tok = TOK_CINT; 2535 if (lcount) { 2536 tok = TOK_CLONG; 2537 if (lcount == 2) 2538 tok = TOK_CLLONG; 2539 } 2540 if (ucount) 2541 ++tok; /* TOK_CU... */ 2542 tokc.i = n; 2050 2543 } 2051 2544 if (ch) … … 2068 2561 static inline void next_nomacro1(void) 2069 2562 { 2070 int t, c, is_long ;2563 int t, c, is_long, len; 2071 2564 TokenSym *ts; 2072 2565 uint8_t *p, *p1; … … 2081 2574 tok = c; 2082 2575 p++; 2083 goto keep_tok_flags; 2576 if (parse_flags & PARSE_FLAG_SPACES) 2577 goto keep_tok_flags; 2578 while (isidnum_table[*p - CH_EOF] & IS_SPC) 2579 ++p; 2580 goto redo_no_start; 2084 2581 case '\f': 2085 2582 case '\v': … … 2089 2586 case '\\': 2090 2587 /* first look if it is in fact an end of buffer */ 2091 if (p >= file->buf_end) { 2092 file->buf_ptr = p; 2093 handle_eob(); 2094 p = file->buf_ptr; 2095 if (p >= file->buf_end) 2096 goto parse_eof; 2097 else 2098 goto redo_no_start; 2099 } else { 2100 file->buf_ptr = p; 2101 ch = *p; 2102 handle_stray(); 2103 p = file->buf_ptr; 2588 c = handle_stray1(p); 2589 p = file->buf_ptr; 2590 if (c == '\\') 2591 goto parse_simple; 2592 if (c != CH_EOF) 2104 2593 goto redo_no_start; 2105 }2106 parse_eof:2107 2594 { 2108 2595 TCCState *s1 = tcc_state; … … 2129 2616 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL)); 2130 2617 #endif 2131 add_cached_include(s1, file->filename, file->ifndef_macro_saved); 2618 search_cached_include(s1, file->filename, 1) 2619 ->ifndef_macro = file->ifndef_macro_saved; 2132 2620 tok_flags &= ~TOK_FLAG_ENDIF; 2133 2621 } … … 2141 2629 s1->include_stack_ptr--; 2142 2630 p = file->buf_ptr; 2631 if (p == file->buffer) 2632 tok_flags = TOK_FLAG_BOF|TOK_FLAG_BOL; 2143 2633 goto redo_no_start; 2144 2634 } … … 2170 2660 tok = TOK_TWOSHARPS; 2171 2661 } else { 2172 if (parse_flags & PARSE_FLAG_ASM_ COMMENTS) {2662 if (parse_flags & PARSE_FLAG_ASM_FILE) { 2173 2663 p = parse_line_comment(p - 1); 2174 2664 goto redo_no_start; … … 2179 2669 } 2180 2670 break; 2671 2672 /* dollar is allowed to start identifiers when not parsing asm */ 2673 case '$': 2674 if (!(isidnum_table[c - CH_EOF] & IS_ID) 2675 || (parse_flags & PARSE_FLAG_ASM_FILE)) 2676 goto parse_simple; 2181 2677 2182 2678 case 'a': case 'b': case 'c': case 'd': … … 2199 2695 h = TOK_HASH_INIT; 2200 2696 h = TOK_HASH_FUNC(h, c); 2201 p++; 2202 for(;;) { 2203 c = *p; 2204 if (!isidnum_table[c-CH_EOF]) 2205 break; 2697 while (c = *++p, isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM)) 2206 2698 h = TOK_HASH_FUNC(h, c); 2207 p++; 2208 } 2699 len = p - p1; 2209 2700 if (c != '\\') { 2210 2701 TokenSym **pts; 2211 int len;2212 2702 2213 2703 /* fast case : no stray found, so we have the full token 2214 2704 and we have already hashed it */ 2215 len = p - p1;2216 2705 h &= (TOK_HASH_SIZE - 1); 2217 2706 pts = &hash_ident[h]; … … 2224 2713 pts = &(ts->hash_next); 2225 2714 } 2226 ts = tok_alloc_new(pts, p1, len);2715 ts = tok_alloc_new(pts, (char *) p1, len); 2227 2716 token_found: ; 2228 2717 } else { 2229 2718 /* slower case */ 2230 2719 cstr_reset(&tokcstr); 2231 2232 while (p1 < p) { 2233 cstr_ccat(&tokcstr, *p1); 2234 p1++; 2235 } 2720 cstr_cat(&tokcstr, (char *) p1, len); 2236 2721 p--; 2237 2722 PEEKC(c, p); 2238 2723 parse_ident_slow: 2239 while (isidnum_table[c-CH_EOF]) { 2724 while (isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM)) 2725 { 2240 2726 cstr_ccat(&tokcstr, c); 2241 2727 PEEKC(c, p); … … 2262 2748 } 2263 2749 break; 2750 2264 2751 case '0': case '1': case '2': case '3': 2265 2752 case '4': case '5': case '6': case '7': 2266 2753 case '8': case '9': 2267 2268 cstr_reset(&tokcstr);2754 t = c; 2755 PEEKC(c, p); 2269 2756 /* after the first digit, accept digits, alpha, '.' or sign if 2270 2757 prefixed by 'eEpP' */ 2271 2758 parse_num: 2759 cstr_reset(&tokcstr); 2272 2760 for(;;) { 2761 cstr_ccat(&tokcstr, t); 2762 if (!((isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM)) 2763 || c == '.' 2764 || ((c == '+' || c == '-') 2765 && (((t == 'e' || t == 'E') 2766 && !(parse_flags & PARSE_FLAG_ASM_FILE 2767 /* 0xe+1 is 3 tokens in asm */ 2768 && ((char*)tokcstr.data)[0] == '0' 2769 && toup(((char*)tokcstr.data)[1]) == 'X')) 2770 || t == 'p' || t == 'P')))) 2771 break; 2273 2772 t = c; 2274 cstr_ccat(&tokcstr, c);2275 2773 PEEKC(c, p); 2276 if (!(isnum(c) || isid(c) || c == '.' ||2277 ((c == '+' || c == '-') &&2278 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))2279 break;2280 2774 } 2281 2775 /* We add a trailing '\0' to ease parsing */ 2282 2776 cstr_ccat(&tokcstr, '\0'); 2283 tokc.cstr = &tokcstr; 2777 tokc.str.size = tokcstr.size; 2778 tokc.str.data = tokcstr.data; 2284 2779 tok = TOK_PPNUM; 2285 2780 break; 2781 2286 2782 case '.': 2287 2783 /* special dot handling because it can also start a number */ 2288 2784 PEEKC(c, p); 2289 2785 if (isnum(c)) { 2290 cstr_reset(&tokcstr); 2291 cstr_ccat(&tokcstr, '.'); 2786 t = '.'; 2292 2787 goto parse_num; 2788 } else if ((isidnum_table['.' - CH_EOF] & IS_ID) 2789 && (isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))) { 2790 *--p = c = '.'; 2791 goto parse_ident_fast; 2293 2792 } else if (c == '.') { 2294 2793 PEEKC(c, p); 2295 if (c != '.') 2296 expect("'.'"); 2297 PEEKC(c, p); 2298 tok = TOK_DOTS; 2794 if (c == '.') { 2795 p++; 2796 tok = TOK_DOTS; 2797 } else { 2798 *--p = '.'; /* may underflow into file->unget[] */ 2799 tok = '.'; 2800 } 2299 2801 } else { 2300 2802 tok = '.'; … … 2305 2807 is_long = 0; 2306 2808 str_const: 2307 { 2308 CString str; 2309 int sep; 2310 2311 sep = c; 2312 2313 /* parse the string */ 2314 cstr_new(&str); 2315 p = parse_pp_string(p, sep, &str); 2316 cstr_ccat(&str, '\0'); 2317 2318 /* eval the escape (should be done as TOK_PPNUM) */ 2319 cstr_reset(&tokcstr); 2320 parse_escape_string(&tokcstr, str.data, is_long); 2321 cstr_free(&str); 2322 2323 if (sep == '\'') { 2324 int char_size; 2325 /* XXX: make it portable */ 2326 if (!is_long) 2327 char_size = 1; 2328 else 2329 char_size = sizeof(nwchar_t); 2330 if (tokcstr.size <= char_size) 2331 tcc_error("empty character constant"); 2332 if (tokcstr.size > 2 * char_size) 2333 tcc_warning("multi-character character constant"); 2334 if (!is_long) { 2335 tokc.i = *(int8_t *)tokcstr.data; 2336 tok = TOK_CCHAR; 2337 } else { 2338 tokc.i = *(nwchar_t *)tokcstr.data; 2339 tok = TOK_LCHAR; 2340 } 2341 } else { 2342 tokc.cstr = &tokcstr; 2343 if (!is_long) 2344 tok = TOK_STR; 2345 else 2346 tok = TOK_LSTR; 2347 } 2348 } 2809 cstr_reset(&tokcstr); 2810 if (is_long) 2811 cstr_ccat(&tokcstr, 'L'); 2812 cstr_ccat(&tokcstr, c); 2813 p = parse_pp_string(p, c, &tokcstr); 2814 cstr_ccat(&tokcstr, c); 2815 cstr_ccat(&tokcstr, '\0'); 2816 tokc.str.size = tokcstr.size; 2817 tokc.str.data = tokcstr.data; 2818 tok = TOK_PPSTR; 2349 2819 break; 2350 2820 … … 2366 2836 } 2367 2837 break; 2368 2369 2838 case '>': 2370 2839 PEEKC(c, p); … … 2478 2947 case '?': 2479 2948 case '~': 2480 case ' $': /* only used in assembler */2481 case '@': /* dito */2949 case '@': /* only used in assembler */ 2950 parse_simple: 2482 2951 tok = c; 2483 2952 p++; 2484 2953 break; 2485 2954 default: 2955 if (c >= 0x80 && c <= 0xFF) /* utf8 identifiers */ 2956 goto parse_ident_fast; 2957 if (parse_flags & PARSE_FLAG_ASM_FILE) 2958 goto parse_simple; 2486 2959 tcc_error("unrecognized character \\x%02x", c); 2487 2960 break; … … 2491 2964 file->buf_ptr = p; 2492 2965 #if defined(PARSE_DEBUG) 2493 printf("token = % s\n", get_tok_str(tok, &tokc));2966 printf("token = %d %s\n", tok, get_tok_str(tok, &tokc)); 2494 2967 #endif 2495 2968 } … … 2512 2985 next_nomacro1(); 2513 2986 } 2987 //printf("token = %s\n", get_tok_str(tok, &tokc)); 2514 2988 } 2515 2989 … … 2518 2992 do { 2519 2993 next_nomacro_spc(); 2520 } while ( is_space(tok));2994 } while (tok < 256 && (isidnum_table[tok - CH_EOF] & IS_SPC)); 2521 2995 } 2522 2996 2523 /* substitute args in macro_str and return allocated string */ 2997 2998 static void macro_subst( 2999 TokenString *tok_str, 3000 Sym **nested_list, 3001 const int *macro_str 3002 ); 3003 3004 /* substitute arguments in replacement lists in macro_str by the values in 3005 args (field d) and return allocated string */ 2524 3006 static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) 2525 3007 { 2526 int last_tok, t, spc;3008 int t, t0, t1, spc; 2527 3009 const int *st; 2528 3010 Sym *s; … … 2532 3014 2533 3015 tok_str_new(&str); 2534 last_tok= 0;3016 t0 = t1 = 0; 2535 3017 while(1) { 2536 3018 TOK_GET(&t, ¯o_str, &cval); … … 2541 3023 TOK_GET(&t, ¯o_str, &cval); 2542 3024 if (!t) 2543 break;3025 goto bad_stringy; 2544 3026 s = sym_find2(args, t); 2545 3027 if (s) { 2546 3028 cstr_new(&cstr); 3029 cstr_ccat(&cstr, '\"'); 2547 3030 st = s->d; 2548 3031 spc = 0; 2549 while (*st ) {3032 while (*st >= 0) { 2550 3033 TOK_GET(&t, &st, &cval); 2551 if (!check_space(t, &spc)) 2552 cstr_cat(&cstr, get_tok_str(t, &cval)); 3034 if (t != TOK_PLCHLDR 3035 && t != TOK_NOSUBST 3036 && 0 == check_space(t, &spc)) { 3037 const char *s = get_tok_str(t, &cval); 3038 while (*s) { 3039 if (t == TOK_PPSTR && *s != '\'') 3040 add_char(&cstr, *s); 3041 else 3042 cstr_ccat(&cstr, *s); 3043 ++s; 3044 } 3045 } 2553 3046 } 2554 3047 cstr.size -= spc; 3048 cstr_ccat(&cstr, '\"'); 2555 3049 cstr_ccat(&cstr, '\0'); 2556 3050 #ifdef PP_DEBUG 2557 printf(" stringize: %s\n", (char *)cstr.data);3051 printf("\nstringize: <%s>\n", (char *)cstr.data); 2558 3052 #endif 2559 3053 /* add string */ 2560 cval.cstr = &cstr; 2561 tok_str_add2(&str, TOK_STR, &cval); 3054 cval.str.size = cstr.size; 3055 cval.str.data = cstr.data; 3056 tok_str_add2(&str, TOK_PPSTR, &cval); 2562 3057 cstr_free(&cstr); 2563 3058 } else { 2564 tok_str_add2(&str, t, &cval); 3059 bad_stringy: 3060 expect("macro parameter after '#'"); 2565 3061 } 2566 3062 } else if (t >= TOK_IDENT) { 2567 3063 s = sym_find2(args, t); 2568 3064 if (s) { 3065 int l0 = str.len; 2569 3066 st = s->d; 2570 3067 /* if '##' is present before or after, no arg substitution */ 2571 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) { 2572 /* special case for var arg macros : ## eats the 2573 ',' if empty VA_ARGS variable. */ 2574 /* XXX: test of the ',' is not 100% 2575 reliable. should fix it to avoid security 2576 problems */ 2577 if (gnu_ext && s->type.t && 2578 last_tok == TOK_TWOSHARPS && 2579 str.len >= 2 && str.str[str.len - 2] == ',') { 2580 if (*st == 0) { 3068 if (*macro_str == TOK_PPJOIN || t1 == TOK_PPJOIN) { 3069 /* special case for var arg macros : ## eats the ',' 3070 if empty VA_ARGS variable. */ 3071 if (t1 == TOK_PPJOIN && t0 == ',' && gnu_ext && s->type.t) { 3072 if (*st <= 0) { 2581 3073 /* suppress ',' '##' */ 2582 3074 str.len -= 2; … … 2586 3078 goto add_var; 2587 3079 } 2588 } else {2589 int t1;2590 add_var:2591 for(;;) {2592 TOK_GET(&t1, &st, &cval);2593 if (!t1)2594 break;2595 tok_str_add2(&str, t1, &cval);2596 }2597 3080 } 2598 3081 } else { 2599 /* NOTE: the stream cannot be read when macro 2600 substituing an argument */ 2601 macro_subst(&str, nested_list, st, NULL); 3082 add_var: 3083 if (!s->next) { 3084 /* Expand arguments tokens and store them. In most 3085 cases we could also re-expand each argument if 3086 used multiple times, but not if the argument 3087 contains the __COUNTER__ macro. */ 3088 TokenString str2; 3089 sym_push2(&s->next, s->v, s->type.t, 0); 3090 tok_str_new(&str2); 3091 macro_subst(&str2, nested_list, st); 3092 tok_str_add(&str2, 0); 3093 s->next->d = str2.str; 3094 } 3095 st = s->next->d; 2602 3096 } 3097 for(;;) { 3098 int t2; 3099 TOK_GET(&t2, &st, &cval); 3100 if (t2 <= 0) 3101 break; 3102 tok_str_add2(&str, t2, &cval); 3103 } 3104 if (str.len == l0) /* expanded to empty string */ 3105 tok_str_add(&str, TOK_PLCHLDR); 2603 3106 } else { 2604 3107 tok_str_add(&str, t); … … 2607 3110 tok_str_add2(&str, t, &cval); 2608 3111 } 2609 last_tok= t;3112 t0 = t1, t1 = t; 2610 3113 } 2611 3114 tok_str_add(&str, 0); … … 2618 3121 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 2619 3122 }; 3123 3124 static int paste_tokens(int t1, CValue *v1, int t2, CValue *v2) 3125 { 3126 CString cstr; 3127 int n, ret = 1; 3128 3129 cstr_new(&cstr); 3130 if (t1 != TOK_PLCHLDR) 3131 cstr_cat(&cstr, get_tok_str(t1, v1), -1); 3132 n = cstr.size; 3133 if (t2 != TOK_PLCHLDR) 3134 cstr_cat(&cstr, get_tok_str(t2, v2), -1); 3135 cstr_ccat(&cstr, '\0'); 3136 3137 tcc_open_bf(tcc_state, ":paste:", cstr.size); 3138 memcpy(file->buffer, cstr.data, cstr.size); 3139 tok_flags = 0; 3140 for (;;) { 3141 next_nomacro1(); 3142 if (0 == *file->buf_ptr) 3143 break; 3144 if (is_space(tok)) 3145 continue; 3146 tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid" 3147 " preprocessing token", n, cstr.data, (char*)cstr.data + n); 3148 ret = 0; 3149 break; 3150 } 3151 tcc_close(); 3152 //printf("paste <%s>\n", (char*)cstr.data); 3153 cstr_free(&cstr); 3154 return ret; 3155 } 3156 3157 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise 3158 return the resulting string (which must be freed). */ 3159 static inline int *macro_twosharps(const int *ptr0) 3160 { 3161 int t; 3162 CValue cval; 3163 TokenString macro_str1; 3164 int start_of_nosubsts = -1; 3165 const int *ptr; 3166 3167 /* we search the first '##' */ 3168 for (ptr = ptr0;;) { 3169 TOK_GET(&t, &ptr, &cval); 3170 if (t == TOK_PPJOIN) 3171 break; 3172 if (t == 0) 3173 return NULL; 3174 } 3175 3176 tok_str_new(¯o_str1); 3177 3178 //tok_print(" $$$", ptr0); 3179 for (ptr = ptr0;;) { 3180 TOK_GET(&t, &ptr, &cval); 3181 if (t == 0) 3182 break; 3183 if (t == TOK_PPJOIN) 3184 continue; 3185 while (*ptr == TOK_PPJOIN) { 3186 int t1; CValue cv1; 3187 /* given 'a##b', remove nosubsts preceding 'a' */ 3188 if (start_of_nosubsts >= 0) 3189 macro_str1.len = start_of_nosubsts; 3190 /* given 'a##b', remove nosubsts preceding 'b' */ 3191 while ((t1 = *++ptr) == TOK_NOSUBST) 3192 ; 3193 if (t1 && t1 != TOK_PPJOIN) { 3194 TOK_GET(&t1, &ptr, &cv1); 3195 if (t != TOK_PLCHLDR || t1 != TOK_PLCHLDR) { 3196 if (paste_tokens(t, &cval, t1, &cv1)) { 3197 t = tok, cval = tokc; 3198 } else { 3199 tok_str_add2(¯o_str1, t, &cval); 3200 t = t1, cval = cv1; 3201 } 3202 } 3203 } 3204 } 3205 if (t == TOK_NOSUBST) { 3206 if (start_of_nosubsts < 0) 3207 start_of_nosubsts = macro_str1.len; 3208 } else { 3209 start_of_nosubsts = -1; 3210 } 3211 tok_str_add2(¯o_str1, t, &cval); 3212 } 3213 tok_str_add(¯o_str1, 0); 3214 //tok_print(" ###", macro_str1.str); 3215 return macro_str1.str; 3216 } 3217 3218 /* peek or read [ws_str == NULL] next token from function macro call, 3219 walking up macro levels up to the file if necessary */ 3220 static int next_argstream(Sym **nested_list, TokenString *ws_str) 3221 { 3222 int t; 3223 const int *p; 3224 Sym *sa; 3225 3226 for (;;) { 3227 if (macro_ptr) { 3228 p = macro_ptr, t = *p; 3229 if (ws_str) { 3230 while (is_space(t) || TOK_LINEFEED == t || TOK_PLCHLDR == t) 3231 tok_str_add(ws_str, t), t = *++p; 3232 } 3233 if (t == 0) { 3234 end_macro(); 3235 /* also, end of scope for nested defined symbol */ 3236 sa = *nested_list; 3237 while (sa && sa->v == 0) 3238 sa = sa->prev; 3239 if (sa) 3240 sa->v = 0; 3241 continue; 3242 } 3243 } else { 3244 ch = handle_eob(); 3245 if (ws_str) { 3246 while (is_space(ch) || ch == '\n' || ch == '/') { 3247 if (ch == '/') { 3248 int c; 3249 uint8_t *p = file->buf_ptr; 3250 PEEKC(c, p); 3251 if (c == '*') { 3252 p = parse_comment(p); 3253 file->buf_ptr = p - 1; 3254 } else if (c == '/') { 3255 p = parse_line_comment(p); 3256 file->buf_ptr = p - 1; 3257 } else 3258 break; 3259 ch = ' '; 3260 } 3261 if (ch == '\n') 3262 file->line_num++; 3263 if (!(ch == '\f' || ch == '\v' || ch == '\r')) 3264 tok_str_add(ws_str, ch); 3265 cinp(); 3266 } 3267 } 3268 t = ch; 3269 } 3270 3271 if (ws_str) 3272 return t; 3273 next_nomacro_spc(); 3274 return tok; 3275 } 3276 } 2620 3277 2621 3278 /* do macro substitution of current token with macro 's' and add … … 2623 3280 macros we got inside to avoid recursing. Return non zero if no 2624 3281 substitution needs to be done */ 2625 static int macro_subst_tok(TokenString *tok_str, 2626 Sym **nested_list, Sym *s, struct macro_level **can_read_stream) 3282 static int macro_subst_tok( 3283 TokenString *tok_str, 3284 Sym **nested_list, 3285 Sym *s) 2627 3286 { 2628 3287 Sym *args, *sa, *sa1; 2629 int mstr_allocated, parlevel, *mstr, t, t1, spc; 2630 const int *p; 3288 int parlevel, t, t1, spc; 2631 3289 TokenString str; 2632 3290 char *cstrval; … … 2634 3292 CString cstr; 2635 3293 char buf[32]; 2636 3294 2637 3295 /* if symbol is a macro, prepare substitution */ 2638 3296 /* special macros */ 2639 if (tok == TOK___LINE__) { 2640 snprintf(buf, sizeof(buf), "%d", file->line_num); 3297 if (tok == TOK___LINE__ || tok == TOK___COUNTER__) { 3298 t = tok == TOK___LINE__ ? file->line_num : pp_counter++; 3299 snprintf(buf, sizeof(buf), "%d", t); 2641 3300 cstrval = buf; 2642 3301 t1 = TOK_PPNUM; … … 2663 3322 add_cstr1: 2664 3323 cstr_new(&cstr); 2665 cstr_cat(&cstr, cstrval );2666 c str_ccat(&cstr, '\0');2667 cval. cstr = &cstr;3324 cstr_cat(&cstr, cstrval, 0); 3325 cval.str.size = cstr.size; 3326 cval.str.data = cstr.data; 2668 3327 tok_str_add2(tok_str, t1, &cval); 2669 3328 cstr_free(&cstr); 2670 } else { 2671 mstr = s->d; 2672 mstr_allocated = 0; 3329 } else if (s->d) { 3330 int saved_parse_flags = parse_flags; 3331 int *joined_str = NULL; 3332 int *mstr = s->d; 3333 2673 3334 if (s->type.t == MACRO_FUNC) { 2674 /* NOTE: we do not use next_nomacro to avoid eating the2675 next token. XXX: find better solution */2676 redo:2677 if (macro_ptr) { 2678 p = macro_ptr;2679 while (is_space(t = *p) || TOK_LINEFEED == t)2680 ++p;2681 if (t == 0 && can_read_stream) { 2682 /* end of macro stream: we must look at the token2683 after in the file */2684 struct macro_level *ml = *can_read_stream;2685 macro_ptr = NULL;2686 if (ml)2687 {2688 macro_ptr = ml->p;2689 ml->p = NULL;2690 *can_read_stream = ml -> prev;2691 }2692 /* also, end of scope for nested defined symbol */2693 (*nested_list)->v = -1;2694 goto redo;3335 /* whitespace between macro name and argument list */ 3336 TokenString ws_str; 3337 tok_str_new(&ws_str); 3338 3339 spc = 0; 3340 parse_flags |= PARSE_FLAG_SPACES | PARSE_FLAG_LINEFEED 3341 | PARSE_FLAG_ACCEPT_STRAYS; 3342 3343 /* get next token from argument stream */ 3344 t = next_argstream(nested_list, &ws_str); 3345 if (t != '(') { 3346 /* not a macro substitution after all, restore the 3347 * macro token plus all whitespace we've read. 3348 * whitespace is intentionally not merged to preserve 3349 * newlines. */ 3350 parse_flags = saved_parse_flags; 3351 tok_str_add(tok_str, tok); 3352 if (parse_flags & PARSE_FLAG_SPACES) { 3353 int i; 3354 for (i = 0; i < ws_str.len; i++) 3355 tok_str_add(tok_str, ws_str.str[i]); 2695 3356 } 3357 tok_str_free_str(ws_str.str); 3358 return 0; 2696 3359 } else { 2697 ch = file->buf_ptr[0]; 2698 while (is_space(ch) || ch == '\n' || ch == '/') 2699 { 2700 if (ch == '/') 2701 { 2702 int c; 2703 uint8_t *p = file->buf_ptr; 2704 PEEKC(c, p); 2705 if (c == '*') { 2706 p = parse_comment(p); 2707 file->buf_ptr = p - 1; 2708 } else if (c == '/') { 2709 p = parse_line_comment(p); 2710 file->buf_ptr = p - 1; 2711 } else 2712 break; 2713 } 2714 cinp(); 2715 } 2716 t = ch; 2717 } 2718 if (t != '(') /* no macro subst */ 2719 return -1; 2720 3360 tok_str_free_str(ws_str.str); 3361 } 3362 do { 3363 next_nomacro(); /* eat '(' */ 3364 } while (tok == TOK_PLCHLDR); 3365 2721 3366 /* argument macro */ 2722 next_nomacro();2723 next_nomacro();2724 3367 args = NULL; 2725 3368 sa = s->next; 2726 3369 /* NOTE: empty args are allowed, except if no args */ 2727 3370 for(;;) { 3371 do { 3372 next_argstream(nested_list, NULL); 3373 } while (is_space(tok) || TOK_LINEFEED == tok); 3374 empty_arg: 2728 3375 /* handle '()' case */ 2729 3376 if (!args && !sa && tok == ')') … … 2737 3384 while ((parlevel > 0 || 2738 3385 (tok != ')' && 2739 (tok != ',' || sa->type.t))) && 2740 tok != -1) { 3386 (tok != ',' || sa->type.t)))) { 3387 if (tok == TOK_EOF || tok == 0) 3388 break; 2741 3389 if (tok == '(') 2742 3390 parlevel++; … … 2747 3395 if (!check_space(tok, &spc)) 2748 3396 tok_str_add2(&str, tok, &tokc); 2749 next_ nomacro_spc();3397 next_argstream(nested_list, NULL); 2750 3398 } 3399 if (parlevel) 3400 expect(")"); 2751 3401 str.len -= spc; 3402 tok_str_add(&str, -1); 2752 3403 tok_str_add(&str, 0); 2753 3404 sa1 = sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, 0); … … 2758 3409 var arg argument if it is omitted */ 2759 3410 if (sa && sa->type.t && gnu_ext) 2760 continue; 2761 else 2762 break; 3411 goto empty_arg; 3412 break; 2763 3413 } 2764 3414 if (tok != ',') 2765 3415 expect(","); 2766 next_nomacro();2767 3416 } 2768 3417 if (sa) { … … 2770 3419 get_tok_str(s->v, 0)); 2771 3420 } 3421 3422 parse_flags = saved_parse_flags; 2772 3423 2773 3424 /* now subst each arg */ … … 2777 3428 while (sa) { 2778 3429 sa1 = sa->prev; 2779 tok_str_free(sa->d); 3430 tok_str_free_str(sa->d); 3431 if (sa->next) { 3432 tok_str_free_str(sa->next->d); 3433 sym_free(sa->next); 3434 } 2780 3435 sym_free(sa); 2781 3436 sa = sa1; 2782 3437 } 2783 mstr_allocated = 1;2784 } 3438 } 3439 2785 3440 sym_push2(nested_list, s->v, 0, 0); 2786 macro_subst(tok_str, nested_list, mstr, can_read_stream); 3441 parse_flags = saved_parse_flags; 3442 joined_str = macro_twosharps(mstr); 3443 macro_subst(tok_str, nested_list, joined_str ? joined_str : mstr); 3444 2787 3445 /* pop nested defined symbol */ 2788 3446 sa1 = *nested_list; 2789 3447 *nested_list = sa1->prev; 2790 3448 sym_free(sa1); 2791 if (mstr_allocated) 2792 tok_str_free(mstr); 3449 if (joined_str) 3450 tok_str_free_str(joined_str); 3451 if (mstr != s->d) 3452 tok_str_free_str(mstr); 2793 3453 } 2794 3454 return 0; 2795 3455 } 2796 2797 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise2798 return the resulting string (which must be freed). */2799 static inline int *macro_twosharps(const int *macro_str)2800 {2801 const int *ptr;2802 int t;2803 TokenString macro_str1;2804 CString cstr;2805 int n, start_of_nosubsts;2806 2807 /* we search the first '##' */2808 for(ptr = macro_str;;) {2809 CValue cval;2810 TOK_GET(&t, &ptr, &cval);2811 if (t == TOK_TWOSHARPS)2812 break;2813 /* nothing more to do if end of string */2814 if (t == 0)2815 return NULL;2816 }2817 2818 /* we saw '##', so we need more processing to handle it */2819 start_of_nosubsts = -1;2820 tok_str_new(¯o_str1);2821 for(ptr = macro_str;;) {2822 TOK_GET(&tok, &ptr, &tokc);2823 if (tok == 0)2824 break;2825 if (tok == TOK_TWOSHARPS)2826 continue;2827 if (tok == TOK_NOSUBST && start_of_nosubsts < 0)2828 start_of_nosubsts = macro_str1.len;2829 while (*ptr == TOK_TWOSHARPS) {2830 /* given 'a##b', remove nosubsts preceding 'a' */2831 if (start_of_nosubsts >= 0)2832 macro_str1.len = start_of_nosubsts;2833 /* given 'a##b', skip '##' */2834 t = *++ptr;2835 /* given 'a##b', remove nosubsts preceding 'b' */2836 while (t == TOK_NOSUBST)2837 t = *++ptr;2838 if (t && t != TOK_TWOSHARPS) {2839 CValue cval;2840 TOK_GET(&t, &ptr, &cval);2841 /* We concatenate the two tokens */2842 cstr_new(&cstr);2843 cstr_cat(&cstr, get_tok_str(tok, &tokc));2844 n = cstr.size;2845 cstr_cat(&cstr, get_tok_str(t, &cval));2846 cstr_ccat(&cstr, '\0');2847 2848 tcc_open_bf(tcc_state, ":paste:", cstr.size);2849 memcpy(file->buffer, cstr.data, cstr.size);2850 for (;;) {2851 next_nomacro1();2852 if (0 == *file->buf_ptr)2853 break;2854 tok_str_add2(¯o_str1, tok, &tokc);2855 tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid preprocessing token",2856 n, cstr.data, (char*)cstr.data + n);2857 }2858 tcc_close();2859 cstr_free(&cstr);2860 }2861 }2862 if (tok != TOK_NOSUBST)2863 start_of_nosubsts = -1;2864 tok_str_add2(¯o_str1, tok, &tokc);2865 }2866 tok_str_add(¯o_str1, 0);2867 return macro_str1.str;2868 }2869 2870 3456 2871 3457 /* do macro substitution of macro_str and add result to 2872 3458 (tok_str,tok_len). 'nested_list' is the list of all macros we got 2873 3459 inside to avoid recursing. */ 2874 static void macro_subst(TokenString *tok_str, Sym **nested_list, 2875 const int *macro_str, struct macro_level ** can_read_stream) 3460 static void macro_subst( 3461 TokenString *tok_str, 3462 Sym **nested_list, 3463 const int *macro_str 3464 ) 2876 3465 { 2877 3466 Sym *s; 2878 int *macro_str1; 2879 const int *ptr; 2880 int t, ret, spc; 3467 int t, spc, nosubst; 2881 3468 CValue cval; 2882 struct macro_level ml;2883 int force_blank;2884 3469 2885 /* first scan for '##' operator handling */ 2886 ptr = macro_str; 2887 macro_str1 = macro_twosharps(ptr); 2888 2889 if (macro_str1) 2890 ptr = macro_str1; 2891 spc = 0; 2892 force_blank = 0; 3470 spc = nosubst = 0; 2893 3471 2894 3472 while (1) { 2895 /* NOTE: ptr == NULL can only happen if tokens are read from 2896 file stream due to a macro function call */ 2897 if (ptr == NULL) 3473 TOK_GET(&t, ¯o_str, &cval); 3474 if (t <= 0) 2898 3475 break; 2899 TOK_GET(&t, &ptr, &cval); 2900 if (t == 0) 2901 break; 2902 if (t == TOK_NOSUBST) { 2903 /* following token has already been subst'd. just copy it on */ 2904 tok_str_add2(tok_str, TOK_NOSUBST, NULL); 2905 TOK_GET(&t, &ptr, &cval); 2906 goto no_subst; 2907 } 2908 s = define_find(t); 2909 if (s != NULL) { 3476 3477 if (t >= TOK_IDENT && 0 == nosubst) { 3478 s = define_find(t); 3479 if (s == NULL) 3480 goto no_subst; 3481 2910 3482 /* if nested substitution, do nothing */ 2911 3483 if (sym_find2(*nested_list, t)) { … … 2914 3486 goto no_subst; 2915 3487 } 2916 ml.p = macro_ptr; 2917 if (can_read_stream) 2918 ml.prev = *can_read_stream, *can_read_stream = &ml; 2919 macro_ptr = (int *)ptr; 2920 tok = t; 2921 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream); 2922 ptr = (int *)macro_ptr; 2923 macro_ptr = ml.p; 2924 if (can_read_stream && *can_read_stream == &ml) 2925 *can_read_stream = ml.prev; 2926 if (ret != 0) 2927 goto no_subst; 2928 if (parse_flags & PARSE_FLAG_SPACES) 2929 force_blank = 1; 3488 3489 { 3490 TokenString str; 3491 str.str = (int*)macro_str; 3492 begin_macro(&str, 2); 3493 3494 tok = t; 3495 macro_subst_tok(tok_str, nested_list, s); 3496 3497 if (str.alloc == 3) { 3498 /* already finished by reading function macro arguments */ 3499 break; 3500 } 3501 3502 macro_str = macro_ptr; 3503 end_macro (); 3504 } 3505 if (tok_str->len) 3506 spc = is_space(t = tok_str->str[tok_str->lastlen]); 2930 3507 } else { 2931 no_subst: 2932 if (force_blank) { 2933 tok_str_add(tok_str, ' '); 2934 spc = 1; 2935 force_blank = 0; 2936 } 2937 if (!check_space(t, &spc)) 3508 if (t == '\\' && !(parse_flags & PARSE_FLAG_ACCEPT_STRAYS)) 3509 tcc_error("stray '\\' in program"); 3510 no_subst: 3511 if (!check_space(t, &spc)) 2938 3512 tok_str_add2(tok_str, t, &cval); 2939 } 2940 } 2941 if (macro_str1) 2942 tok_str_free(macro_str1); 3513 3514 if (nosubst) { 3515 if (nosubst > 1 && (spc || (++nosubst == 3 && t == '('))) 3516 continue; 3517 nosubst = 0; 3518 } 3519 if (t == TOK_NOSUBST) 3520 nosubst = 1; 3521 } 3522 /* GCC supports 'defined' as result of a macro substitution */ 3523 if (t == TOK_DEFINED && pp_expr) 3524 nosubst = 2; 3525 } 2943 3526 } 2944 3527 … … 2946 3529 ST_FUNC void next(void) 2947 3530 { 2948 Sym *nested_list, *s;2949 TokenString str;2950 struct macro_level *ml;2951 2952 3531 redo: 2953 3532 if (parse_flags & PARSE_FLAG_SPACES) … … 2955 3534 else 2956 3535 next_nomacro(); 2957 if (!macro_ptr) { 2958 /* if not reading from macro substituted string, then try 2959 to substitute macros */ 2960 if (tok >= TOK_IDENT && 2961 (parse_flags & PARSE_FLAG_PREPROCESS)) { 2962 s = define_find(tok); 2963 if (s) { 2964 /* we have a macro: we try to substitute */ 2965 tok_str_new(&str); 2966 nested_list = NULL; 2967 ml = NULL; 2968 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) { 2969 /* substitution done, NOTE: maybe empty */ 2970 tok_str_add(&str, 0); 2971 macro_ptr = str.str; 2972 macro_ptr_allocated = str.str; 2973 goto redo; 2974 } 2975 } 2976 } 2977 } else { 2978 if (tok == 0) { 2979 /* end of macro or end of unget buffer */ 2980 if (unget_buffer_enabled) { 2981 macro_ptr = unget_saved_macro_ptr; 2982 unget_buffer_enabled = 0; 2983 } else { 2984 /* end of macro string: free it */ 2985 tok_str_free(macro_ptr_allocated); 2986 macro_ptr_allocated = NULL; 2987 macro_ptr = NULL; 2988 } 3536 3537 if (macro_ptr) { 3538 if (tok == TOK_NOSUBST || tok == TOK_PLCHLDR) { 3539 /* discard preprocessor markers */ 2989 3540 goto redo; 2990 } else if (tok == TOK_NOSUBST) { 2991 /* discard preprocessor's nosubst markers */ 3541 } else if (tok == 0) { 3542 /* end of macro or unget token string */ 3543 end_macro(); 2992 3544 goto redo; 2993 3545 } 2994 } 2995 3546 } else if (tok >= TOK_IDENT && (parse_flags & PARSE_FLAG_PREPROCESS)) { 3547 Sym *s; 3548 /* if reading from file, try to substitute macros */ 3549 s = define_find(tok); 3550 if (s) { 3551 Sym *nested_list = NULL; 3552 tokstr_buf.len = 0; 3553 macro_subst_tok(&tokstr_buf, &nested_list, s); 3554 tok_str_add(&tokstr_buf, 0); 3555 begin_macro(&tokstr_buf, 2); 3556 goto redo; 3557 } 3558 } 2996 3559 /* convert preprocessor tokens into C tokens */ 2997 if (tok == TOK_PPNUM && 2998 (parse_flags & PARSE_FLAG_TOK_NUM)) { 2999 parse_number((char *)tokc.cstr->data); 3560 if (tok == TOK_PPNUM) { 3561 if (parse_flags & PARSE_FLAG_TOK_NUM) 3562 parse_number((char *)tokc.str.data); 3563 } else if (tok == TOK_PPSTR) { 3564 if (parse_flags & PARSE_FLAG_TOK_STR) 3565 parse_string((char *)tokc.str.data, tokc.str.size - 1); 3000 3566 } 3001 3567 } … … 3005 3571 ST_INLN void unget_tok(int last_tok) 3006 3572 { 3007 int i, n; 3008 int *q; 3009 if (unget_buffer_enabled) 3010 { 3011 /* assert(macro_ptr == unget_saved_buffer + 1); 3012 assert(*macro_ptr == 0); */ 3013 } 3014 else 3015 { 3016 unget_saved_macro_ptr = macro_ptr; 3017 unget_buffer_enabled = 1; 3018 } 3019 q = unget_saved_buffer; 3020 macro_ptr = q; 3021 *q++ = tok; 3022 n = tok_ext_size(tok) - 1; 3023 for(i=0;i<n;i++) 3024 *q++ = tokc.tab[i]; 3025 *q = 0; /* end of token string */ 3573 3574 TokenString *str = tok_str_alloc(); 3575 tok_str_add2(str, tok, &tokc); 3576 tok_str_add(str, 0); 3577 begin_macro(str, 1); 3026 3578 tok = last_tok; 3027 3579 } 3028 3580 3029 3030 /* better than nothing, but needs extension to handle '-E' option 3031 correctly too */3032 ST_FUNC void preprocess_init(TCCState *s1) 3033 { 3581 ST_FUNC void preprocess_start(TCCState *s1, int is_asm) 3582 { 3583 CString cstr; 3584 int i; 3585 3034 3586 s1->include_stack_ptr = s1->include_stack; 3035 /* XXX: move that before to avoid having to initialize3036 file->ifdef_stack_ptr ? */3037 3587 s1->ifdef_stack_ptr = s1->ifdef_stack; 3038 3588 file->ifdef_stack_ptr = s1->ifdef_stack_ptr; 3039 3040 vtop = vstack - 1; 3589 pp_expr = 0; 3590 pp_counter = 0; 3591 pp_debug_tok = pp_debug_symv = 0; 3592 pp_once++; 3593 pvtop = vtop = vstack - 1; 3041 3594 s1->pack_stack[0] = 0; 3042 3595 s1->pack_stack_ptr = s1->pack_stack; 3043 } 3044 3045 ST_FUNC void preprocess_new(void) 3596 3597 set_idnum('$', s1->dollars_in_identifiers ? IS_ID : 0); 3598 set_idnum('.', is_asm ? IS_ID : 0); 3599 3600 cstr_new(&cstr); 3601 cstr_cat(&cstr, "\"", -1); 3602 cstr_cat(&cstr, file->filename, -1); 3603 cstr_cat(&cstr, "\"", 0); 3604 tcc_define_symbol(s1, "__BASE_FILE__", cstr.data); 3605 3606 cstr_reset(&cstr); 3607 for (i = 0; i < s1->nb_cmd_include_files; i++) { 3608 cstr_cat(&cstr, "#include \"", -1); 3609 cstr_cat(&cstr, s1->cmd_include_files[i], -1); 3610 cstr_cat(&cstr, "\"\n", -1); 3611 } 3612 if (cstr.size) { 3613 *s1->include_stack_ptr++ = file; 3614 tcc_open_bf(s1, "<command line>", cstr.size); 3615 memcpy(file->buffer, cstr.data, cstr.size); 3616 } 3617 cstr_free(&cstr); 3618 3619 if (is_asm) 3620 tcc_define_symbol(s1, "__ASSEMBLER__", NULL); 3621 3622 parse_flags = is_asm ? PARSE_FLAG_ASM_FILE : 0; 3623 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; 3624 } 3625 3626 /* cleanup from error/setjmp */ 3627 ST_FUNC void preprocess_end(TCCState *s1) 3628 { 3629 while (macro_stack) 3630 end_macro(); 3631 macro_ptr = NULL; 3632 } 3633 3634 ST_FUNC void tccpp_new(TCCState *s) 3046 3635 { 3047 3636 int i, c; 3048 3637 const char *p, *r; 3049 3638 3639 /* might be used in error() before preprocess_start() */ 3640 s->include_stack_ptr = s->include_stack; 3641 s->ppfp = stdout; 3642 3050 3643 /* init isid table */ 3051 for(i=CH_EOF;i<256;i++) 3052 isidnum_table[i-CH_EOF] = isid(i) || isnum(i); 3053 3054 /* add all tokens */ 3055 table_ident = NULL; 3644 for(i = CH_EOF; i<128; i++) 3645 set_idnum(i, 3646 is_space(i) ? IS_SPC 3647 : isid(i) ? IS_ID 3648 : isnum(i) ? IS_NUM 3649 : 0); 3650 3651 for(i = 128; i<256; i++) 3652 set_idnum(i, IS_ID); 3653 3654 /* init allocators */ 3655 tal_new(&toksym_alloc, TOKSYM_TAL_LIMIT, TOKSYM_TAL_SIZE); 3656 tal_new(&tokstr_alloc, TOKSTR_TAL_LIMIT, TOKSTR_TAL_SIZE); 3657 tal_new(&cstr_alloc, CSTR_TAL_LIMIT, CSTR_TAL_SIZE); 3658 3056 3659 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *)); 3660 cstr_new(&cstr_buf); 3661 cstr_realloc(&cstr_buf, STRING_MAX_SIZE); 3662 tok_str_new(&tokstr_buf); 3663 tok_str_realloc(&tokstr_buf, TOKSTR_MAX_SIZE); 3057 3664 3058 3665 tok_ident = TOK_IDENT; … … 3070 3677 } 3071 3678 3679 ST_FUNC void tccpp_delete(TCCState *s) 3680 { 3681 int i, n; 3682 3683 /* free -D and compiler defines */ 3684 free_defines(NULL); 3685 3686 /* free tokens */ 3687 n = tok_ident - TOK_IDENT; 3688 for(i = 0; i < n; i++) 3689 tal_free(toksym_alloc, table_ident[i]); 3690 tcc_free(table_ident); 3691 table_ident = NULL; 3692 3693 /* free static buffers */ 3694 cstr_free(&tokcstr); 3695 cstr_free(&cstr_buf); 3696 cstr_free(¯o_equal_buf); 3697 tok_str_free_str(tokstr_buf.str); 3698 3699 /* free allocators */ 3700 tal_delete(toksym_alloc); 3701 toksym_alloc = NULL; 3702 tal_delete(tokstr_alloc); 3703 tokstr_alloc = NULL; 3704 tal_delete(cstr_alloc); 3705 cstr_alloc = NULL; 3706 } 3707 3708 /* ------------------------------------------------------------------------- */ 3709 /* tcc -E [-P[1]] [-dD} support */ 3710 3711 static void tok_print(const char *msg, const int *str) 3712 { 3713 FILE *fp; 3714 int t, s = 0; 3715 CValue cval; 3716 3717 fp = tcc_state->ppfp; 3718 fprintf(fp, "%s", msg); 3719 while (str) { 3720 TOK_GET(&t, &str, &cval); 3721 if (!t) 3722 break; 3723 fprintf(fp, " %s" + s, get_tok_str(t, &cval)), s = 1; 3724 } 3725 fprintf(fp, "\n"); 3726 } 3727 3728 static void pp_line(TCCState *s1, BufferedFile *f, int level) 3729 { 3730 int d = f->line_num - f->line_ref; 3731 3732 if (s1->dflag & 4) 3733 return; 3734 3735 if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_NONE) { 3736 ; 3737 } else if (level == 0 && f->line_ref && d < 8) { 3738 while (d > 0) 3739 fputs("\n", s1->ppfp), --d; 3740 } else if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_STD) { 3741 fprintf(s1->ppfp, "#line %d \"%s\"\n", f->line_num, f->filename); 3742 } else { 3743 fprintf(s1->ppfp, "# %d \"%s\"%s\n", f->line_num, f->filename, 3744 level > 0 ? " 1" : level < 0 ? " 2" : ""); 3745 } 3746 f->line_ref = f->line_num; 3747 } 3748 3749 static void define_print(TCCState *s1, int v) 3750 { 3751 FILE *fp; 3752 Sym *s; 3753 3754 s = define_find(v); 3755 if (NULL == s || NULL == s->d) 3756 return; 3757 3758 fp = s1->ppfp; 3759 fprintf(fp, "#define %s", get_tok_str(v, NULL)); 3760 if (s->type.t == MACRO_FUNC) { 3761 Sym *a = s->next; 3762 fprintf(fp,"("); 3763 if (a) 3764 for (;;) { 3765 fprintf(fp,"%s", get_tok_str(a->v & ~SYM_FIELD, NULL)); 3766 if (!(a = a->next)) 3767 break; 3768 fprintf(fp,","); 3769 } 3770 fprintf(fp,")"); 3771 } 3772 tok_print("", s->d); 3773 } 3774 3775 static void pp_debug_defines(TCCState *s1) 3776 { 3777 int v, t; 3778 const char *vs; 3779 FILE *fp; 3780 3781 t = pp_debug_tok; 3782 if (t == 0) 3783 return; 3784 3785 file->line_num--; 3786 pp_line(s1, file, 0); 3787 file->line_ref = ++file->line_num; 3788 3789 fp = s1->ppfp; 3790 v = pp_debug_symv; 3791 vs = get_tok_str(v, NULL); 3792 if (t == TOK_DEFINE) { 3793 define_print(s1, v); 3794 } else if (t == TOK_UNDEF) { 3795 fprintf(fp, "#undef %s\n", vs); 3796 } else if (t == TOK_push_macro) { 3797 fprintf(fp, "#pragma push_macro(\"%s\")\n", vs); 3798 } else if (t == TOK_pop_macro) { 3799 fprintf(fp, "#pragma pop_macro(\"%s\")\n", vs); 3800 } 3801 pp_debug_tok = 0; 3802 } 3803 3804 static void pp_debug_builtins(TCCState *s1) 3805 { 3806 int v; 3807 for (v = TOK_IDENT; v < tok_ident; ++v) 3808 define_print(s1, v); 3809 } 3810 3811 /* Add a space between tokens a and b to avoid unwanted textual pasting */ 3812 static int pp_need_space(int a, int b) 3813 { 3814 return 'E' == a ? '+' == b || '-' == b 3815 : '+' == a ? TOK_INC == b || '+' == b 3816 : '-' == a ? TOK_DEC == b || '-' == b 3817 : a >= TOK_IDENT ? b >= TOK_IDENT 3818 : a == TOK_PPNUM ? b >= TOK_IDENT 3819 : 0; 3820 } 3821 3822 /* maybe hex like 0x1e */ 3823 static int pp_check_he0xE(int t, const char *p) 3824 { 3825 if (t == TOK_PPNUM && toup(strchr(p, 0)[-1]) == 'E') 3826 return 'E'; 3827 return t; 3828 } 3829 3072 3830 /* Preprocess the current file */ 3073 3831 ST_FUNC int tcc_preprocess(TCCState *s1) 3074 3832 { 3075 Sym *define_start; 3076 3077 BufferedFile *file_ref, **iptr, **iptr_new; 3078 int token_seen, line_ref, d; 3079 const char *s; 3080 3081 preprocess_init(s1); 3082 define_start = define_stack; 3083 ch = file->buf_ptr[0]; 3084 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; 3085 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS | 3086 PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES; 3087 token_seen = 0; 3088 line_ref = 0; 3089 file_ref = NULL; 3090 iptr = s1->include_stack_ptr; 3091 3833 BufferedFile **iptr; 3834 int token_seen, spcs, level; 3835 const char *p; 3836 char white[400]; 3837 3838 parse_flags = PARSE_FLAG_PREPROCESS 3839 | (parse_flags & PARSE_FLAG_ASM_FILE) 3840 | PARSE_FLAG_LINEFEED 3841 | PARSE_FLAG_SPACES 3842 | PARSE_FLAG_ACCEPT_STRAYS 3843 ; 3844 /* Credits to Fabrice Bellard's initial revision to demonstrate its 3845 capability to compile and run itself, provided all numbers are 3846 given as decimals. tcc -E -P10 will do. */ 3847 if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_P10) 3848 parse_flags |= PARSE_FLAG_TOK_NUM, s1->Pflag = 1; 3849 3850 #ifdef PP_BENCH 3851 /* for PP benchmarks */ 3852 do next(); while (tok != TOK_EOF); 3853 return 0; 3854 #endif 3855 3856 if (s1->dflag & 1) { 3857 pp_debug_builtins(s1); 3858 s1->dflag &= ~1; 3859 } 3860 3861 token_seen = TOK_LINEFEED, spcs = 0; 3862 pp_line(s1, file, 0); 3092 3863 for (;;) { 3864 iptr = s1->include_stack_ptr; 3093 3865 next(); 3094 if (tok == TOK_EOF) {3866 if (tok == TOK_EOF) 3095 3867 break; 3096 } else if (file != file_ref) { 3097 goto print_line; 3868 3869 level = s1->include_stack_ptr - iptr; 3870 if (level) { 3871 if (level > 0) 3872 pp_line(s1, *iptr, 0); 3873 pp_line(s1, file, level); 3874 } 3875 if (s1->dflag & 7) { 3876 pp_debug_defines(s1); 3877 if (s1->dflag & 4) 3878 continue; 3879 } 3880 3881 if (is_space(tok)) { 3882 if (spcs < sizeof white - 1) 3883 white[spcs++] = tok; 3884 continue; 3098 3885 } else if (tok == TOK_LINEFEED) { 3099 if (!token_seen) 3886 spcs = 0; 3887 if (token_seen == TOK_LINEFEED) 3100 3888 continue; 3101 ++line_ref; 3102 token_seen = 0; 3103 } else if (!token_seen) { 3104 d = file->line_num - line_ref; 3105 if (file != file_ref || d < 0 || d >= 8) { 3106 print_line: 3107 iptr_new = s1->include_stack_ptr; 3108 s = iptr_new > iptr ? " 1" 3109 : iptr_new < iptr ? " 2" 3110 : iptr_new > s1->include_stack ? " 3" 3111 : "" 3112 ; 3113 iptr = iptr_new; 3114 fprintf(s1->ppfp, "# %d \"%s\"%s\n", file->line_num, file->filename, s); 3115 } else { 3116 while (d) 3117 fputs("\n", s1->ppfp), --d; 3118 } 3119 line_ref = (file_ref = file)->line_num; 3120 token_seen = tok != TOK_LINEFEED; 3121 if (!token_seen) 3122 continue; 3123 } 3124 fputs(get_tok_str(tok, &tokc), s1->ppfp); 3125 } 3126 free_defines(define_start); 3889 ++file->line_ref; 3890 } else if (token_seen == TOK_LINEFEED) { 3891 pp_line(s1, file, 0); 3892 } else if (spcs == 0 && pp_need_space(token_seen, tok)) { 3893 white[spcs++] = ' '; 3894 } 3895 3896 white[spcs] = 0, fputs(white, s1->ppfp), spcs = 0; 3897 fputs(p = get_tok_str(tok, &tokc), s1->ppfp); 3898 token_seen = pp_check_he0xE(tok, p); 3899 } 3127 3900 return 0; 3128 3901 } 3902 3903 /* ------------------------------------------------------------------------- */ -
EcnlProtoTool/trunk/tcc-0.9.27/tccrun.c
r321 r331 24 24 #ifdef TCC_IS_NATIVE 25 25 26 #ifndef _WIN32 27 # include <sys/mman.h> 28 #endif 29 26 30 #ifdef CONFIG_TCC_BACKTRACE 31 # ifndef _WIN32 32 # include <signal.h> 33 # ifndef __OpenBSD__ 34 # include <sys/ucontext.h> 35 # endif 36 # else 37 # define ucontext_t CONTEXT 38 # endif 27 39 ST_DATA int rt_num_callers = 6; 28 40 ST_DATA const char **rt_bound_error_msg; 29 41 ST_DATA void *rt_prog_main; 30 #endif31 32 #ifdef _WIN3233 #define ucontext_t CONTEXT34 #endif35 36 static void set_pages_executable(void *ptr, unsigned long length);37 static void set_exception_handler(void);38 42 static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level); 39 43 static void rt_error(ucontext_t *uc, const char *fmt, ...); 40 static int tcc_relocate_ex(TCCState *s1, void *ptr); 44 static void set_exception_handler(void); 45 #endif 46 47 static void set_pages_executable(void *ptr, unsigned long length); 48 static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff); 41 49 42 50 #ifdef _WIN64 43 static void win64_add_function_table(TCCState *s1); 51 static void *win64_add_function_table(TCCState *s1); 52 static void win64_del_function_table(void *); 44 53 #endif 45 54 … … 50 59 LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) 51 60 { 52 int ret; 61 int size; 62 addr_t ptr_diff = 0; 53 63 54 64 if (TCC_RELOCATE_AUTO != ptr) 55 return tcc_relocate_ex(s1, ptr );56 57 ret = tcc_relocate_ex(s1, NULL);58 if ( ret< 0)59 return ret;65 return tcc_relocate_ex(s1, ptr, 0); 66 67 size = tcc_relocate_ex(s1, NULL, 0); 68 if (size < 0) 69 return -1; 60 70 61 71 #ifdef HAVE_SELINUX 62 { /* Use mmap instead of malloc for Selinux. Ref: 63 http://www.gnu.org/s/libc/manual/html_node/File-Size.html */ 64 65 char tmpfname[] = "/tmp/.tccrunXXXXXX"; 66 int fd = mkstemp (tmpfname); 67 68 s1->mem_size = ret; 69 unlink (tmpfname); 70 ftruncate (fd, s1->mem_size); 71 72 s1->write_mem = mmap (NULL, ret, PROT_READ|PROT_WRITE, 73 MAP_SHARED, fd, 0); 74 if (s1->write_mem == MAP_FAILED) 75 tcc_error("/tmp not writeable"); 76 77 s1->runtime_mem = mmap (NULL, ret, PROT_READ|PROT_EXEC, 78 MAP_SHARED, fd, 0); 79 if (s1->runtime_mem == MAP_FAILED) 80 tcc_error("/tmp not executable"); 81 82 ret = tcc_relocate_ex(s1, s1->write_mem); 83 } 84 #else 85 s1->runtime_mem = tcc_malloc(ret); 86 ret = tcc_relocate_ex(s1, s1->runtime_mem); 87 #endif 88 return ret; 72 { 73 /* Using mmap instead of malloc */ 74 void *prx; 75 char tmpfname[] = "/tmp/.tccrunXXXXXX"; 76 int fd = mkstemp(tmpfname); 77 unlink(tmpfname); 78 ftruncate(fd, size); 79 80 ptr = mmap (NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 81 prx = mmap (NULL, size, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0); 82 if (ptr == MAP_FAILED || prx == MAP_FAILED) 83 tcc_error("tccrun: could not map memory"); 84 dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size); 85 dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, prx); 86 ptr_diff = (char*)prx - (char*)ptr; 87 } 88 #else 89 ptr = tcc_malloc(size); 90 #endif 91 tcc_relocate_ex(s1, ptr, ptr_diff); /* no more errors expected */ 92 dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr); 93 return 0; 94 } 95 96 ST_FUNC void tcc_run_free(TCCState *s1) 97 { 98 int i; 99 100 for (i = 0; i < s1->nb_runtime_mem; ++i) { 101 #ifdef HAVE_SELINUX 102 unsigned size = (unsigned)(addr_t)s1->runtime_mem[i++]; 103 munmap(s1->runtime_mem[i++], size); 104 munmap(s1->runtime_mem[i], size); 105 #else 106 #ifdef _WIN64 107 win64_del_function_table(*(void**)s1->runtime_mem[i]); 108 #endif 109 tcc_free(s1->runtime_mem[i]); 110 #endif 111 } 112 tcc_free(s1->runtime_mem); 89 113 } 90 114 … … 93 117 { 94 118 int (*prog_main)(int, char **); 95 int ret; 96 119 120 s1->runtime_main = "main"; 121 if ((s1->dflag & 16) && !find_elf_sym(s1->symtab, s1->runtime_main)) 122 return 0; 97 123 if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0) 98 124 return -1; 99 100 prog_main = tcc_get_symbol_err(s1, "main"); 125 prog_main = tcc_get_symbol_err(s1, s1->runtime_main); 101 126 102 127 #ifdef CONFIG_TCC_BACKTRACE … … 107 132 #endif 108 133 134 errno = 0; /* clean errno value */ 135 109 136 #ifdef CONFIG_TCC_BCHECK 110 137 if (s1->do_bounds_check) { 111 138 void (*bound_init)(void); 112 139 void (*bound_exit)(void); 140 void (*bound_new_region)(void *p, addr_t size); 141 int (*bound_delete_region)(void *p); 142 int i, ret; 143 113 144 /* set error function */ 114 145 rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg"); … … 116 147 bound_init = tcc_get_symbol_err(s1, "__bound_init"); 117 148 bound_exit = tcc_get_symbol_err(s1, "__bound_exit"); 149 bound_new_region = tcc_get_symbol_err(s1, "__bound_new_region"); 150 bound_delete_region = tcc_get_symbol_err(s1, "__bound_delete_region"); 151 118 152 bound_init(); 153 /* mark argv area as valid */ 154 bound_new_region(argv, argc*sizeof(argv[0])); 155 for (i=0; i<argc; ++i) 156 bound_new_region(argv[i], strlen(argv[i]) + 1); 157 119 158 ret = (*prog_main)(argc, argv); 159 160 /* unmark argv area */ 161 for (i=0; i<argc; ++i) 162 bound_delete_region(argv[i]); 163 bound_delete_region(argv); 120 164 bound_exit(); 121 } else 122 #endif 123 ret = (*prog_main)(argc, argv); 124 return ret; 125 } 165 return ret; 166 } 167 #endif 168 return (*prog_main)(argc, argv); 169 } 170 171 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 172 #define RUN_SECTION_ALIGNMENT 63 173 #else 174 #define RUN_SECTION_ALIGNMENT 15 175 #endif 126 176 127 177 /* relocate code. Return -1 on error, required size if ptr is NULL, 128 178 otherwise copy code into buffer passed by the caller */ 129 static int tcc_relocate_ex(TCCState *s1, void *ptr )179 static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) 130 180 { 131 181 Section *s; 132 unsigned long offset, length;182 unsigned offset, length, fill, i, k; 133 183 addr_t mem; 134 int i;135 184 136 185 if (NULL == ptr) { … … 140 189 #else 141 190 tcc_add_runtime(s1); 142 relocate_common_syms(); 143 tcc_add_linker_symbols(s1); 191 resolve_common_syms(s1); 144 192 build_got_entries(s1); 145 193 #endif … … 149 197 150 198 offset = 0, mem = (addr_t)ptr; 199 fill = -mem & RUN_SECTION_ALIGNMENT; 200 #ifdef _WIN64 201 offset += sizeof (void*); 202 #endif 203 for (k = 0; k < 2; ++k) { 204 for(i = 1; i < s1->nb_sections; i++) { 205 s = s1->sections[i]; 206 if (0 == (s->sh_flags & SHF_ALLOC)) 207 continue; 208 if (k != !(s->sh_flags & SHF_EXECINSTR)) 209 continue; 210 offset += fill; 211 if (!mem) 212 s->sh_addr = 0; 213 else if (s->sh_flags & SHF_EXECINSTR) 214 s->sh_addr = mem + offset + ptr_diff; 215 else 216 s->sh_addr = mem + offset; 217 #if 0 218 if (mem) 219 printf("%-16s +%02lx %p %04x\n", 220 s->name, fill, (void*)s->sh_addr, (unsigned)s->data_offset); 221 #endif 222 offset += s->data_offset; 223 fill = -(mem + offset) & 15; 224 } 225 #if RUN_SECTION_ALIGNMENT > 15 226 /* To avoid that x86 processors would reload cached instructions each time 227 when data is written in the near, we need to make sure that code and data 228 do not share the same 64 byte unit */ 229 fill = -(mem + offset) & RUN_SECTION_ALIGNMENT; 230 #endif 231 } 232 233 /* relocate symbols */ 234 relocate_syms(s1, s1->symtab, 1); 235 if (s1->nb_errors) 236 return -1; 237 238 if (0 == mem) 239 return offset + RUN_SECTION_ALIGNMENT; 240 241 #ifdef TCC_TARGET_PE 242 s1->pe_imagebase = mem; 243 #endif 244 245 /* relocate each section */ 246 for(i = 1; i < s1->nb_sections; i++) { 247 s = s1->sections[i]; 248 if (s->reloc) 249 relocate_section(s1, s); 250 } 251 relocate_plt(s1); 252 151 253 for(i = 1; i < s1->nb_sections; i++) { 152 254 s = s1->sections[i]; … … 154 256 continue; 155 257 length = s->data_offset; 156 s->sh_addr = mem ? (mem + offset + 15) & ~15 : 0;157 offset = (offset + length + 15) & ~15;158 }159 offset += 16;160 161 /* relocate symbols */162 relocate_syms(s1, 1);163 if (s1->nb_errors)164 return -1;165 166 #ifdef TCC_HAS_RUNTIME_PLTGOT167 s1->runtime_plt_and_got_offset = 0;168 s1->runtime_plt_and_got = (char *)(mem + offset);169 /* double the size of the buffer for got and plt entries170 XXX: calculate exact size for them? */171 offset *= 2;172 #endif173 174 if (0 == mem)175 return offset;176 177 /* relocate each section */178 for(i = 1; i < s1->nb_sections; i++) {179 s = s1->sections[i];180 if (s->reloc)181 relocate_section(s1, s);182 }183 184 for(i = 1; i < s1->nb_sections; i++) {185 s = s1->sections[i];186 if (0 == (s->sh_flags & SHF_ALLOC))187 continue;188 length = s->data_offset;189 // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);190 258 ptr = (void*)s->sh_addr; 259 if (s->sh_flags & SHF_EXECINSTR) 260 ptr = (char*)ptr - ptr_diff; 191 261 if (NULL == s->data || s->sh_type == SHT_NOBITS) 192 262 memset(ptr, 0, length); … … 195 265 /* mark executable sections as executable in memory */ 196 266 if (s->sh_flags & SHF_EXECINSTR) 197 set_pages_executable(ptr, length); 198 } 199 200 #ifdef TCC_HAS_RUNTIME_PLTGOT 201 set_pages_executable(s1->runtime_plt_and_got, 202 s1->runtime_plt_and_got_offset); 203 #endif 267 set_pages_executable((char*)ptr + ptr_diff, length); 268 } 204 269 205 270 #ifdef _WIN64 206 win64_add_function_table(s1); 207 #endif 271 *(void**)mem = win64_add_function_table(s1); 272 #endif 273 208 274 return 0; 209 275 } … … 218 284 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect); 219 285 #else 220 #ifndef PAGESIZE 221 # define PAGESIZE 4096 222 #endif 286 void __clear_cache(void *beginning, void *end); 287 # ifndef HAVE_SELINUX 223 288 addr_t start, end; 289 # ifndef PAGESIZE 290 # define PAGESIZE 4096 291 # endif 224 292 start = (addr_t)ptr & ~(PAGESIZE - 1); 225 293 end = (addr_t)ptr + length; 226 294 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); 227 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC); 228 #endif 229 } 295 if (mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC)) 296 tcc_error("mprotect failed: did you mean to configure --with-selinux?"); 297 # endif 298 # if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 299 __clear_cache(ptr, (char *)ptr + length); 300 # endif 301 #endif 302 } 303 304 #ifdef _WIN64 305 static void *win64_add_function_table(TCCState *s1) 306 { 307 void *p = NULL; 308 if (s1->uw_pdata) { 309 p = (void*)s1->uw_pdata->sh_addr; 310 RtlAddFunctionTable( 311 (RUNTIME_FUNCTION*)p, 312 s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION), 313 s1->pe_imagebase 314 ); 315 s1->uw_pdata = NULL; 316 } 317 return p; 318 } 319 320 static void win64_del_function_table(void *p) 321 { 322 if (p) { 323 RtlDeleteFunctionTable((RUNTIME_FUNCTION*)p); 324 } 325 } 326 #endif 230 327 231 328 /* ------------------------------------------------------------- */ … … 254 351 stab_len = stab_section->data_offset; 255 352 stab_sym = (Stab_Sym *)stab_section->data; 256 stab_str = stabstr_section->data;353 stab_str = (char *) stabstr_section->data; 257 354 } 258 355 … … 347 444 wanted_pc < sym->st_value + sym->st_size) { 348 445 pstrcpy(last_func_name, sizeof(last_func_name), 349 strtab_section->data + sym->st_name);446 (char *) symtab_section->link->data + sym->st_name); 350 447 func_addr = sym->st_value; 351 448 goto found; … … 453 550 runtime errors */ 454 551 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND; 455 /*sigact.sa_sigaction = sig_error;*/ 456 sigact.sa_handler = sig_error; 552 sigact.sa_sigaction = sig_error; 457 553 sigemptyset(&sigact.sa_mask); 458 554 sigaction(SIGFPE, &sigact, NULL); … … 481 577 #if defined(__APPLE__) 482 578 *paddr = uc->uc_mcontext->__ss.__eip; 483 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 579 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 484 580 *paddr = uc->uc_mcontext.mc_eip; 485 581 #elif defined(__dietlibc__) 486 582 *paddr = uc->uc_mcontext.eip; 583 #elif defined(__NetBSD__) 584 *paddr = uc->uc_mcontext.__gregs[_REG_EIP]; 585 #elif defined(__OpenBSD__) 586 *paddr = uc->sc_eip; 487 587 #else 488 588 *paddr = uc->uc_mcontext.gregs[REG_EIP]; … … 492 592 #if defined(__APPLE__) 493 593 fp = uc->uc_mcontext->__ss.__ebp; 494 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 594 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 495 595 fp = uc->uc_mcontext.mc_ebp; 496 596 #elif defined(__dietlibc__) 497 597 fp = uc->uc_mcontext.ebp; 598 #elif defined(__NetBSD__) 599 fp = uc->uc_mcontext.__gregs[_REG_EBP]; 600 #elif defined(__OpenBSD__) 601 *paddr = uc->sc_ebp; 498 602 #else 499 603 fp = uc->uc_mcontext.gregs[REG_EBP]; … … 523 627 #if defined(__APPLE__) 524 628 *paddr = uc->uc_mcontext->__ss.__rip; 525 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 629 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 526 630 *paddr = uc->uc_mcontext.mc_rip; 631 #elif defined(__NetBSD__) 632 *paddr = uc->uc_mcontext.__gregs[_REG_RIP]; 527 633 #else 528 634 *paddr = uc->uc_mcontext.gregs[REG_RIP]; … … 532 638 #if defined(__APPLE__) 533 639 fp = uc->uc_mcontext->__ss.__rbp; 534 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 640 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 535 641 fp = uc->uc_mcontext.mc_rbp; 642 #elif defined(__NetBSD__) 643 fp = uc->uc_mcontext.__gregs[_REG_RBP]; 536 644 #else 537 645 fp = uc->uc_mcontext.gregs[REG_RBP]; … … 587 695 /* XXX: check address validity with program info */ 588 696 *paddr = ((addr_t *)fp)[-1]; 697 return 0; 698 } 699 } 700 701 /* ------------------------------------------------------------- */ 702 #elif defined(__aarch64__) 703 704 static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level) 705 { 706 if (level < 0) 707 return -1; 708 else if (level == 0) { 709 *paddr = uc->uc_mcontext.pc; 710 return 0; 711 } 712 else { 713 addr_t *fp = (addr_t *)uc->uc_mcontext.regs[29]; 714 int i; 715 for (i = 1; i < level; i++) 716 fp = (addr_t *)fp[0]; 717 *paddr = fp[1]; 589 718 return 0; 590 719 } … … 635 764 } 636 765 637 #ifdef _WIN64638 static void win64_add_function_table(TCCState *s1)639 {640 RtlAddFunctionTable(641 (RUNTIME_FUNCTION*)s1->uw_pdata->sh_addr,642 s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),643 text_section->sh_addr644 );645 }646 #endif647 648 766 /* return the PC at frame level 'level'. Return non zero if not found */ 649 767 static int rt_get_caller_pc(addr_t *paddr, CONTEXT *uc, int level) … … 696 814 } TCCSyms; 697 815 816 #if !defined(CONFIG_TCCBOOT) 817 extern int __environ; 818 extern int __expand_heap; 819 extern int __get_handler_set; 820 extern int __get_locale; 821 extern int __gmt; 822 extern int __h_errno_location; 823 extern int __hwcap; 824 extern int __init_tls; 825 extern int __libc; 826 extern int __libc_sigaction; 827 extern int __libc_start_main; 828 extern int __malloc0; 829 extern int __ofl_lock; 830 extern int __ofl_unlock; 831 extern int __progname; 832 extern int __progname_full; 833 extern int __secs_to_zone; 834 extern int __sigaction; 835 extern int __sysinfo; 836 extern int __tm_to_tzname; 837 //extern int atexit; 838 //extern int environ; 839 //extern int free; 840 extern int gethostbyname2; 841 //extern int getopt; 842 extern int getpwnam; 843 //extern int gmtime; 844 //extern int localtime; 845 //extern int malloc; 846 extern int mbrtowc; 847 //extern int optarg; 848 extern int optind; 849 //extern int rand; 850 //extern int realloc; 851 //extern int setenv; 852 extern int setlocale; 853 //extern int sigaction; 854 //extern int srand; 855 //extern int stderr; 856 //extern int stdin; 857 //extern int stdout; 858 //extern int strtok; 859 extern int syslog; 860 extern int vsyslog; 861 #endif 698 862 699 863 /* add the symbol you want here if no dynamic linking is done */ … … 701 865 #if !defined(CONFIG_TCCBOOT) 702 866 #define TCCSYM(a) { #a, &a, }, 703 TCCSYM(printf) 704 TCCSYM(fprintf) 705 TCCSYM(fopen) 706 TCCSYM(fclose) 867 TCCSYM(__environ) 868 TCCSYM(__expand_heap) 869 TCCSYM(__get_handler_set) 870 TCCSYM(__get_locale) 871 TCCSYM(__gmt) 872 TCCSYM(__h_errno_location) 873 TCCSYM(__hwcap) 874 TCCSYM(__init_tls) 875 TCCSYM(__libc) 876 TCCSYM(__libc_sigaction) 877 TCCSYM(__libc_start_main) 878 TCCSYM(__malloc0) 879 TCCSYM(__ofl_lock) 880 TCCSYM(__ofl_unlock) 881 TCCSYM(__progname) 882 TCCSYM(__progname_full) 883 TCCSYM(__secs_to_zone) 884 TCCSYM(__sigaction) 885 TCCSYM(__sysinfo) 886 TCCSYM(__tm_to_tzname) 887 TCCSYM(atexit) 888 TCCSYM(environ) 889 TCCSYM(free) 890 TCCSYM(gethostbyname2) 891 TCCSYM(getopt) 892 TCCSYM(getpwnam) 893 TCCSYM(gmtime) 894 TCCSYM(localtime) 895 TCCSYM(malloc) 896 TCCSYM(mbrtowc) 897 TCCSYM(optarg) 898 TCCSYM(optind) 899 TCCSYM(rand) 900 TCCSYM(realloc) 901 TCCSYM(setenv) 902 TCCSYM(setlocale) 903 TCCSYM(sigaction) 904 TCCSYM(srand) 905 TCCSYM(stderr) 906 TCCSYM(stdin) 907 TCCSYM(stdout) 908 TCCSYM(strtok) 909 TCCSYM(syslog) 910 TCCSYM(vsyslog) 707 911 #undef TCCSYM 708 912 #endif … … 710 914 }; 711 915 712 ST_FUNC void * resolve_sym(TCCState *s1, const char *symbol)916 ST_FUNC void *dlsym(void *handle, const char *symbol) 713 917 { 714 918 TCCSyms *p; … … 722 926 } 723 927 724 #elif !defined(_WIN32)725 726 ST_FUNC void *resolve_sym(TCCState *s1, const char *sym)727 {728 return dlsym(RTLD_DEFAULT, sym);729 }730 731 928 #endif /* CONFIG_TCC_STATIC */ 732 929 #endif /* TCC_IS_NATIVE */ -
EcnlProtoTool/trunk/tcc-0.9.27/tcctok.h
r321 r331 37 37 DEF(TOK_RESTRICT3, "__restrict__") 38 38 DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */ 39 39 40 DEF(TOK_GENERIC, "_Generic") 41 40 42 DEF(TOK_FLOAT, "float") 41 43 DEF(TOK_DOUBLE, "double") … … 59 61 DEF(TOK_ASM2, "__asm") 60 62 DEF(TOK_ASM3, "__asm__") 63 64 #ifdef TCC_TARGET_ARM64 65 DEF(TOK_UINT128, "__uint128_t") 66 #endif 61 67 62 68 /*********************************************************************/ … … 82 88 DEF(TOK___FUNCTION__, "__FUNCTION__") 83 89 DEF(TOK___VA_ARGS__, "__VA_ARGS__") 90 DEF(TOK___COUNTER__, "__COUNTER__") 84 91 85 92 /* special identifiers */ … … 114 121 DEF(TOK_FASTCALL2, "__fastcall") 115 122 DEF(TOK_FASTCALL3, "__fastcall__") 123 DEF(TOK_REGPARM1, "regparm") 124 DEF(TOK_REGPARM2, "__regparm__") 125 116 126 DEF(TOK_MODE, "__mode__") 127 DEF(TOK_MODE_QI, "__QI__") 117 128 DEF(TOK_MODE_DI, "__DI__") 118 129 DEF(TOK_MODE_HI, "__HI__") 119 130 DEF(TOK_MODE_SI, "__SI__") 131 DEF(TOK_MODE_word, "__word__") 132 120 133 DEF(TOK_DLLEXPORT, "dllexport") 121 134 DEF(TOK_DLLIMPORT, "dllimport") 122 135 DEF(TOK_NORETURN1, "noreturn") 123 136 DEF(TOK_NORETURN2, "__noreturn__") 137 DEF(TOK_VISIBILITY1, "visibility") 138 DEF(TOK_VISIBILITY2, "__visibility__") 139 124 140 DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p") 141 DEF(TOK_builtin_choose_expr, "__builtin_choose_expr") 125 142 DEF(TOK_builtin_constant_p, "__builtin_constant_p") 126 143 DEF(TOK_builtin_frame_address, "__builtin_frame_address") 127 #ifdef TCC_TARGET_X86_64 144 DEF(TOK_builtin_return_address, "__builtin_return_address") 145 DEF(TOK_builtin_expect, "__builtin_expect") 146 /*DEF(TOK_builtin_va_list, "__builtin_va_list")*/ 147 #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64 148 DEF(TOK_builtin_va_start, "__builtin_va_start") 149 #elif defined TCC_TARGET_X86_64 128 150 DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types") 129 #endif 130 DEF(TOK_REGPARM1, "regparm") 131 DEF(TOK_REGPARM2, "__regparm__") 151 #elif defined TCC_TARGET_ARM64 152 DEF(TOK___va_start, "__va_start") 153 DEF(TOK___va_arg, "__va_arg") 154 #endif 132 155 133 156 /* pragma */ … … 138 161 DEF(TOK_ASM_pop, "pop") 139 162 #endif 163 DEF(TOK_comment, "comment") 164 DEF(TOK_lib, "lib") 165 DEF(TOK_push_macro, "push_macro") 166 DEF(TOK_pop_macro, "pop_macro") 167 DEF(TOK_once, "once") 168 DEF(TOK_option, "option") 140 169 141 170 /* builtin functions or variables */ 142 #ifdef TCC_ARM_EABI 143 DEF(TOK_memcpy, "__aeabi_memcpy") 144 DEF(TOK_memcpy4, "__aeabi_memcpy4") 145 DEF(TOK_memcpy8, "__aeabi_memcpy8") 146 DEF(TOK_memset, "__aeabi_memset") 147 DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod") 148 DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod") 149 #else 171 #ifndef TCC_ARM_EABI 150 172 DEF(TOK_memcpy, "memcpy") 173 DEF(TOK_memmove, "memmove") 151 174 DEF(TOK_memset, "memset") 152 175 DEF(TOK___divdi3, "__divdi3") … … 154 177 DEF(TOK___udivdi3, "__udivdi3") 155 178 DEF(TOK___umoddi3, "__umoddi3") 156 #endif 157 #if defined(TCC_TARGET_ARM) 158 #ifdef TCC_ARM_EABI 179 DEF(TOK___ashrdi3, "__ashrdi3") 180 DEF(TOK___lshrdi3, "__lshrdi3") 181 DEF(TOK___ashldi3, "__ashldi3") 182 DEF(TOK___floatundisf, "__floatundisf") 183 DEF(TOK___floatundidf, "__floatundidf") 184 # ifndef TCC_ARM_VFP 185 DEF(TOK___floatundixf, "__floatundixf") 186 DEF(TOK___fixunsxfdi, "__fixunsxfdi") 187 # endif 188 DEF(TOK___fixunssfdi, "__fixunssfdi") 189 DEF(TOK___fixunsdfdi, "__fixunsdfdi") 190 #endif 191 192 #if defined TCC_TARGET_ARM 193 # ifdef TCC_ARM_EABI 194 DEF(TOK_memcpy, "__aeabi_memcpy") 195 DEF(TOK_memcpy4, "__aeabi_memcpy4") 196 DEF(TOK_memcpy8, "__aeabi_memcpy8") 197 DEF(TOK_memmove, "__aeabi_memmove") 198 DEF(TOK_memset, "__aeabi_memset") 199 DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod") 200 DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod") 159 201 DEF(TOK___aeabi_idivmod, "__aeabi_idivmod") 160 202 DEF(TOK___aeabi_uidivmod, "__aeabi_uidivmod") … … 165 207 DEF(TOK___fixsfdi, "__aeabi_f2lz") 166 208 DEF(TOK___fixdfdi, "__aeabi_d2lz") 167 #else168 DEF(TOK___modsi3, "__modsi3")169 DEF(TOK___umodsi3, "__umodsi3")170 DEF(TOK___divsi3, "__divsi3")171 DEF(TOK___udivsi3, "__udivsi3")172 DEF(TOK___floatdisf, "__floatdisf")173 DEF(TOK___floatdidf, "__floatdidf")174 #ifndef TCC_ARM_VFP175 DEF(TOK___floatdixf, "__floatdixf")176 DEF(TOK___fixunssfsi, "__fixunssfsi")177 DEF(TOK___fixunsdfsi, "__fixunsdfsi")178 DEF(TOK___fixunsxfsi, "__fixunsxfsi")179 DEF(TOK___fixxfdi, "__fixxfdi")180 #endif181 DEF(TOK___fixsfdi, "__fixsfdi")182 DEF(TOK___fixdfdi, "__fixdfdi")183 #endif184 #elif defined(TCC_TARGET_C67)185 DEF(TOK__divi, "_divi")186 DEF(TOK__divu, "_divu")187 DEF(TOK__divf, "_divf")188 DEF(TOK__divd, "_divd")189 DEF(TOK__remi, "_remi")190 DEF(TOK__remu, "_remu")191 #endif192 #ifdef TCC_TARGET_I386193 DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")194 DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")195 #endif196 #ifdef TCC_ARM_EABI197 209 DEF(TOK___ashrdi3, "__aeabi_lasr") 198 210 DEF(TOK___lshrdi3, "__aeabi_llsr") … … 202 214 DEF(TOK___fixunssfdi, "__aeabi_f2ulz") 203 215 DEF(TOK___fixunsdfdi, "__aeabi_d2ulz") 204 #else 205 DEF(TOK___ashrdi3, "__ashrdi3") 206 DEF(TOK___lshrdi3, "__lshrdi3") 207 DEF(TOK___ashldi3, "__ashldi3") 208 DEF(TOK___floatundisf, "__floatundisf") 209 DEF(TOK___floatundidf, "__floatundidf") 210 #ifndef TCC_ARM_VFP 211 DEF(TOK___floatundixf, "__floatundixf") 212 DEF(TOK___fixunsxfdi, "__fixunsxfdi") 213 #endif 214 DEF(TOK___fixunssfdi, "__fixunssfdi") 215 DEF(TOK___fixunsdfdi, "__fixunsdfdi") 216 #endif 217 #ifdef TCC_TARGET_PE 216 # else 217 DEF(TOK___modsi3, "__modsi3") 218 DEF(TOK___umodsi3, "__umodsi3") 219 DEF(TOK___divsi3, "__divsi3") 220 DEF(TOK___udivsi3, "__udivsi3") 221 DEF(TOK___floatdisf, "__floatdisf") 222 DEF(TOK___floatdidf, "__floatdidf") 223 # ifndef TCC_ARM_VFP 224 DEF(TOK___floatdixf, "__floatdixf") 225 DEF(TOK___fixunssfsi, "__fixunssfsi") 226 DEF(TOK___fixunsdfsi, "__fixunsdfsi") 227 DEF(TOK___fixunsxfsi, "__fixunsxfsi") 228 DEF(TOK___fixxfdi, "__fixxfdi") 229 # endif 230 DEF(TOK___fixsfdi, "__fixsfdi") 231 DEF(TOK___fixdfdi, "__fixdfdi") 232 # endif 233 #endif 234 235 #if defined TCC_TARGET_C67 236 DEF(TOK__divi, "_divi") 237 DEF(TOK__divu, "_divu") 238 DEF(TOK__divf, "_divf") 239 DEF(TOK__divd, "_divd") 240 DEF(TOK__remi, "_remi") 241 DEF(TOK__remu, "_remu") 242 #endif 243 244 #if defined TCC_TARGET_I386 245 DEF(TOK___fixsfdi, "__fixsfdi") 246 DEF(TOK___fixdfdi, "__fixdfdi") 247 DEF(TOK___fixxfdi, "__fixxfdi") 248 #endif 249 250 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 251 DEF(TOK_alloca, "alloca") 252 #endif 253 254 #if defined TCC_TARGET_PE 218 255 DEF(TOK___chkstk, "__chkstk") 256 #endif 257 #ifdef TCC_TARGET_ARM64 258 DEF(TOK___arm64_clear_cache, "__arm64_clear_cache") 259 DEF(TOK___addtf3, "__addtf3") 260 DEF(TOK___subtf3, "__subtf3") 261 DEF(TOK___multf3, "__multf3") 262 DEF(TOK___divtf3, "__divtf3") 263 DEF(TOK___extendsftf2, "__extendsftf2") 264 DEF(TOK___extenddftf2, "__extenddftf2") 265 DEF(TOK___trunctfsf2, "__trunctfsf2") 266 DEF(TOK___trunctfdf2, "__trunctfdf2") 267 DEF(TOK___fixtfsi, "__fixtfsi") 268 DEF(TOK___fixtfdi, "__fixtfdi") 269 DEF(TOK___fixunstfsi, "__fixunstfsi") 270 DEF(TOK___fixunstfdi, "__fixunstfdi") 271 DEF(TOK___floatsitf, "__floatsitf") 272 DEF(TOK___floatditf, "__floatditf") 273 DEF(TOK___floatunsitf, "__floatunsitf") 274 DEF(TOK___floatunditf, "__floatunditf") 275 DEF(TOK___eqtf2, "__eqtf2") 276 DEF(TOK___netf2, "__netf2") 277 DEF(TOK___lttf2, "__lttf2") 278 DEF(TOK___letf2, "__letf2") 279 DEF(TOK___gttf2, "__gttf2") 280 DEF(TOK___getf2, "__getf2") 219 281 #endif 220 282 … … 228 290 DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12") 229 291 DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16") 292 DEF(TOK___bound_main_arg, "__bound_main_arg") 230 293 DEF(TOK___bound_local_new, "__bound_local_new") 231 294 DEF(TOK___bound_local_delete, "__bound_local_delete") 232 # ifdef TCC_TARGET_PE295 # ifdef TCC_TARGET_PE 233 296 DEF(TOK_malloc, "malloc") 234 297 DEF(TOK_free, "free") … … 236 299 DEF(TOK_memalign, "memalign") 237 300 DEF(TOK_calloc, "calloc") 238 #endif 239 DEF(TOK_memmove, "memmove") 301 # endif 240 302 DEF(TOK_strlen, "strlen") 241 303 DEF(TOK_strcpy, "strcpy") 242 304 #endif 243 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64244 DEF(TOK_alloca, "alloca")245 #endif246 305 247 306 /* Tiny Assembler */ 248 DEF_ASM(byte) 249 DEF_ASM(word) 250 DEF_ASM(align) 251 DEF_ASM(skip) 252 DEF_ASM(space) 253 DEF_ASM(string) 254 DEF_ASM(asciz) 255 DEF_ASM(ascii) 256 DEF_ASM(file) 257 DEF_ASM(globl) 258 DEF_ASM(global) 259 DEF_ASM(ident) 260 DEF_ASM(size) 261 DEF_ASM(type) 262 DEF_ASM(text) 263 DEF_ASM(data) 264 DEF_ASM(bss) 265 DEF_ASM(previous) 266 DEF_ASM(fill) 267 DEF_ASM(org) 268 DEF_ASM(quad) 307 DEF_ASMDIR(byte) /* must be first directive */ 308 DEF_ASMDIR(word) 309 DEF_ASMDIR(align) 310 DEF_ASMDIR(balign) 311 DEF_ASMDIR(p2align) 312 DEF_ASMDIR(set) 313 DEF_ASMDIR(skip) 314 DEF_ASMDIR(space) 315 DEF_ASMDIR(string) 316 DEF_ASMDIR(asciz) 317 DEF_ASMDIR(ascii) 318 DEF_ASMDIR(file) 319 DEF_ASMDIR(globl) 320 DEF_ASMDIR(global) 321 DEF_ASMDIR(weak) 322 DEF_ASMDIR(hidden) 323 DEF_ASMDIR(ident) 324 DEF_ASMDIR(size) 325 DEF_ASMDIR(type) 326 DEF_ASMDIR(text) 327 DEF_ASMDIR(data) 328 DEF_ASMDIR(bss) 329 DEF_ASMDIR(previous) 330 DEF_ASMDIR(pushsection) 331 DEF_ASMDIR(popsection) 332 DEF_ASMDIR(fill) 333 DEF_ASMDIR(rept) 334 DEF_ASMDIR(endr) 335 DEF_ASMDIR(org) 336 DEF_ASMDIR(quad) 269 337 #if defined(TCC_TARGET_I386) 270 DEF_ASM (code16)271 DEF_ASM (code32)338 DEF_ASMDIR(code16) 339 DEF_ASMDIR(code32) 272 340 #elif defined(TCC_TARGET_X86_64) 273 DEF_ASM(code64) 274 #endif 341 DEF_ASMDIR(code64) 342 #endif 343 DEF_ASMDIR(short) 344 DEF_ASMDIR(long) 345 DEF_ASMDIR(int) 346 DEF_ASMDIR(section) /* must be last directive */ 275 347 276 348 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 -
EcnlProtoTool/trunk/tcc-0.9.27/tests/Makefile
r279 r331 5 5 TOP = .. 6 6 include $(TOP)/Makefile 7 VPATH = $(top_srcdir)/tests 7 VPATH = $(TOPSRC)/tests $(TOPSRC) $(TOP) 8 CFLAGS := $(filter-out -W% -g% -O%,$(CFLAGS)) -I$(TOPSRC) $(LDFLAGS) 8 9 9 10 # what tests to run … … 13 14 libtest \ 14 15 test3 \ 15 moretests 16 memtest \ 17 dlltest \ 18 abitest \ 19 asm-c-connect-test \ 20 vla_test-run \ 21 cross-test \ 22 tests2-dir \ 23 pp-dir 24 25 BTESTS = test1b test3b btest 16 26 17 27 # test4 -- problem with -static 18 # asmtest -- minor differences with gcc28 # asmtest / asmtest2 -- minor differences with gcc 19 29 # btest -- works on i386 (including win32) 20 # test3 -- win32 does not know how to printf long doubles21 30 22 31 # bounds-checking is supported only on i386 23 32 ifneq ($(ARCH),i386) 24 TESTS := $(filter-out btest,$(TESTS))33 TESTS := $(filter-out $(BTESTS),$(TESTS)) 25 34 endif 26 35 ifdef CONFIG_WIN32 36 TESTS := $(filter-out $(BTESTS),$(TESTS)) 37 endif 38 ifdef CONFIG_OSX # -run only 39 TESTS := hello-run libtest tests2-dir pp-dir 40 endif 41 ifeq (,$(filter arm64 i386 x86_64,$(ARCH))) 42 TESTS := $(filter-out vla_test-run,$(TESTS)) 43 endif 44 ifeq ($(CONFIG_arm_eabi),yes) 27 45 TESTS := $(filter-out test3,$(TESTS)) 28 46 endif 29 ifeq ($(TARGETOS),Darwin) 30 TESTS := $(filter-out hello-exe test3 btest,$(TESTS)) 31 endif 32 33 ifdef DISABLE_STATIC 34 export LD_LIBRARY_PATH:=$(CURDIR)/.. 35 endif 36 37 ifeq ($(TARGETOS),Darwin) 38 CFLAGS+=-Wl,-flat_namespace,-undefined,warning 39 export MACOSX_DEPLOYMENT_TARGET:=10.2 40 NATIVE_DEFINES+=-D_ANSI_SOURCE 41 endif 42 43 # run local version of tcc with local libraries and includes 44 TCCFLAGS = -B$(TOP) 45 ifdef CONFIG_WIN32 46 TCCFLAGS = -B$(top_srcdir)/win32 -I$(top_srcdir)/include -L$(TOP) 47 endif 48 49 TCC = $(TOP)/tcc $(TCCFLAGS) 50 RUN_TCC = $(NATIVE_DEFINES) -DONE_SOURCE -run $(TOP)/tcc.c $(TCCFLAGS) 51 47 ifeq (,$(filter i386 x86_64,$(ARCH))) 48 TESTS := $(filter-out dlltest asm-c-connect-test,$(TESTS)) 49 endif 50 ifndef CONFIG_cross 51 TESTS := $(filter-out cross-%,$(TESTS)) 52 endif 53 54 ifeq ($(OS),Windows_NT) # for libtcc_test to find libtcc.dll 55 PATH := $(CURDIR)/$(TOP)$(if $(findstring :\,$(PATH)),;,:)$(PATH) 56 endif 57 58 RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) 52 59 DISAS = objdump -d 53 54 # libtcc test 55 ifdef LIBTCC1 56 LIBTCC1:=$(TOP)/$(LIBTCC1) 57 endif 58 59 all test : $(TESTS) 60 DUMPTCC = (set -x; $(TOP)/tcc -vv; ldd $(TOP)/tcc; exit 1) 61 62 all test : clean-s $(TESTS) 60 63 61 64 hello-exe: ../examples/ex1.c 62 65 @echo ------------ $@ ------------ 63 $(TCC) $< -o hello$(EXESUF) || ($(TOP)/tcc -vv; exit 1) && ./hello$(EXESUF)66 $(TCC) $< -o hello$(EXESUF) && ./hello$(EXESUF) || $(DUMPTCC) 64 67 65 68 hello-run: ../examples/ex1.c 66 69 @echo ------------ $@ ------------ 67 $(TCC) -run $< 68 69 libtest: libtcc_test$(EXESUF) $(LIBTCC1) 70 @echo ------------ $@ ------------ 71 ./libtcc_test$(EXESUF) lib_path=.. 72 73 libtcc_test$(EXESUF): libtcc_test.c $(top_builddir)/$(LIBTCC) 74 $(CC) -o $@ $^ $(CPPFLAGS) $(CFLAGS) $(NATIVE_DEFINES) $(LIBS) $(LINK_LIBTCC) $(LDFLAGS) 75 76 moretests: 77 @echo ------------ $@ ------------ 78 $(MAKE) -C tests2 79 80 # test.ref - generate using gcc 81 # copy only tcclib.h so GCC's stddef and stdarg will be used 70 $(TCC) -run $< || $(DUMPTCC) 71 72 libtest: libtcc_test$(EXESUF) 73 @echo ------------ $@ ------------ 74 ./libtcc_test$(EXESUF) $(TCCFLAGS) 75 76 libtcc_test$(EXESUF): libtcc_test.c $(LIBTCC) 77 $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 78 79 %-dir: 80 @echo ------------ $@ ------------ 81 $(MAKE) -k -C $* 82 83 # test.ref - generate using cc 82 84 test.ref: tcctest.c 83 cp ../include/tcclib.h . 84 gcc -o tcctest.gcc $< -I. $(CPPFLAGS) -w $(CFLAGS) $(NATIVE_DEFINES) -std=gnu99 -O0 -fno-omit-frame-pointer $(LDFLAGS) 85 $(CC) -o tcctest.gcc $< $(NATIVE_DEFINES) $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer 85 86 ./tcctest.gcc > $@ 86 87 87 88 # auto test 88 test1 :test.ref89 @echo ------------ $@ ------------ 90 $(TCC) -run tcctest.c> test.out191 @ if diff -u test.ref test.out1 ; then echo "Auto Test OK"; fi89 test1 test1b: tcctest.c test.ref 90 @echo ------------ $@ ------------ 91 $(TCC) -run $< > test.out1 92 @diff -u test.ref test.out1 && echo "Auto Test OK" 92 93 93 94 # iterated test2 (compile tcc then compile tcctest.c !) 94 test2 :test.ref95 @echo ------------ $@ ------------ 96 $(TCC) $(RUN_TCC) $(RUN_TCC) -run tcctest.c> test.out297 @ if diff -u test.ref test.out2 ; then echo "Auto Test2 OK"; fi95 test2 test2b: tcctest.c test.ref 96 @echo ------------ $@ ------------ 97 $(TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out2 98 @diff -u test.ref test.out2 && echo "Auto Test2 OK" 98 99 99 100 # iterated test3 (compile tcc then compile tcc then compile tcctest.c !) 100 test3: test.ref 101 @echo ------------ $@ ------------ 102 $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run tcctest.c > test.out3 103 @if diff -u test.ref test.out3 ; then echo "Auto Test3 OK"; fi 101 test3 test3b: tcctest.c test.ref 102 @echo ------------ $@ ------------ 103 $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out3 104 @diff -u test.ref test.out3 && echo "Auto Test3 OK" 105 106 test%b : TCCFLAGS += -b 104 107 105 108 # binary output test 106 test4: t est.ref109 test4: tcctest.c test.ref 107 110 @echo ------------ $@ ------------ 108 111 # object + link output 109 $(TCC) -c -o tcctest3.o tcctest.c112 $(TCC) -c -o tcctest3.o $< 110 113 $(TCC) -o tcctest3 tcctest3.o 111 114 ./tcctest3 > test3.out 112 115 @if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi 113 116 # dynamic output 114 $(TCC) -o tcctest1 tcctest.c117 $(TCC) -o tcctest1 $< 115 118 ./tcctest1 > test1.out 116 119 @if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi 117 120 # dynamic output + bound check 118 $(TCC) -b -o tcctest4 tcctest.c121 $(TCC) -b -o tcctest4 $< 119 122 ./tcctest4 > test4.out 120 123 @if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi 121 124 # static output 122 $(TCC) -static -o tcctest2 tcctest.c125 $(TCC) -static -o tcctest2 $< 123 126 ./tcctest2 > test2.out 124 127 @if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi 128 129 # use tcc to create libtcc.so/.dll and the tcc(.exe) frontend and run them 130 dlltest: 131 @echo ------------ $@ ------------ 132 $(TCC) $(NATIVE_DEFINES) -DLIBTCC_AS_DLL $(TOPSRC)/libtcc.c $(LIBS) -shared -o libtcc2$(DLLSUF) 133 $(TCC) $(NATIVE_DEFINES) -DONE_SOURCE=0 $(TOPSRC)/tcc.c libtcc2$(DLLSUF) $(LIBS) -Wl,-rpath=. -o tcc2$(EXESUF) 134 ./tcc2$(EXESUF) $(TCCFLAGS) $(RUN_TCC) -run $(TOPSRC)/examples/ex1.c 135 ifndef CONFIG_WIN32 136 @echo ------------ $@ with PIC ------------ 137 $(CC) $(CFLAGS) -fPIC $(NATIVE_DEFINES) -DLIBTCC_AS_DLL -c $(TOPSRC)/libtcc.c 138 $(TCC) libtcc.o $(LIBS) -shared -o libtcc2$(DLLSUF) 139 $(TCC) $(NATIVE_DEFINES) -DONE_SOURCE=0 $(TOPSRC)/tcc.c libtcc2$(DLLSUF) $(LIBS) -Wl,-rpath=. -o tcc2$(EXESUF) 140 ./tcc2$(EXESUF) $(TCCFLAGS) $(RUN_TCC) -run $(TOPSRC)/examples/ex1.c 141 endif 142 @rm tcc2$(EXESUF) libtcc2$(DLLSUF) 143 144 memtest: 145 @echo ------------ $@ ------------ 146 $(CC) $(CFLAGS) $(NATIVE_DEFINES) -DMEM_DEBUG=2 $(TOPSRC)/tcc.c $(LIBS) -o memtest-tcc$(EXESUF) 147 ./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) $(TOPSRC)/tcc.c $(LIBS) 148 ./memtest-tcc$(EXESUF) $(TCCFLAGS) $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) $(TOPSRC)/tests/tcctest.c 149 125 150 126 151 # memory and bound check auto test … … 132 157 @for i in $(BOUNDS_OK); do \ 133 158 echo ; echo --- boundtest $$i ---; \ 134 if $(TCC) -b -run boundtest.c$$i ; then \135 echo succe ded as expected; \159 if $(TCC) -b -run $< $$i ; then \ 160 echo succeeded as expected; \ 136 161 else\ 137 162 echo Failed positive test $$i ; exit 1 ; \ … … 140 165 for i in $(BOUNDS_FAIL); do \ 141 166 echo ; echo --- boundtest $$i ---; \ 142 if $(TCC) -b -run boundtest.c$$i ; then \167 if $(TCC) -b -run $< $$i ; then \ 143 168 echo Failed negative test $$i ; exit 1 ;\ 144 169 else\ … … 152 177 @echo ------------ $@ ------------ 153 178 time ./ex2 1238 2 3 4 10 13 4 154 time $(TCC) -run $( top_srcdir)/examples/ex2.c 1238 2 3 4 10 13 4179 time $(TCC) -run $(TOPSRC)/examples/ex2.c 1238 2 3 4 10 13 4 155 180 time ./ex3 35 156 time $(TCC) -run $( top_srcdir)/examples/ex3.c 35157 158 weaktest: t est.ref159 $(TCC) -c tcctest.c -o weaktest.tcc.o $(CPPFLAGS) $(CFLAGS)160 $(CC) -c tcctest.c -o weaktest.gcc.o -I. $(CPPFLAGS) -w $(CFLAGS)181 time $(TCC) -run $(TOPSRC)/examples/ex3.c 35 182 183 weaktest: tcctest.c test.ref 184 $(TCC) -c $< -o weaktest.tcc.o 185 $(CC) -c $< -o weaktest.gcc.o $(NATIVE_DEFINES) $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer 161 186 objdump -t weaktest.tcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.tcc.o.txt 162 187 objdump -t weaktest.gcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.gcc.o.txt 163 188 diff weaktest.gcc.o.txt weaktest.tcc.o.txt && echo "Weak Auto Test OK" 164 189 165 ex%: $( top_srcdir)/examples/ex%.c166 $(CC) -o $@ $< $(C PPFLAGS) $(CFLAGS) $(LDFLAGS)190 ex%: $(TOPSRC)/examples/ex%.c 191 $(CC) -o $@ $< $(CFLAGS) 167 192 168 193 # tiny assembler testing … … 171 196 objdump -D asmtest.ref.o > asmtest.ref 172 197 173 asmtest : asmtest.ref174 @echo ------------ $@ ------------ 175 $(TCC) -c asmtest.S198 asmtest asmtest2: asmtest.ref 199 @echo ------------ $@ ------------ 200 $(TCC) $(MAYBE_RUN_TCC) -c asmtest.S 176 201 objdump -D asmtest.o > asmtest.out 177 202 @if diff -u --ignore-matching-lines="file format" asmtest.ref asmtest.out ; then echo "ASM Auto Test OK"; fi 203 204 # test assembler with tcc compiled by itself 205 asmtest2: MAYBE_RUN_TCC = $(RUN_TCC) 206 207 # Check that code generated by libtcc is binary compatible with 208 # that generated by CC 209 abitest-cc$(EXESUF): abitest.c $(LIBTCC) 210 $(CC) -o $@ $^ $(CFLAGS) $(LIBS) -w 211 212 abitest-tcc$(EXESUF): abitest.c libtcc.c 213 $(TCC) -o $@ $^ $(NATIVE_DEFINES) $(LIBS) 214 215 ABITESTS := abitest-cc$(EXESUF) 216 ifneq ($(CONFIG_arm_eabi),yes) # not ARM soft-float 217 ABITESTS += abitest-tcc$(EXESUF) 218 endif 219 220 abitest: $(ABITESTS) 221 @echo ------------ $@ ------------ 222 ./abitest-cc$(EXESUF) $(TCCFLAGS) 223 ifneq ($(CONFIG_arm_eabi),yes) # not ARM soft-float 224 ./abitest-tcc$(EXESUF) $(TCCFLAGS) 225 endif 226 227 vla_test$(EXESUF): vla_test.c 228 $(TCC) -o $@ $^ 229 230 vla_test-run: vla_test$(EXESUF) 231 @echo ------------ $@ ------------ 232 ./vla_test$(EXESUF) 233 234 asm-c-connect$(EXESUF): asm-c-connect-1.c asm-c-connect-2.c 235 $(TCC) -o $@ $^ 236 237 asm-c-connect-%.o: asm-c-connect-%.c 238 $(TCC) -c -o $@ $< 239 240 asm-c-connect-sep$(EXESUF): asm-c-connect-1.o asm-c-connect-2.o 241 $(TCC) -o $@ $^ 242 243 asm-c-connect-test: asm-c-connect$(EXESUF) asm-c-connect-sep$(EXESUF) 244 @echo ------------ $@ ------------ 245 ./asm-c-connect$(EXESUF) > asm-c-connect.out1 && cat asm-c-connect.out1 246 ./asm-c-connect-sep$(EXESUF) > asm-c-connect.out2 && cat asm-c-connect.out2 247 @diff -u asm-c-connect.out1 asm-c-connect.out2 && echo "ok" 248 249 cross-test : 250 @echo ------------ $@ ------------ 251 $(TOP)/i386-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok" 252 $(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/examples/ex3.c && echo "ok" 253 $(TOP)/x86_64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok" 254 $(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/examples/ex3.c && echo "ok" 255 $(TOP)/arm-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok" 256 $(TOP)/arm-wince-tcc$(EXESUF) $(TCCFLAGS-win) -c $(TOPSRC)/examples/ex3.c && echo "ok" 257 $(TOP)/arm64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok" 258 $(TOP)/c67-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok" 259 $(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok" 260 $(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok" 261 $(TOP)/arm-wince-tcc$(EXESUF) $(TCCFLAGS-win) -c $(TOPSRC)/win32/examples/hello_win.c && echo "ok" 178 262 179 263 # targets for development … … 194 278 # clean 195 279 clean: 196 $(MAKE) -C tests2 $@ 197 rm -vf *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.gcc *.exe \ 198 hello libtcc_test tcctest[1234] ex? tcc_g tcclib.h 199 280 rm -f *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.cc *.gcc 281 rm -f *-cc *-gcc *-tcc *.exe hello libtcc_test vla_test tcctest[1234] 282 rm -f asm-c-connect$(EXESUF) 283 rm -f ex? tcc_g weaktest.*.txt *.def 284 @$(MAKE) -C tests2 $@ 285 @$(MAKE) -C pp $@ 286 287 # silent clean, used before running tests 288 clean-s: 289 @$(MAKE) -s --no-print-directory clean -
EcnlProtoTool/trunk/tcc-0.9.27/tests/asmtest.S
- Property svn:keywords deleted
r279 r331 12 12 .byte 1 13 13 /* .align 16, 0x90 gas is too clever for us with 0x90 fill */ 14 .balign 4, 0x92 14 15 .align 16, 0x91 /* 0x91 tests the non-clever behaviour */ 15 16 .skip 3 16 17 .skip 15, 0x90 17 18 .string "hello\0world" 18 19 /* Macro expansion should work like with C, the #n shouldn't be parsed 20 as asm line comment */ 21 #define __stringify(n) #n 22 #define stringify(n) __stringify(n) 23 .skip 8,0x90 24 .asciz stringify(BLA) 25 .skip 8,0x90 26 27 # 28 "asmtest.S" # a line directive (and a line comment) 28 movl %eax, %ebx # some more asm comment 19 29 /* some label tests */ 20 21 movl %eax, %ebx22 30 L1: 23 31 movl %eax, %ebx … … 39 47 mov $1, %edx 40 48 mov $1, %dx 41 mov $1, % dl49 mov $1, %cl 42 50 movb $2, 0x100(%ebx,%edx,2) 43 51 movw $2, 0x100(%ebx,%edx,2) … … 47 55 movw %ax, 0x100(%ebx,%edx,2) 48 56 57 movw $0x1122,%si 58 movl $0x112233,%edx 59 movl $0x80000000, %esi 60 movl $-0x7fffffff, %edi 61 #ifdef __x86_64__ 62 mov $0x11223344,%rbx 63 movq $0x11223344,%rbx 64 mov $0x1122334455,%rbx 65 movq $0x1122334455,%rbx 66 movl $0x11334455,(%rbx) 67 #endif 68 49 69 mov %eax, 0x12(,%edx,2) 50 70 71 #ifdef __i386__ 51 72 mov %cr3, %edx 52 73 mov %ecx, %cr3 … … 55 76 movl %db3, %ebx 56 77 movl %dr6, %eax 78 #else 79 mov %cr3, %rdx 80 mov %rcx, %cr3 81 movq %cr3, %rax 82 movq %db3, %rbx 83 movq %dr6, %rax 84 mov %cr8, %rsi 85 mov %rdi, %cr8 86 #endif 57 87 movl %fs, %ecx 58 88 movl %ebx, %fs 89 90 #ifdef __x86_64__ 91 movq %r8, %r9 92 movq %r10, %r11 93 movq %r12, %r13 94 movq %r14, %r15 95 movq %rax, %r9 96 movq %r15, %rsi 97 inc %r9b 98 dec %r10w 99 not %r11d 100 negq %r12 101 decb %r13b 102 incw %r14w 103 notl %r15d 104 #endif 59 105 60 106 movsbl 0x1000, %eax … … 69 115 movzb 0x1000, %ax 70 116 117 mov $0x12345678,%eax 118 119 #ifdef __x86_64__ 120 movzb 0x1000, %rax 121 movzbq 0x1000, %rbx 122 movsbq 0x1000, %rdx 123 movzwq 0x1000, %rdi 124 movswq 0x1000, %rdx 125 movslq %eax, %rcx 126 mov $0x12345678,%rax 127 mov $0x12345678,%rdx 128 mov $0x12345678,%r10 129 mov $0x123456789abcdef0,%rax 130 mov $0x123456789abcdef0,%rcx 131 mov $0x123456789abcdef0,%r11 132 #endif 71 133 134 #ifdef __i386__ 72 135 pushl %eax 73 pushw %ax74 136 push %eax 75 137 push %cs 138 #else 139 pushq %rax 140 push %rax 141 #endif 142 pushw %ax 76 143 push %gs 77 144 push $1 78 145 push $100 146 push 0x42(%eax) 147 pop 0x43(%esi) 79 148 149 #ifdef __i386__ 80 150 popl %eax 81 popw %ax82 151 pop %eax 83 152 pop %ds 153 #else 154 popq %rax 155 pop %rax 156 #endif 157 popw %ax 84 158 pop %fs 85 159 … … 112 186 lea 0x1000(%ebx), %ecx 113 187 188 #ifdef __i386__ 114 189 les 0x2000, %eax 115 190 lds 0x2000, %ebx 191 lss 0x2000, %edx 192 #endif 116 193 lfs 0x2000, %ecx 117 194 lgs 0x2000, %edx 118 lss 0x2000, %edx119 195 120 196 addl $0x123, %eax 121 197 add $0x123, %ebx 198 add $-16, %ecx 199 add $-0x123, %esi 200 add $1, %bx 201 add $1, %ebx 202 add $-1, %bx 203 add $-1, %ebx 204 add $127, %bx 205 addl $127, %ebx 206 addl $-128, %ebx 207 addl $-128, %ebx 208 addl $-129, %ebx 209 addl $128, %ebx 210 addl $255, %ebx 211 addl $256, %ebx 212 andb $0xf, %ah 213 andb $-15, %cl 214 xorb $127, %dh 215 cmpb $42, (%eax) 122 216 addl $0x123, 0x100 123 217 addl $0x123, 0x100(%ebx) … … 128 222 addl $0x123, (%esp) 129 223 cmpl $0x123, (%esp) 224 225 #ifdef __x86_64__ 226 xor %bl,%ah 227 xor %bl,%r8b 228 xor %r9b,%bl 229 xor %sil,%cl 230 add %eax,(%r8d) 231 add %ebx,(%r9) 232 add %edx,(%r10d,%r11d) 233 add %ecx,(%r12,%r13) 234 add %esi,(%r14,%r15,4) 235 add %edi,0x1000(%rbx,%r12,8) 236 add %r11,0x1000(%ebp,%r9d,8) 237 movb $12, %ah 238 movb $13, %bpl 239 movb $14, %dil 240 movb $15, %r12b 241 #endif 130 242 131 243 add %eax, (%ebx) … … 180 292 div %ecx, %eax 181 293 294 and $15,%bx 295 and $-20,%edx 182 296 183 297 shl %edx … … 196 310 call 0x1000 197 311 call L4 312 #ifdef __i386__ 198 313 call *%eax 314 #else 315 call *%rax 316 #endif 199 317 call *0x1000 200 318 call func1 … … 205 323 L6: 206 324 325 #ifdef __i386__ 207 326 lcall $0x100, $0x1000 327 #else 328 lcall *0x100 329 lcall *(%rax) 330 #endif 208 331 209 332 jmp 0x1000 333 jmp *(%edi) 334 #ifdef __i386__ 210 335 jmp *%eax 336 #else 337 jmp *%rax 338 #endif 211 339 jmp *0x1000 212 340 341 #ifdef __i386__ 213 342 ljmp $0x100, $0x1000 343 #else 344 ljmp *0x100 345 ljmp *(%rdi) 346 ljmpl *(%esi) 347 ljmpw *(%esi) 348 #endif 214 349 215 350 ret 351 ret $10 352 #ifdef __i386__ 216 353 retl 217 218 ret $10219 354 retl $10 355 #else 356 retq 357 retq $10 358 #endif 220 359 221 360 lret … … 245 384 246 385 seto %al 386 setc %al 387 setcb %al 247 388 setnp 0x1000 248 389 setl 0xaaaa … … 402 543 403 544 bswap %edx 545 bswapl %ecx 404 546 xadd %ecx, %edx 405 547 xaddb %dl, 0x1000 … … 412 554 invlpg 0x1000 413 555 cmpxchg8b 0x1002 556 #ifdef __x86_64__ 557 cmpxchg16b (%rax) 558 cmpxchg16b (%r10,%r11) 559 #endif 414 560 415 561 fcmovb %st(5), %st … … 431 577 cmovs 0x1000, %eax 432 578 cmovns %edx, %edi 579 cmovne %ax, %si 580 cmovbw %ax, %di 581 cmovnbel %edx, %ecx 582 #ifdef __x86_64__ 583 bswapq %rsi 584 bswapq %r10 585 cmovz %rdi,%rbx 586 cmovpeq %rsi, %rdx 587 #endif 433 588 434 589 int $3 435 590 int $0x10 436 591 592 #ifdef __i386__ 437 593 pusha 438 594 popa 439 clc 440 cld 595 #endif 596 clc # another comment 597 cld # a comment with embedded ' tick 441 598 cli 442 599 clts … … 444 601 lahf 445 602 sahf 603 #ifdef __i386__ 446 604 pushfl 447 605 popfl 606 #else 607 pushfq 608 popfq 609 #endif 448 610 pushf 449 611 popf … … 451 613 std 452 614 sti 615 #ifdef __i386__ 453 616 aaa 454 617 aas … … 457 620 aad 458 621 aam 622 into 623 #endif 459 624 cbw 460 625 cwd … … 467 632 leave 468 633 int3 469 into470 634 iret 471 635 rsm … … 512 676 rdpmc 513 677 ud2 514 678 #ifdef __x86_64__ 679 syscall 680 sysret 681 sysretq 682 lfence 683 mfence 684 sfence 685 prefetchnta 0x18(%rdx) 686 prefetcht0 (%rcx) 687 prefetcht1 (%rsi) 688 prefetcht2 (%rdi) 689 prefetchw (%rdi) 690 clflush 0x1000(%rax,%rcx) 691 fxsaveq (%rdx) 692 fxsaveq (%r11) 693 fxrstorq (%rcx) 694 fxrstorq (%r10) 695 696 #endif 697 698 lar %ax,%dx 699 lar %eax,%dx 700 lar %ax,%edx 701 lar %eax,%edx 702 #ifdef __x86_64__ 703 lar %ax,%rdx 704 lar %eax,%rdx 705 #endif 515 706 emms 516 707 movd %edx, %mm3 … … 557 748 558 749 750 #ifdef __i386__ 559 751 boundl %edx, 0x10000 560 752 boundw %bx, 0x1000 561 753 562 754 arpl %bx, 0x1000 755 #endif 563 756 lar 0x1000, %eax 564 757 lgdt 0x1000 565 758 lidt 0x1000 566 759 lldt 0x1000 760 sgdt 0x1000 761 sidt 0x1000 762 sldt 0x1000 763 #ifdef __x86_64__ 764 lgdtq 0x1000 765 lidtq 0x1000 766 sgdtq 0x1000 767 sidtq 0x1000 768 769 swapgs 770 771 str %rdx 772 str %r9 773 #endif 774 567 775 lmsw 0x1000 568 776 lsl 0x1000, %ecx 569 777 ltr 0x1000 570 571 sgdt 0x1000 572 sidt 0x1000 573 sldt 0x1000 778 ltr %si 574 779 smsw 0x1000 575 780 str 0x1000 781 str %ecx 782 str %dx 576 783 577 784 verr 0x1000 578 785 verw 0x1000 579 786 787 #ifdef __i386__ 580 788 push %ds 581 789 pushw %ds … … 584 792 popw %ds 585 793 popl %ds 794 #endif 586 795 fxsave 1(%ebx) 587 796 fxrstor 1(%ecx) 797 #ifdef __i386__ 588 798 pushl $1 799 #else 800 pushq $1 801 #endif 589 802 pushw $1 590 803 push $1 … … 594 807 #endif 595 808 809 #ifndef _WIN32 596 810 ft1: ft2: ft3: ft4: ft5: ft6: ft7: ft8: ft9: 597 811 xor %eax, %eax … … 606 820 .type ft7,%function 607 821 .type ft8,"function" 822 #endif 608 823 609 824 pause 825 .rept 6 826 nop 827 .endr 828 .fill 4,1,0x90 829 830 .section .text.one,"ax" 831 nop 832 .previous 833 .pushsection .text.one,"ax" 834 nop 835 .pushsection .text.two,"ax" 836 nop 837 .popsection 838 .popsection 839 840 1: ud2 841 .pushsection __bug_table,"a" 842 .align 8 843 2: .long 1b - 2b 844 .long 0x600000 - 2b 845 .long 1b + 42 846 .long 43 + 1b 847 .long 2b + 144 848 .long 145 + 2b 849 .word 164, 0 850 .org 2b+32 851 #ifdef __x86_64__ 852 .quad 1b 853 #else 854 .long 1b 855 #endif 856 .popsection 857 3: mov %eax,%ecx 858 4: 859 .pushsection .text.three, "ax" 860 nop 861 .skip (-((4b-3b) > 0) * 2) , 0x90 862 .popsection 863 864 .globl overrideme 865 .weak overrideme 866 nop 867 .globl notimplemented 868 notimplemented: 869 ret 870 .set overrideme, notimplemented 871 overrideme = notimplemented 872 overrideme: 873 ret 874 875 movd %esi, %mm1 876 movd %edi, %xmm2 877 movd (%ebx), %mm3 878 movd (%ebx), %xmm3 879 movd %mm1, %esi 880 movd %xmm2, %edi 881 movd %mm3, (%edx) 882 movd %xmm3, (%edx) 883 #ifdef __x86_64__ 884 movd %rsi, %mm1 885 movd %rdi, %xmm2 886 movd (%rbx), %mm3 887 movd (%rbx), %xmm3 888 movd %mm1, %r12 889 movd %xmm2, %rdi 890 movd %mm3, (%r8) 891 movd %xmm3, (%r13) 892 #endif 893 894 movq (%ebp), %mm1 895 movq %mm2, (%edi) 896 movq (%edi), %xmm3 897 movq %mm4, %mm5 898 #ifdef __x86_64__ 899 movq %rcx, %mm1 900 movq %rdx, %xmm2 901 movq %r13, %xmm3 902 /* movq mem64->xmm is encoded as f30f7e by GAS, but as 903 660f6e by tcc (which really is a movd and would need 904 a REX.W prefix to be movq). */ 905 movq (%rsi), %xmm3 906 movq %mm1, %rdx 907 movq %xmm3, %rcx 908 movq %xmm4, (%rsi) 909 #endif 910 911 #define TEST_MMX_SSE(insn) \ 912 insn %mm1, %mm2; \ 913 insn %xmm2, %xmm3; \ 914 insn (%ebx), %xmm3; 915 #define TEST_MMX_SSE_I8(insn) \ 916 TEST_MMX_SSE(insn) \ 917 insn $0x42, %mm4; \ 918 insn $0x42, %xmm4; 919 920 TEST_MMX_SSE(packssdw) 921 TEST_MMX_SSE(packsswb) 922 TEST_MMX_SSE(packuswb) 923 TEST_MMX_SSE(paddb) 924 TEST_MMX_SSE(paddw) 925 TEST_MMX_SSE(paddd) 926 TEST_MMX_SSE(paddsb) 927 TEST_MMX_SSE(paddsw) 928 TEST_MMX_SSE(paddusb) 929 TEST_MMX_SSE(paddusw) 930 TEST_MMX_SSE(pand) 931 TEST_MMX_SSE(pandn) 932 TEST_MMX_SSE(pcmpeqb) 933 TEST_MMX_SSE(pcmpeqw) 934 TEST_MMX_SSE(pcmpeqd) 935 TEST_MMX_SSE(pcmpgtb) 936 TEST_MMX_SSE(pcmpgtw) 937 TEST_MMX_SSE(pcmpgtd) 938 TEST_MMX_SSE(pmaddwd) 939 TEST_MMX_SSE(pmulhw) 940 TEST_MMX_SSE(pmullw) 941 TEST_MMX_SSE(por) 942 TEST_MMX_SSE(psllw) 943 TEST_MMX_SSE_I8(psllw) 944 TEST_MMX_SSE(pslld) 945 TEST_MMX_SSE_I8(pslld) 946 TEST_MMX_SSE(psllq) 947 TEST_MMX_SSE_I8(psllq) 948 TEST_MMX_SSE(psraw) 949 TEST_MMX_SSE_I8(psraw) 950 TEST_MMX_SSE(psrad) 951 TEST_MMX_SSE_I8(psrad) 952 TEST_MMX_SSE(psrlw) 953 TEST_MMX_SSE_I8(psrlw) 954 TEST_MMX_SSE(psrld) 955 TEST_MMX_SSE_I8(psrld) 956 TEST_MMX_SSE(psrlq) 957 TEST_MMX_SSE_I8(psrlq) 958 TEST_MMX_SSE(psubb) 959 TEST_MMX_SSE(psubw) 960 TEST_MMX_SSE(psubd) 961 TEST_MMX_SSE(psubsb) 962 TEST_MMX_SSE(psubsw) 963 TEST_MMX_SSE(psubusb) 964 TEST_MMX_SSE(psubusw) 965 TEST_MMX_SSE(punpckhbw) 966 TEST_MMX_SSE(punpckhwd) 967 TEST_MMX_SSE(punpckhdq) 968 TEST_MMX_SSE(punpcklbw) 969 TEST_MMX_SSE(punpcklwd) 970 TEST_MMX_SSE(punpckldq) 971 TEST_MMX_SSE(pxor) 972 973 cvtpi2ps %mm1, %xmm2 974 cvtpi2ps (%ebx), %xmm2 975 TEST_MMX_SSE(pmaxsw) 976 TEST_MMX_SSE(pmaxub) 977 TEST_MMX_SSE(pminsw) 978 TEST_MMX_SSE(pminub) -
EcnlProtoTool/trunk/tcc-0.9.27/tests/boundtest.c
r321 r331 1 1 #include <stdlib.h> 2 2 #include <stdio.h> 3 #include <string.h> 3 4 4 5 #define NB_ITS 1000000 … … 50 51 int *tab4; 51 52 53 fprintf(stderr, "%s start\n", __FUNCTION__); 54 52 55 tab4 = malloc(20 * sizeof(int)); 53 56 for(i=0;i<20;i++) { … … 56 59 free(tab4); 57 60 61 fprintf(stderr, "%s end\n", __FUNCTION__); 58 62 return sum; 59 63 } … … 64 68 int i, sum = 0; 65 69 int *tab4; 70 71 fprintf(stderr, "%s start\n", __FUNCTION__); 66 72 67 73 tab4 = malloc(20 * sizeof(int)); … … 71 77 free(tab4); 72 78 79 fprintf(stderr, "%s end\n", __FUNCTION__); 73 80 return sum; 74 81 } … … 187 194 } 188 195 196 /* ok */ 197 int test16() 198 { 199 char *demo = "This is only a test."; 200 char *p; 201 202 fprintf(stderr, "%s start\n", __FUNCTION__); 203 204 p = alloca(16); 205 strcpy(p,"12345678901234"); 206 printf("alloca: p is %s\n", p); 207 208 /* Test alloca embedded in a larger expression */ 209 printf("alloca: %s\n", strcpy(alloca(strlen(demo)+1),demo) ); 210 211 fprintf(stderr, "%s end\n", __FUNCTION__); 212 } 213 214 /* error */ 215 int test17() 216 { 217 char *demo = "This is only a test."; 218 char *p; 219 220 fprintf(stderr, "%s start\n", __FUNCTION__); 221 222 p = alloca(16); 223 strcpy(p,"12345678901234"); 224 printf("alloca: p is %s\n", p); 225 226 /* Test alloca embedded in a larger expression */ 227 printf("alloca: %s\n", strcpy(alloca(strlen(demo)),demo) ); 228 229 fprintf(stderr, "%s end\n", __FUNCTION__); 230 } 231 189 232 int (*table_test[])(void) = { 190 test1,191 233 test1, 192 234 test2, … … 204 246 test14, 205 247 test15, 248 test16, 249 test17, 206 250 }; 207 251 … … 210 254 int index; 211 255 int (*ftest)(void); 256 int index_max = sizeof(table_test)/sizeof(table_test[0]); 212 257 213 258 if (argc < 2) { 214 printf("usage: boundtest n\n" 215 "test TCC bound checking system\n" 216 ); 259 printf( 260 "test TCC bound checking system\n" 261 "usage: boundtest N\n" 262 " 1 <= N <= %d\n", index_max); 217 263 exit(1); 218 264 } … … 220 266 index = 0; 221 267 if (argc >= 2) 222 index = atoi(argv[1]); 268 index = atoi(argv[1]) - 1; 269 270 if ((index < 0) || (index >= index_max)) { 271 printf("N is outside of the valid range (%d)\n", index); 272 exit(2); 273 } 274 223 275 /* well, we also use bounds on this ! */ 224 276 ftest = table_test[index]; -
EcnlProtoTool/trunk/tcc-0.9.27/tests/libtcc_test.c
r321 r331 16 16 } 17 17 18 /* this strinc is referenced by the generated code */ 19 const char hello[] = "Hello World!"; 20 18 21 char my_program[] = 22 "#include <tcclib.h>\n" /* include the "Simple libc header for TCC" */ 23 "extern int add(int a, int b);\n" 24 "#ifdef _WIN32\n" /* dynamically linked data needs 'dllimport' */ 25 " __attribute__((dllimport))\n" 26 "#endif\n" 27 "extern const char hello[];\n" 19 28 "int fib(int n)\n" 20 29 "{\n" … … 27 36 "int foo(int n)\n" 28 37 "{\n" 29 " printf(\" Hello World!\\n\");\n"38 " printf(\"%s\\n\", hello);\n" 30 39 " printf(\"fib(%d) = %d\\n\", n, fib(n));\n" 31 40 " printf(\"add(%d, %d) = %d\\n\", n, 2 * n, add(n, 2 * n));\n" … … 36 45 { 37 46 TCCState *s; 47 int i; 38 48 int (*func)(int); 39 49 … … 45 55 46 56 /* if tcclib.h and libtcc1.a are not installed, where can we find them */ 47 if (argc == 2 && !memcmp(argv[1], "lib_path=",9)) 48 tcc_set_lib_path(s, argv[1]+9); 57 for (i = 1; i < argc; ++i) { 58 char *a = argv[i]; 59 if (a[0] == '-') { 60 if (a[1] == 'B') 61 tcc_set_lib_path(s, a+2); 62 else if (a[1] == 'I') 63 tcc_add_include_path(s, a+2); 64 else if (a[1] == 'L') 65 tcc_add_library_path(s, a+2); 66 } 67 } 49 68 50 69 /* MUST BE CALLED before any compilation */ … … 54 73 return 1; 55 74 56 /* as a test, we add a symbolthat the compiled program can use.75 /* as a test, we add symbols that the compiled program can use. 57 76 You may also open a dll with tcc_add_dll() and use symbols from that */ 58 77 tcc_add_symbol(s, "add", add); 78 tcc_add_symbol(s, "hello", hello); 59 79 60 80 /* relocate the code */ -
EcnlProtoTool/trunk/tcc-0.9.27/tests/tcctest.c
r321 r331 2 2 * TCC auto test program 3 3 */ 4 #include " ../config.h"4 #include "config.h" 5 5 6 6 #if GCC_MAJOR >= 3 … … 15 15 #define CORRECT_CR_HANDLING 16 16 17 #endif 18 19 #if defined(_WIN32) 20 #define LONG_LONG_FORMAT "%lld" 21 #define ULONG_LONG_FORMAT "%llu" 22 #else 23 #define LONG_LONG_FORMAT "%Ld" 24 #define ULONG_LONG_FORMAT "%Lu" 25 #endif 26 27 // MinGW has 80-bit rather than 64-bit long double which isn't compatible with TCC or MSVC 28 #if defined(_WIN32) && defined(__GNUC__) 29 #define LONG_DOUBLE double 30 #define LONG_DOUBLE_LITERAL(x) x 31 #else 32 #define LONG_DOUBLE long double 33 #define LONG_DOUBLE_LITERAL(x) x ## L 17 34 #endif 18 35 … … 28 45 #define TCCLIB_INC1 <tcclib 29 46 #define TCCLIB_INC2 h> 30 #define TCCLIB_INC3 "tcclib "47 #define TCCLIB_INC3 "tcclib.h" 31 48 32 49 #include TCCLIB_INC … … 36 53 #include TCCLIB_INC1.h> 37 54 38 /* gcc 3.2 does not accept that (bug ?) */ 39 //#include TCCLIB_INC3 ".h" 55 #include TCCLIB_INC3 40 56 41 57 #include <tcclib.h> … … 43 59 #include "tcclib.h" 44 60 61 #include "tcctest.h" 62 63 /* Test two more ways to include a file named like a pp-number */ 64 #define INC(name) <tests/name.h> 65 #define funnyname 42test.h 66 #define incdir tests/ 67 #define incname < incdir funnyname > 68 #define __stringify(x) #x 69 #define stringify(x) __stringify(x) 70 #include INC(42test) 71 #include incname 72 #include stringify(funnyname) 73 74 void intdiv_test(); 45 75 void string_test(); 46 76 void expr_test(); … … 59 89 void expr_ptr_test(); 60 90 void bool_test(); 91 void optimize_out(); 61 92 void expr2_test(); 62 93 void constant_expr_test(); … … 91 122 void callsave_test(void); 92 123 void builtin_frame_address_test(void); 124 void attrib_test(void); 93 125 94 126 int fib(int n); … … 96 128 void forward_ref(void); 97 129 int isid(int c); 130 131 /* Line joining happens before tokenization, so the following 132 must be parsed as ellipsis. */ 133 void funny_line_continuation (int, ..\ 134 . ); 135 136 char via_volatile (char); 98 137 99 138 #define A 2 … … 138 177 #endif 139 178 179 #ifdef __TINYC__ 180 /* We try to handle this syntax. Make at least sure it doesn't segfault. */ 181 char invalid_function_def()[] {} 182 #endif 183 140 184 #define __INT64_C(c) c ## LL 141 185 #define INT64_MIN (-__INT64_C(9223372036854775807)-1) … … 150 194 #define wq_spin_lock spin_lock 151 195 #define TEST2() wq_spin_lock(a) 196 197 #define UINT_MAX ((unsigned) -1) 198 199 void intdiv_test(void) 200 { 201 printf("18/21=%u\n", 18/21); 202 printf("18%%21=%u\n", 18%21); 203 printf("41/21=%u\n", 41/21); 204 printf("41%%21=%u\n", 41%21); 205 printf("42/21=%u\n", 42/21); 206 printf("42%%21=%u\n", 42%21); 207 printf("43/21=%u\n", 43/21); 208 printf("43%%21=%u\n", 43%21); 209 printf("126/21=%u\n", 126/21); 210 printf("126%%21=%u\n", 126%21); 211 printf("131/21=%u\n", 131/21); 212 printf("131%%21=%u\n", 131%21); 213 printf("(UINT_MAX/2+3)/2=%u\n", (UINT_MAX/2+3)/2); 214 printf("(UINT_MAX/2+3)%%2=%u\n", (UINT_MAX/2+3)%2); 215 216 printf("18/-21=%u\n", 18/-21); 217 printf("18%%-21=%u\n", 18%-21); 218 printf("41/-21=%u\n", 41/-21); 219 printf("41%%-21=%u\n", 41%-21); 220 printf("42/-21=%u\n", 42/-21); 221 printf("42%%-21=%u\n", 42%-21); 222 printf("43/-21=%u\n", 43/-21); 223 printf("43%%-21=%u\n", 43%-21); 224 printf("126/-21=%u\n", 126/-21); 225 printf("126%%-21=%u\n", 126%-21); 226 printf("131/-21=%u\n", 131/-21); 227 printf("131%%-21=%u\n", 131%-21); 228 printf("(UINT_MAX/2+3)/-2=%u\n", (UINT_MAX/2+3)/-2); 229 printf("(UINT_MAX/2+3)%%-2=%u\n", (UINT_MAX/2+3)%-2); 230 231 printf("-18/21=%u\n", -18/21); 232 printf("-18%%21=%u\n", -18%21); 233 printf("-41/21=%u\n", -41/21); 234 printf("-41%%21=%u\n", -41%21); 235 printf("-42/21=%u\n", -42/21); 236 printf("-42%%21=%u\n", -42%21); 237 printf("-43/21=%u\n", -43/21); 238 printf("-43%%21=%u\n", -43%21); 239 printf("-126/21=%u\n", -126/21); 240 printf("-126%%21=%u\n", -126%21); 241 printf("-131/21=%u\n", -131/21); 242 printf("-131%%21=%u\n", -131%21); 243 printf("-(UINT_MAX/2+3)/2=%u\n", (0-(UINT_MAX/2+3))/2); 244 printf("-(UINT_MAX/2+3)%%2=%u\n", (0-(UINT_MAX/2+3))%2); 245 246 printf("-18/-21=%u\n", -18/-21); 247 printf("-18%%-21=%u\n", -18%-21); 248 printf("-41/-21=%u\n", -41/-21); 249 printf("-41%%-21=%u\n", -41%-21); 250 printf("-42/-21=%u\n", -42/-21); 251 printf("-42%%-21=%u\n", -42%-21); 252 printf("-43/-21=%u\n", -43/-21); 253 printf("-43%%-21=%u\n", -43%-21); 254 printf("-126/-21=%u\n", -126/-21); 255 printf("-126%%-21=%u\n", -126%-21); 256 printf("-131/-21=%u\n", -131/-21); 257 printf("-131%%-21=%u\n", -131%-21); 258 printf("-(UINT_MAX/2+3)/-2=%u\n", (0-(UINT_MAX/2+3))/-2); 259 printf("-(UINT_MAX/2+3)%%-2=%u\n", (0-(UINT_MAX/2+3))%-2); 260 } 152 261 153 262 void macro_test(void) … … 236 345 printf("__LINE__=%d __FILE__=%s\n", 237 346 __LINE__, __FILE__); 347 #if 0 238 348 #line 200 239 349 printf("__LINE__=%d __FILE__=%s\n", … … 243 353 __LINE__, __FILE__); 244 354 #line 227 "tcctest.c" 355 #endif 245 356 246 357 /* not strictly preprocessor, but we test it there */ … … 257 368 258 369 /* complicated macros in glibc */ 259 printf("INT64_MIN= %Ld\n", INT64_MIN);370 printf("INT64_MIN=" LONG_LONG_FORMAT "\n", INT64_MIN); 260 371 { 261 372 int a; … … 276 387 MF_t("hi"); 277 388 278 /* test macro substitu ion inside args (should not eat stream) */389 /* test macro substitution inside args (should not eat stream) */ 279 390 printf("qq=%d\n", qq(qq)(2)); 280 391 … … 296 407 TEST2(); 297 408 298 /* And again when the name and parenthes are separated by a409 /* And again when the name and parentheses are separated by a 299 410 comment. */ 300 411 TEST2 /* the comment */ (); 412 413 printf("%s\n", get_basefile_from_header()); 414 printf("%s\n", __BASE_FILE__); 415 printf("%s\n", get_file_from_header()); 416 printf("%s\n", __FILE__); 417 418 /* Check that funnily named include was in fact included */ 419 have_included_42test_h = 1; 420 have_included_42test_h_second = 1; 421 have_included_42test_h_third = 1; 301 422 } 302 423 … … 490 611 }; 491 612 613 struct S_enum { 614 enum {E6 = 42, E7, E8} e:8; 615 }; 616 617 enum ELong { 618 /* This is either 0 on L32 machines, or a large number 619 on L64 machines. We should be able to store this. */ 620 EL_large = ((unsigned long)0xf000 << 31) << 1, 621 }; 622 623 enum { BIASU = -1U<<31 }; 624 enum { BIASS = -1 << 31 }; 625 626 static int getint(int i) 627 { 628 if (i) 629 return 0; 630 else 631 return (int)(-1U << 31); 632 } 633 492 634 void enum_test() 493 635 { 494 636 enum test b1; 637 /* The following should give no warning */ 638 unsigned *p = &b1; 639 struct S_enum s = {E7}; 640 printf("enum: %d\n", s.e); 495 641 printf("enum:\n%d %d %d %d %d %d\n", 496 642 E0, E1, E2, E3, E4, E5); 497 643 b1 = 1; 498 644 printf("b1=%d\n", b1); 645 printf("enum large: %ld\n", EL_large); 646 647 if (getint(0) == BIASU) 648 printf("enum unsigned: ok\n"); 649 else 650 printf("enum unsigned: wrong\n"); 651 if (getint(0) == BIASS) 652 printf("enum unsigned: ok\n"); 653 else 654 printf("enum unsigned: wrong\n"); 499 655 } 500 656 … … 552 708 553 709 struct struct1 st1, st2; 710 711 struct empty_mem { 712 /* nothing */ ; 713 int x; 714 }; 554 715 555 716 int main(int argc, char **argv) … … 571 732 expr_ptr_test(); 572 733 bool_test(); 734 optimize_out(); 573 735 expr2_test(); 574 736 constant_expr_test(); … … 605 767 callsave_test(); 606 768 builtin_frame_address_test(); 769 intdiv_test(); 770 if (via_volatile (42) != 42) 771 printf ("via_volatile broken\n"); 772 attrib_test(); 607 773 return 0; 608 774 } … … 816 982 printf("%d\n", sp[j].i); 817 983 } 984 #ifdef __LP64__ 985 i = 1; 986 p = (int*)0x100000000UL + i; 987 i = ((long)p) >> 32; 988 printf("largeptr: %p %d\n", p, i); 989 #endif 818 990 } 819 991 … … 862 1034 }; 863 1035 1036 struct __attribute__((aligned(16))) aligntest5 1037 { 1038 int i; 1039 }; 1040 struct aligntest6 1041 { 1042 int i; 1043 } __attribute__((aligned(16))); 1044 struct aligntest7 1045 { 1046 int i; 1047 }; 1048 struct aligntest5 altest5[2]; 1049 struct aligntest6 altest6[2]; 1050 int pad1; 1051 /* altest7 is correctly aligned to 16 bytes also with TCC, 1052 but __alignof__ returns the wrong result (4) because we 1053 can't store the alignment yet when specified on symbols 1054 directly (it's stored in the type so we'd need to make 1055 a copy of it). -- FIXED */ 1056 struct aligntest7 altest7[2] __attribute__((aligned(16))); 1057 1058 struct aligntest8 1059 { 1060 int i; 1061 } __attribute__((aligned(4096))); 1062 1063 struct Large { 1064 unsigned long flags; 1065 union { 1066 void *u1; 1067 int *u2; 1068 }; 1069 1070 struct { 1071 union { 1072 unsigned long index; 1073 void *freelist; 1074 }; 1075 union { 1076 unsigned long counters; 1077 struct { 1078 int bla; 1079 }; 1080 }; 1081 }; 1082 1083 union { 1084 struct { 1085 long u3; 1086 long u4; 1087 }; 1088 void *u5; 1089 struct { 1090 unsigned long compound_head; 1091 unsigned int compound_dtor; 1092 unsigned int compound_order; 1093 }; 1094 }; 1095 } __attribute__((aligned(2 * sizeof(long)))); 1096 1097 typedef unsigned long long __attribute__((aligned(4))) unaligned_u64; 1098 1099 struct aligntest9 { 1100 unsigned int buf_nr; 1101 unaligned_u64 start_lba; 1102 }; 1103 1104 struct aligntest10 { 1105 unsigned int buf_nr; 1106 unsigned long long start_lba; 1107 }; 1108 864 1109 void struct_test() 865 1110 { 866 1111 struct1 *s; 867 1112 union union2 u; 1113 struct Large ls; 868 1114 869 1115 printf("struct:\n"); … … 873 1119 sizeof(union union1), 874 1120 sizeof(union union2)); 1121 printf("offsets: %d\n", (int)((char*)&st1.u.v1 - (char*)&st1)); 875 1122 st1.f1 = 1; 876 1123 st1.f2 = 2; … … 901 1148 printf("aligntest4 sizeof=%d alignof=%d\n", 902 1149 sizeof(struct aligntest4), __alignof__(struct aligntest4)); 1150 printf("aligntest5 sizeof=%d alignof=%d\n", 1151 sizeof(struct aligntest5), __alignof__(struct aligntest5)); 1152 printf("aligntest6 sizeof=%d alignof=%d\n", 1153 sizeof(struct aligntest6), __alignof__(struct aligntest6)); 1154 printf("aligntest7 sizeof=%d alignof=%d\n", 1155 sizeof(struct aligntest7), __alignof__(struct aligntest7)); 1156 printf("aligntest8 sizeof=%d alignof=%d\n", 1157 sizeof(struct aligntest8), __alignof__(struct aligntest8)); 1158 printf("aligntest9 sizeof=%d alignof=%d\n", 1159 sizeof(struct aligntest9), __alignof__(struct aligntest9)); 1160 printf("aligntest10 sizeof=%d alignof=%d\n", 1161 sizeof(struct aligntest10), __alignof__(struct aligntest10)); 1162 printf("altest5 sizeof=%d alignof=%d\n", 1163 sizeof(altest5), __alignof__(altest5)); 1164 printf("altest6 sizeof=%d alignof=%d\n", 1165 sizeof(altest6), __alignof__(altest6)); 1166 printf("altest7 sizeof=%d alignof=%d\n", 1167 sizeof(altest7), __alignof__(altest7)); 903 1168 904 1169 /* empty structures (GCC extension) */ 905 1170 printf("sizeof(struct empty) = %d\n", sizeof(struct empty)); 906 1171 printf("alignof(struct empty) = %d\n", __alignof__(struct empty)); 1172 1173 printf("Large: sizeof=%d\n", sizeof(ls)); 1174 memset(&ls, 0, sizeof(ls)); 1175 ls.compound_head = 42; 1176 printf("Large: offsetof(compound_head)=%d\n", (int)((char*)&ls.compound_head - (char*)&ls)); 907 1177 } 908 1178 … … 954 1224 } 955 1225 1226 static unsigned int calc_vm_flags(unsigned int prot) 1227 { 1228 unsigned int prot_bits; 1229 /* This used to segfault in some revisions: */ 1230 prot_bits = ((0x1==0x00000001)?(prot&0x1):(prot&0x1)?0x00000001:0); 1231 return prot_bits; 1232 } 1233 956 1234 void bool_test() 957 1235 { … … 1026 1304 printf("error %d\n", i); 1027 1305 } 1306 printf ("bits = 0x%x\n", calc_vm_flags (0x1)); 1307 } 1308 1309 extern int undefined_function(void); 1310 extern int defined_function(void); 1311 1312 static inline void refer_to_undefined(void) 1313 { 1314 undefined_function(); 1315 } 1316 1317 void optimize_out(void) 1318 { 1319 int i = 0 ? undefined_function() : defined_function(); 1320 printf ("oo:%d\n", i); 1321 int j = 1 ? defined_function() : undefined_function(); 1322 printf ("oo:%d\n", j); 1323 if (0) 1324 printf("oo:%d\n", undefined_function()); 1325 else 1326 printf("oo:%d\n", defined_function()); 1327 if (1) 1328 printf("oo:%d\n", defined_function()); 1329 else 1330 printf("oo:%d\n", undefined_function()); 1331 while (1) { 1332 printf("oow:%d\n", defined_function()); 1333 break; 1334 printf("oow:%d\n", undefined_function()); 1335 } 1336 j = 1; 1337 /* Following is a switch without {} block intentionally. */ 1338 switch (j) 1339 case 1: break; 1340 printf ("oos:%d\n", defined_function()); 1341 /* The following break shouldn't lead to disabled code after 1342 the while. */ 1343 while (1) 1344 break; 1345 printf ("ool1:%d\n", defined_function()); 1346 /* Same for the other types of loops. */ 1347 do 1348 break; 1349 while (1); 1350 printf ("ool2:%d\n", defined_function()); 1351 for (;;) 1352 break; 1353 printf ("ool3:%d\n", defined_function()); 1354 /* Normal {} blocks without controlling statements 1355 shouldn't reactivate code emission */ 1356 while (1) { 1357 { 1358 break; 1359 } 1360 printf ("ool4:%d\n", undefined_function()); 1361 } 1362 j = 1; 1363 while (j) { 1364 if (j == 0) 1365 break; /* this break shouldn't disable code outside the if. */ 1366 printf("ool5:%d\n", defined_function()); 1367 j--; 1368 } 1369 1370 j = 1; 1371 while (j) { 1372 if (1) 1373 j--; 1374 else 1375 breakhere: break; 1376 printf("ool6:%d\n", defined_function()); 1377 goto breakhere; 1378 } 1379 1380 /* Test that constants in logical && are optimized: */ 1381 i = 0 && undefined_function(); 1382 i = defined_function() && 0 && undefined_function(); 1383 if (0 && undefined_function()) 1384 undefined_function(); 1385 if (defined_function() && 0) 1386 undefined_function(); 1387 if (0 && 0) 1388 undefined_function(); 1389 if (defined_function() && 0 && undefined_function()) 1390 undefined_function(); 1391 /* The same for || : */ 1392 i = 1 || undefined_function(); 1393 i = defined_function() || 1 || undefined_function(); 1394 if (1 || undefined_function()) 1395 ; 1396 else 1397 undefined_function(); 1398 if (defined_function() || 1) 1399 ; 1400 else 1401 undefined_function(); 1402 if (1 || 1) 1403 ; 1404 else 1405 undefined_function(); 1406 if (defined_function() || 1 || undefined_function()) 1407 ; 1408 else 1409 undefined_function(); 1410 1411 if (defined_function() && 0) 1412 refer_to_undefined(); 1413 1414 if (0) { 1415 (void)sizeof( ({ 1416 do { } while (0); 1417 0; 1418 }) ); 1419 undefined_function(); 1420 } 1421 1422 /* Leave the "if(1)return; printf()" in this order and last in the function */ 1423 if (1) 1424 return; 1425 printf ("oor:%d\n", undefined_function()); 1426 } 1427 1428 int defined_function(void) 1429 { 1430 static int i = 40; 1431 return i++; 1028 1432 } 1029 1433 … … 1340 1744 }; 1341 1745 1746 typedef int arrtype1[]; 1747 arrtype1 sinit19 = {1}; 1748 arrtype1 sinit20 = {2,3}; 1749 typedef int arrtype2[3]; 1750 arrtype2 sinit21 = {4}; 1751 arrtype2 sinit22 = {5,6,7}; 1752 1753 /* Address comparisons of non-weak symbols with zero can be const-folded */ 1754 int sinit23[2] = { "astring" ? sizeof("astring") : -1, 1755 &sinit23 ? 42 : -1 }; 1756 1757 extern int external_inited = 42; 1758 1342 1759 void init_test(void) 1343 1760 { … … 1354 1771 struct linit16 { int a1, a2, a3, a4; } linit16 = { 1, .a3 = 2 }; 1355 1772 int linit17 = sizeof(linit17); 1773 int zero = 0; 1774 /* Addresses on non-weak symbols are non-zero, but not the access itself */ 1775 int linit18[2] = {&zero ? 1 : -1, zero ? -1 : 1 }; 1356 1776 1357 1777 printf("init_test:\n"); … … 1440 1860 printf("cix2: %d %d\n", cix21.b[2], cix22.b[5]); 1441 1861 printf("sizeof cix20 %d, cix21 %d, sizeof cix22 %d\n", sizeof cix20, sizeof cix21, sizeof cix22); 1442 } 1443 1862 1863 printf("arrtype1: %d %d %d\n", sinit19[0], sinit20[0], sinit20[1]); 1864 printf("arrtype2: %d %d\n", sizeof(sinit19), sizeof(sinit20)); 1865 printf("arrtype3: %d %d %d\n", sinit21[0], sinit21[1], sinit21[2]); 1866 printf("arrtype4: %d %d %d\n", sinit22[0], sinit22[1], sinit22[2]); 1867 printf("arrtype5: %d %d\n", sizeof(sinit21), sizeof(sinit22)); 1868 printf("arrtype6: %d\n", sizeof(arrtype2)); 1869 1870 printf("sinit23= %d %d\n", sinit23[0], sinit23[1]); 1871 printf("linit18= %d %d\n", linit18[0], linit18[1]); 1872 } 1873 1874 void switch_uc(unsigned char uc) 1875 { 1876 switch (uc) { 1877 case 0xfb ... 0xfe: 1878 printf("ucsw:1\n"); 1879 break; 1880 case 0xff: 1881 printf("ucsw:2\n"); 1882 break; 1883 case 0 ... 5: 1884 printf("ucsw:3\n"); 1885 break; 1886 default: 1887 printf("ucsw: broken!\n"); 1888 } 1889 } 1890 1891 void switch_sc(signed char sc) 1892 { 1893 switch (sc) { 1894 case -5 ... -2: 1895 printf("scsw:1\n"); 1896 break; 1897 case -1: 1898 printf("scsw:2\n"); 1899 break; 1900 case 0 ... 5: 1901 printf("scsw:3\n"); 1902 break; 1903 default: 1904 printf("scsw: broken!\n"); 1905 } 1906 } 1444 1907 1445 1908 void switch_test() 1446 1909 { 1447 1910 int i; 1911 unsigned long long ull; 1912 long long ll; 1448 1913 1449 1914 for(i=0;i<15;i++) { … … 1462 1927 printf("b"); 1463 1928 break; 1929 case 0xc33c6b9fU: 1930 case 0x7c9eeeb9U: 1931 break; 1464 1932 } 1465 1933 } 1466 1934 printf("\n"); 1935 1936 for (i = 1; i <= 5; i++) { 1937 ull = (unsigned long long)i << 61; 1938 switch (ull) { 1939 case 1ULL << 61: 1940 printf("ullsw:1\n"); 1941 break; 1942 case 2ULL << 61: 1943 printf("ullsw:2\n"); 1944 break; 1945 case 3ULL << 61: 1946 printf("ullsw:3\n"); 1947 break; 1948 case 4ULL << 61: 1949 printf("ullsw:4\n"); 1950 break; 1951 case 5ULL << 61: 1952 printf("ullsw:5\n"); 1953 break; 1954 default: 1955 printf("ullsw: broken!\n"); 1956 } 1957 } 1958 1959 for (i = 1; i <= 5; i++) { 1960 ll = (long long)i << 61; 1961 switch (ll) { 1962 case 1LL << 61: 1963 printf("llsw:1\n"); 1964 break; 1965 case 2LL << 61: 1966 printf("llsw:2\n"); 1967 break; 1968 case 3LL << 61: 1969 printf("llsw:3\n"); 1970 break; 1971 case 4LL << 61: 1972 printf("llsw:4\n"); 1973 break; 1974 case 5LL << 61: 1975 printf("llsw:5\n"); 1976 break; 1977 default: 1978 printf("llsw: broken!\n"); 1979 } 1980 } 1981 1982 for (i = -5; i <= 5; i++) { 1983 switch_uc((unsigned char)i); 1984 } 1985 1986 for (i = -5; i <= 5; i++) { 1987 switch_sc ((signed char)i); 1988 } 1467 1989 } 1468 1990 … … 1525 2047 printf("st1.f2 != -1\n"); 1526 2048 1527 /* bit sizes below must be bigger than 32 since GCC doesn't allow1528 long-long bitfields whose size is not bigger than int */1529 2049 struct sbf2 { 1530 2050 long long f1 : 45; … … 1539 2059 st2.f2++; 1540 2060 printf("%lld %lld %lld\n", st2.f1, st2.f2, st2.f3); 2061 2062 #if 0 2063 Disabled for now until further clarification re GCC compatibility 2064 struct sbf3 { 2065 int f1 : 7; 2066 int f2 : 1; 2067 char f3; 2068 int f4 : 8; 2069 int f5 : 1; 2070 int f6 : 16; 2071 } st3; 2072 printf("sizeof(st3) = %d\n", sizeof(st3)); 2073 #endif 2074 2075 struct sbf4 { 2076 int x : 31; 2077 char y : 2; 2078 } st4; 2079 st4.y = 1; 2080 printf("st4.y == %d\n", st4.y); 2081 struct sbf5 { 2082 int a; 2083 char b; 2084 int x : 12, y : 4, : 0, : 4, z : 3; 2085 char c; 2086 } st5 = { 1, 2, 3, 4, -3, 6 }; 2087 printf("st5 = %d %d %d %d %d %d\n", st5.a, st5.b, st5.x, st5.y, st5.z, st5.c); 2088 struct sbf6 { 2089 short x : 12; 2090 unsigned char y : 2; 2091 } st6; 2092 st6.y = 1; 2093 printf("st6.y == %d\n", st6.y); 1541 2094 } 1542 2095 … … 1550 2103 /* declare strto* functions as they are C99 */ 1551 2104 double strtod(const char *nptr, char **endptr); 2105 2106 #if defined(_WIN32) 2107 float strtof(const char *nptr, char **endptr) {return (float)strtod(nptr, endptr);} 2108 LONG_DOUBLE strtold(const char *nptr, char **endptr) {return (LONG_DOUBLE)strtod(nptr, endptr);} 2109 #else 1552 2110 float strtof(const char *nptr, char **endptr); 1553 long double strtold(const char *nptr, char **endptr); 1554 1555 #define FTEST(prefix, type, fmt)\ 2111 LONG_DOUBLE strtold(const char *nptr, char **endptr); 2112 #endif 2113 2114 #define FTEST(prefix, typename, type, fmt)\ 1556 2115 void prefix ## cmp(type a, type b)\ 1557 2116 {\ … … 1581 2140 float fa;\ 1582 2141 double da;\ 1583 long doublela;\2142 LONG_DOUBLE la;\ 1584 2143 int ia;\ 2144 long long llia;\ 1585 2145 unsigned int ua;\ 2146 unsigned long long llua;\ 1586 2147 type b;\ 1587 2148 fa = a;\ … … 1590 2151 printf("ftof: %f %f %Lf\n", fa, da, la);\ 1591 2152 ia = (int)a;\ 2153 llia = (long long)a;\ 2154 a = (a >= 0) ? a : -a;\ 1592 2155 ua = (unsigned int)a;\ 1593 printf("ftoi: %d %u\n", ia, ua);\ 2156 llua = (unsigned long long)a;\ 2157 printf("ftoi: %d %u %lld %llu\n", ia, ua, llia, llua);\ 1594 2158 ia = -1234;\ 1595 2159 ua = 0x81234500;\ 2160 llia = -0x123456789012345LL;\ 2161 llua = 0xf123456789012345LLU;\ 1596 2162 b = ia;\ 1597 2163 printf("itof: " fmt "\n", b);\ 1598 2164 b = ua;\ 1599 2165 printf("utof: " fmt "\n", b);\ 2166 b = llia;\ 2167 printf("lltof: " fmt "\n", b);\ 2168 b = llua;\ 2169 printf("ulltof: " fmt "\n", b);\ 1600 2170 }\ 1601 2171 \ 1602 2172 float prefix ## retf(type a) { return a; }\ 1603 2173 double prefix ## retd(type a) { return a; }\ 1604 long doubleprefix ## retld(type a) { return a; }\2174 LONG_DOUBLE prefix ## retld(type a) { return a; }\ 1605 2175 \ 1606 2176 void prefix ## call(void)\ … … 1612 2182 }\ 1613 2183 \ 2184 void prefix ## signed_zeros(void) \ 2185 {\ 2186 type x = 0.0, y = -0.0, n, p;\ 2187 if (x == y)\ 2188 printf ("Test 1.0 / x != 1.0 / y returns %d (should be 1).\n",\ 2189 1.0 / x != 1.0 / y);\ 2190 else\ 2191 printf ("x != y; this is wrong!\n");\ 2192 \ 2193 n = -x;\ 2194 if (x == n)\ 2195 printf ("Test 1.0 / x != 1.0 / -x returns %d (should be 1).\n",\ 2196 1.0 / x != 1.0 / n);\ 2197 else\ 2198 printf ("x != -x; this is wrong!\n");\ 2199 \ 2200 p = +y;\ 2201 if (x == p)\ 2202 printf ("Test 1.0 / x != 1.0 / +y returns %d (should be 1).\n",\ 2203 1.0 / x != 1.0 / p);\ 2204 else\ 2205 printf ("x != +y; this is wrong!\n");\ 2206 p = -y;\ 2207 if (x == p)\ 2208 printf ("Test 1.0 / x != 1.0 / -y returns %d (should be 0).\n",\ 2209 1.0 / x != 1.0 / p);\ 2210 else\ 2211 printf ("x != -y; this is wrong!\n");\ 2212 }\ 1614 2213 void prefix ## test(void)\ 1615 2214 {\ 1616 printf("testing '%s'\n", #type );\2215 printf("testing '%s'\n", #typename);\ 1617 2216 prefix ## cmp(1, 2.5);\ 1618 2217 prefix ## cmp(2, 1.5);\ … … 1621 2220 prefix ## fcast(-2334.6);\ 1622 2221 prefix ## call();\ 1623 } 1624 1625 FTEST(f, float, "%f") 1626 FTEST(d, double, "%f") 1627 FTEST(ld, long double, "%Lf") 2222 prefix ## signed_zeros();\ 2223 } 2224 2225 FTEST(f, float, float, "%f") 2226 FTEST(d, double, double, "%f") 2227 FTEST(ld, long double, LONG_DOUBLE, "%Lf") 1628 2228 1629 2229 double ftab1[3] = { 1.2, 3.4, -5.6 }; … … 1632 2232 void float_test(void) 1633 2233 { 2234 #if !defined(__arm__) || defined(__ARM_PCS_VFP) 1634 2235 float fa, fb; 1635 2236 double da, db; … … 1640 2241 printf("sizeof(float) = %d\n", sizeof(float)); 1641 2242 printf("sizeof(double) = %d\n", sizeof(double)); 1642 printf("sizeof(long double) = %d\n", sizeof( long double));2243 printf("sizeof(long double) = %d\n", sizeof(LONG_DOUBLE)); 1643 2244 ftest(); 1644 2245 dtest(); … … 1657 2258 db = b; 1658 2259 printf("db = %f\n", db); 2260 #endif 1659 2261 } 1660 2262 … … 1675 2277 void (*func)(int); 1676 2278 } st1; 2279 long diff; 1677 2280 1678 2281 printf("funcptr:\n"); … … 1690 2293 printf("sizeof3 = %d\n", sizeof(&funcptr_test)); 1691 2294 printf("sizeof4 = %d\n", sizeof &funcptr_test); 2295 a = 0; 2296 func = num + a; 2297 diff = func - num; 2298 func(42); 2299 (func + diff)(42); 2300 (num + a)(43); 1692 2301 } 1693 2302 … … 1699 2308 ub = b; 1700 2309 /* arith */ 1701 printf("arith: %Ld %Ld %Ld\n",2310 printf("arith: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", 1702 2311 a + b, 1703 2312 a - b, … … 1705 2314 1706 2315 if (b != 0) { 1707 printf("arith1: %Ld %Ld\n",2316 printf("arith1: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", 1708 2317 a / b, 1709 2318 a % b); … … 1711 2320 1712 2321 /* binary */ 1713 printf("bin: %Ld %Ld %Ld\n",2322 printf("bin: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", 1714 2323 a & b, 1715 2324 a | b, … … 1736 2345 a++; 1737 2346 b++; 1738 printf("arith2: %Ld %Ld\n", a, b);1739 printf("arith2: %Ld %Ld\n", a++, b++);1740 printf("arith2: %Ld %Ld\n", --a, --b);1741 printf("arith2: %Ld %Ld\n", a, b);2347 printf("arith2: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", a, b); 2348 printf("arith2: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", a++, b++); 2349 printf("arith2: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", --a, --b); 2350 printf("arith2: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", a, b); 1742 2351 b = ub = 0; 1743 2352 printf("not: %d %d %d %d\n", !a, !ua, !b, !ub); … … 1746 2355 void llshift(long long a, int b) 1747 2356 { 1748 printf("shift: %Ld %Ld %Ld\n",2357 printf("shift: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", 1749 2358 (unsigned long long)a >> b, 1750 2359 a >> b, 1751 2360 a << b); 1752 printf("shiftc: %Ld %Ld %Ld\n",2361 printf("shiftc: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", 1753 2362 (unsigned long long)a >> 3, 1754 2363 a >> 3, 1755 2364 a << 3); 1756 printf("shiftc: %Ld %Ld %Ld\n",2365 printf("shiftc: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", 1757 2366 (unsigned long long)a >> 35, 1758 2367 a >> 35, … … 1764 2373 float fa; 1765 2374 double da; 1766 long doublelda;2375 LONG_DOUBLE lda; 1767 2376 long long la, lb, lc; 1768 2377 unsigned long long ula, ulb, ulc; … … 1771 2380 la = (la << 20) | 0x12345; 1772 2381 ula = ula << 33; 1773 printf("la= %Ld ula=%Lu\n", la, ula);2382 printf("la=" LONG_LONG_FORMAT " ula=" ULONG_LONG_FORMAT "\n", la, ula); 1774 2383 1775 2384 fa = la; … … 1781 2390 lb = da; 1782 2391 lc = lda; 1783 printf("ftoll: %Ld %Ld %Ld\n", la, lb, lc);2392 printf("ftoll: " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", la, lb, lc); 1784 2393 1785 2394 fa = ula; … … 1791 2400 ulb = da; 1792 2401 ulc = lda; 1793 printf("ftoull: %Lu %Lu %Lu\n", ula, ulb, ulc);2402 printf("ftoull: " ULONG_LONG_FORMAT " " ULONG_LONG_FORMAT " " ULONG_LONG_FORMAT "\n", ula, ulb, ulc); 1794 2403 } 1795 2404 … … 1807 2416 { 1808 2417 return ((long long int)v->item); 2418 } 2419 2420 long long llfunc2(long long x, long long y, int z) 2421 { 2422 return x * y * z; 1809 2423 } 1810 2424 … … 1820 2434 a = ia; 1821 2435 b = ua; 1822 printf( "%Ld %Ld\n", a, b);1823 printf( "%Ld %Ld %Ld%Lx\n",2436 printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT "\n", a, b); 2437 printf(LONG_LONG_FORMAT " " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %Lx\n", 1824 2438 (long long)1, 1825 2439 (long long)-2, … … 1827 2441 0x1234567812345679); 1828 2442 a = llfunc1(-3); 1829 printf( "%Ld\n", a);2443 printf(LONG_LONG_FORMAT "\n", a); 1830 2444 1831 2445 lloptest(1000, 23); … … 1855 2469 lloptest(0x80000000, 0); 1856 2470 1857 /* another long long spill test */1858 2471 { 1859 long long *p, v ;2472 long long *p, v, **pp; 1860 2473 v = 1; 1861 2474 p = &v; 1862 2475 p[0]++; 1863 printf("%lld\n", *p); 2476 printf("another long long spill test : %lld\n", *p); 2477 pp = &p; 2478 2479 v = llfunc2(**pp, **pp, ia); 2480 printf("a long long function (arm-)reg-args test : %lld\n", v); 1864 2481 } 1865 1866 2482 a = 68719476720LL; 1867 2483 b = 4294967295LL; 1868 2484 printf("%d %d %d %d\n", a > b, a < b, a >= b, a <= b); 1869 2485 1870 printf("%Ld\n", 0x123456789LLU); 2486 printf(LONG_LONG_FORMAT "\n", 0x123456789LLU); 2487 2488 /* long long pointer deref in argument passing test */ 2489 a = 0x123; 2490 long long *p = &a; 2491 llshift(*p, 5); 1871 2492 } 1872 2493 1873 2494 void manyarg_test(void) 1874 2495 { 1875 long doubleld = 1234567891234LL;2496 LONG_DOUBLE ld = 1234567891234LL; 1876 2497 printf("manyarg_test:\n"); 1877 2498 printf("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f\n", … … 1879 2500 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0); 1880 2501 printf("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f " 1881 "%Ld %Ld%f %f\n",2502 LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %f %f\n", 1882 2503 1, 2, 3, 4, 5, 6, 7, 8, 1883 2504 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0, … … 1885 2506 42.0, 43.0); 1886 2507 printf("%Lf %d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f " 1887 "%Ld %Ld%f %f\n",2508 LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %f %f\n", 1888 2509 ld, 1, 2, 3, 4, 5, 6, 7, 8, 1889 2510 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0, 1890 2511 1234567891234LL, 987654321986LL, 1891 2512 42.0, 43.0); 1892 /* XXX: known bug of x86-64 */1893 #ifndef __x86_64__1894 2513 printf("%d %d %d %d %d %d %d %d %Lf\n", 1895 2514 1, 2, 3, 4, 5, 6, 7, 8, ld); 1896 2515 printf("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f " 1897 "%Ld %Ld%f %f %Lf\n",2516 LONG_LONG_FORMAT " " LONG_LONG_FORMAT "%f %f %Lf\n", 1898 2517 1, 2, 3, 4, 5, 6, 7, 8, 1899 2518 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0, … … 1901 2520 42.0, 43.0, ld); 1902 2521 printf("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f " 1903 "%Lf %Ld %Ld%f %f %Lf\n",2522 "%Lf " LONG_LONG_FORMAT " " LONG_LONG_FORMAT " %f %f %Lf\n", 1904 2523 1, 2, 3, 4, 5, 6, 7, 8, 1905 2524 0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0, 1906 2525 ld, 1234567891234LL, 987654321986LL, 1907 2526 42.0, 43.0, ld); 1908 #endif1909 2527 } 1910 2528 … … 1916 2534 double d; 1917 2535 long long ll; 1918 long doubleld;2536 LONG_DOUBLE ld; 1919 2537 1920 2538 va_start(aq, fmt); … … 1942 2560 case 'l': 1943 2561 ll = va_arg(ap, long long); 1944 printf( "%Ld", ll);2562 printf(LONG_LONG_FORMAT, ll); 1945 2563 break; 1946 2564 case 'F': 1947 ld = va_arg(ap, long double);2565 ld = va_arg(ap, LONG_DOUBLE); 1948 2566 printf("%Lf", ld); 1949 2567 break; … … 1978 2596 } 1979 2597 2598 void stdarg_for_libc(const char *fmt, ...) 2599 { 2600 va_list args; 2601 va_start(args, fmt); 2602 vprintf(fmt, args); 2603 va_end(args); 2604 } 2605 1980 2606 void stdarg_test(void) 1981 2607 { 1982 long doubleld = 1234567891234LL;2608 LONG_DOUBLE ld = 1234567891234LL; 1983 2609 struct myspace bob; 1984 2610 … … 1986 2612 vprintf1("%f %d %f\n", 1.0, 2, 3.0); 1987 2613 vprintf1("%l %l %d %f\n", 1234567891234LL, 987654321986LL, 3, 1234.0); 1988 vprintf1("%F %F %F\n", 1.2L, 2.3L, 3.4L); 1989 #ifdef __x86_64__ 1990 /* a bug of x86's TCC */ 2614 vprintf1("%F %F %F\n", LONG_DOUBLE_LITERAL(1.2), LONG_DOUBLE_LITERAL(2.3), LONG_DOUBLE_LITERAL(3.4)); 1991 2615 vprintf1("%d %f %l %F %d %f %l %F\n", 1992 1, 1.2, 3L, 4.5L, 6, 7.8, 9L, 0.1L); 1993 #endif 2616 1, 1.2, 3LL, LONG_DOUBLE_LITERAL(4.5), 6, 7.8, 9LL, LONG_DOUBLE_LITERAL(0.1)); 1994 2617 vprintf1("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f\n", 1995 2618 1, 2, 3, 4, 5, 6, 7, 8, … … 2027 2650 bob.profile = 42; 2028 2651 stdarg_for_struct(bob, bob, bob, bob.profile); 2652 stdarg_for_libc("stdarg_for_libc: %s %.2f %d\n", "string", 1.23, 456); 2029 2653 } 2030 2654 … … 2072 2696 int *rel2 = &reltab[2]; 2073 2697 2698 #ifdef _WIN64 2699 void relocation_test(void) {} 2700 #else 2701 void getmyaddress(void) 2702 { 2703 printf("in getmyaddress\n"); 2704 } 2705 2706 #ifdef __LP64__ 2707 long __pa_symbol(void) 2708 { 2709 /* This 64bit constant was handled incorrectly, it was used as addend 2710 (which can hold 64bit just fine) in connection with a symbol, 2711 and TCC generates wrong code for that (displacements are 32bit only). 2712 This effectively is "+ 0x80000000", and if addresses of globals 2713 are below 2GB the result should be a number without high 32 bits set. */ 2714 return ((long)(((unsigned long)(&rel1))) - (0xffffffff80000000UL)); 2715 } 2716 #endif 2717 2718 unsigned long theaddress = (unsigned long)getmyaddress; 2074 2719 void relocation_test(void) 2075 2720 { 2721 void (*fptr)(void) = (void (*)(void))theaddress; 2076 2722 printf("*rel1=%d\n", *rel1); 2077 2723 printf("*rel2=%d\n", *rel2); 2078 } 2724 fptr(); 2725 #ifdef __LP64__ 2726 printf("pa_symbol=0x%lx\n", __pa_symbol() >> 63); 2727 #endif 2728 } 2729 #endif 2079 2730 2080 2731 void old_style_f(a,b,c) … … 2105 2756 void alloca_test() 2106 2757 { 2107 #if defined __i386__ || defined __x86_64__ 2758 #if defined __i386__ || defined __x86_64__ || defined __arm__ 2108 2759 char *p = alloca(16); 2109 2760 strcpy(p,"123456789012345"); … … 2138 2789 tab1_ptr = tab1; 2139 2790 tab2_ptr = tab2; 2140 printf("Test C99 VLA 2 (ptrs sub stract): ");2791 printf("Test C99 VLA 2 (ptrs subtract): "); 2141 2792 printf("%s\n", (tab2 - tab1 == (tab2_ptr - tab1_ptr) / (sizeof(int) * 2)) ? "PASSED" : "FAILED"); 2142 2793 printf("Test C99 VLA 3 (ptr add): "); … … 2174 2825 } 2175 2826 2827 #ifndef __TINYC__ 2176 2828 typedef __SIZE_TYPE__ uintptr_t; 2829 #endif 2177 2830 2178 2831 void sizeof_test(void) … … 2218 2871 printf("__alignof__(unsigned char) = %d\n", __alignof__(unsigned char)); 2219 2872 printf("__alignof__(func) = %d\n", __alignof__ sizeof_test()); 2873 2874 /* sizes of VLAs need to be evaluated even inside sizeof: */ 2875 a = 2; 2876 printf("sizeof(char[1+2*a]) = %d\n", sizeof(char[1+2*a])); 2877 /* And checking if sizeof compound literal works. Parenthesized: */ 2878 printf("sizeof( (struct {int i; int j;}){4,5} ) = %d\n", 2879 sizeof( (struct {int i; int j;}){4,5} )); 2880 /* And as direct sizeof argument (as unary expression): */ 2881 printf("sizeof (struct {short i; short j;}){4,5} = %d\n", 2882 sizeof (struct {short i; short j;}){4,5} ); 2883 2884 /* sizeof(x && y) should be sizeof(int), even if constant 2885 evaluating is possible. */ 2886 printf("sizeof(t && 0) = %d\n", sizeof(t && 0)); 2887 printf("sizeof(1 && 1) = %d\n", sizeof(1 && 1)); 2888 printf("sizeof(t || 1) = %d\n", sizeof(t || 1)); 2889 printf("sizeof(0 || 0) = %d\n", sizeof(0 || 0)); 2220 2890 } 2221 2891 … … 2232 2902 } 2233 2903 2904 2905 struct hlist_node; 2906 struct hlist_head { 2907 struct hlist_node *first, *last; 2908 }; 2909 2910 void consume_ulong (unsigned long i) 2911 { 2912 i = 0; 2913 } 2914 2234 2915 void statement_expr_test(void) 2235 2916 { 2236 2917 int a, i; 2237 2918 2919 /* Basic stmt expr test */ 2238 2920 a = 0; 2239 2921 for(i=0;i<10;i++) { … … 2247 2929 printf("a=%d\n", a); 2248 2930 2931 /* Test that symbols aren't freed prematurely. 2932 With SYM_DEBUG valgrind will show a read from a freed 2933 symbol, and tcc will show an (invalid) warning on the initialization 2934 of 'ptr' below, if symbols are popped after the stmt expr. */ 2935 void *v = (void*)39; 2936 typeof(({ 2937 (struct hlist_node *)v; 2938 })) x; 2939 typeof (x) 2940 ptr = (struct hlist_node *)v; 2941 2942 /* This part used to segfault when symbols were popped prematurely. 2943 The symbols for the static local would be overwritten with 2944 helper symbols from the pre-processor expansions in between. */ 2945 #define some_attr __attribute__((aligned(1))) 2946 #define tps(str) ({ \ 2947 static const char *t some_attr = str; \ 2948 t; \ 2949 }) 2950 printf ("stmtexpr: %s %s\n", 2951 tps("somerandomlongstring"), 2952 tps("anotherlongstring")); 2953 2954 /* Test that the three decls of 't' don't interact. */ 2955 int t = 40; 2956 int b = ({ int t = 41; t; }); 2957 int c = ({ int t = 42; t; }); 2958 2959 /* Test that aggregate return values work. */ 2960 struct hlist_head h 2961 = ({ 2962 typedef struct hlist_head T; 2963 long pre = 48; 2964 T t = { (void*)43, (void*)44 }; 2965 long post = 49; 2966 t; 2967 }); 2968 printf ("stmtexpr: %d %d %d\n", t, b, c); 2969 printf ("stmtexpr: %ld %ld\n", (long)h.first, (long)h.last); 2970 2971 /* Test that we can give out addresses of local labels. */ 2972 consume_ulong(({ __label__ __here; __here: (unsigned long)&&__here; })); 2249 2973 } 2250 2974 … … 2280 3004 2281 3005 /* inline assembler test */ 2282 #if def __i386__3006 #if defined(__i386__) || defined(__x86_64__) 2283 3007 2284 3008 /* from linux kernel */ 2285 3009 static char * strncat1(char * dest,const char * src,size_t count) 2286 3010 { 2287 intd0, d1, d2, d3;3011 long d0, d1, d2, d3; 2288 3012 __asm__ __volatile__( 2289 3013 "repne\n\t" 2290 3014 "scasb\n\t" 2291 "dec l%1\n\t"2292 "mov l%8,%3\n"2293 "1:\tdec l%3\n\t"3015 "dec %1\n\t" 3016 "mov %8,%3\n" 3017 "1:\tdec %3\n\t" 2294 3018 "js 2f\n\t" 2295 3019 "lodsb\n\t" … … 2297 3021 "testb %%al,%%al\n\t" 2298 3022 "jne 1b\n" 2299 "2:\txor l%2,%2\n\t"3023 "2:\txor %2,%2\n\t" 2300 3024 "stosb" 2301 3025 : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) … … 2307 3031 static char * strncat2(char * dest,const char * src,size_t count) 2308 3032 { 2309 intd0, d1, d2, d3;3033 long d0, d1, d2, d3; 2310 3034 __asm__ __volatile__( 2311 3035 "repne scasb\n\t" /* one-line repne prefix + string op */ 2312 "dec l%1\n\t"2313 "mov l%8,%3\n"2314 "1:\tdec l%3\n\t"3036 "dec %1\n\t" 3037 "mov %8,%3\n" 3038 "1:\tdec %3\n\t" 2315 3039 "js 2f\n\t" 2316 3040 "lodsb\n\t" … … 2318 3042 "testb %%al,%%al\n\t" 2319 3043 "jne 1b\n" 2320 "2:\txor l%2,%2\n\t"3044 "2:\txor %2,%2\n\t" 2321 3045 "stosb" 2322 3046 : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) … … 2328 3052 static inline void * memcpy1(void * to, const void * from, size_t n) 2329 3053 { 2330 intd0, d1, d2;3054 long d0, d1, d2; 2331 3055 __asm__ __volatile__( 2332 3056 "rep ; movsl\n\t" … … 2346 3070 static inline void * memcpy2(void * to, const void * from, size_t n) 2347 3071 { 2348 intd0, d1, d2;3072 long d0, d1, d2; 2349 3073 __asm__ __volatile__( 2350 3074 "rep movsl\n\t" /* one-line rep prefix + string op */ … … 2369 3093 static __inline__ void sigdelset1(unsigned int *set, int _sig) 2370 3094 { 2371 asm("btrl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc" );3095 asm("btrl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc", "flags"); 2372 3096 } 2373 3097 … … 2377 3101 "rorl $16,%0\n\t" /* swap words */ 2378 3102 "xchgb %b0,%h0" /* swap higher bytes */ 2379 :"= q" (x)3103 :"=" "q" (x) 2380 3104 : "0" (x)); 2381 3105 return x; … … 2385 3109 { 2386 3110 unsigned long long res; 3111 #ifdef __x86_64__ 3112 /* Using the A constraint is wrong (it means rdx:rax, which is too large) 3113 but still test the 32bit->64bit mull. */ 3114 unsigned int resh, resl; 3115 __asm__("mull %2" : "=a" (resl), "=d" (resh) : "a" (a), "r" (b)); 3116 res = ((unsigned long long)resh << 32) | resl; 3117 #else 2387 3118 __asm__("mull %2" : "=A" (res) : "a" (a), "r" (b)); 3119 #endif 2388 3120 return res; 2389 3121 } … … 2392 3124 { 2393 3125 unsigned long long res; 3126 #ifdef __x86_64__ 3127 /* Using the A constraint is wrong, and increments are tested 3128 elsewhere. */ 3129 res = a + 1; 3130 #else 2394 3131 __asm__("addl $1, %%eax ; adcl $0, %%edx" : "=A" (res) : "A" (a)); 3132 #endif 2395 3133 return res; 2396 3134 } 2397 3135 3136 struct struct123 { 3137 int a; 3138 int b; 3139 }; 3140 struct struct1231 { 3141 unsigned long addr; 3142 }; 3143 3144 unsigned long mconstraint_test(struct struct1231 *r) 3145 { 3146 unsigned long ret; 3147 unsigned int a[2]; 3148 a[0] = 0; 3149 __asm__ volatile ("lea %2,%0; movl 4(%0),%k0; addl %2,%k0; movl $51,%2; movl $52,4%2; movl $63,%1" 3150 : "=&r" (ret), "=m" (a) 3151 : "m" (*(struct struct123 *)r->addr)); 3152 return ret + a[0]; 3153 } 3154 3155 #ifdef __x86_64__ 3156 int fls64(unsigned long long x) 3157 { 3158 int bitpos = -1; 3159 asm("bsrq %1,%q0" 3160 : "+r" (bitpos) 3161 : "rm" (x)); 3162 return bitpos + 1; 3163 } 3164 #endif 3165 3166 void other_constraints_test(void) 3167 { 3168 unsigned long ret; 3169 int var; 3170 #ifndef _WIN64 3171 __asm__ volatile ("mov %P1,%0" : "=r" (ret) : "p" (&var)); 3172 printf ("oc1: %d\n", ret == (unsigned long)&var); 3173 #endif 3174 } 3175 3176 #ifndef _WIN32 3177 /* Test global asm blocks playing with aliases. */ 3178 void base_func(void) 3179 { 3180 printf ("asmc: base\n"); 3181 } 3182 3183 extern void override_func1 (void); 3184 extern void override_func2 (void); 3185 3186 asm(".weak override_func1\n.set override_func1, base_func"); 3187 asm(".set override_func1, base_func"); 3188 asm(".set override_func2, base_func"); 3189 3190 void override_func2 (void) 3191 { 3192 printf ("asmc: override2\n"); 3193 } 3194 3195 /* This checks a construct used by the linux kernel to encode 3196 references to strings by PC relative references. */ 3197 extern int bug_table[] __attribute__((section("__bug_table"))); 3198 char * get_asm_string (void) 3199 { 3200 extern int some_symbol; 3201 asm volatile (".globl some_symbol\n" 3202 "jmp .+6\n" 3203 "1:\n" 3204 "some_symbol: .long 0\n" 3205 ".pushsection __bug_table, \"a\"\n" 3206 ".globl bug_table\n" 3207 "bug_table:\n" 3208 /* The first entry (1b-2b) is unused in this test, 3209 but we include it to check if cross-section 3210 PC-relative references work. */ 3211 "2:\t.long 1b - 2b, %c0 - 2b\n" 3212 ".popsection\n" : : "i" ("A string")); 3213 char * str = ((char*)bug_table) + bug_table[1]; 3214 return str; 3215 } 3216 3217 /* This checks another constructs with local labels. */ 3218 extern unsigned char alld_stuff[]; 3219 asm(".data\n" 3220 ".byte 41\n" 3221 "alld_stuff:\n" 3222 "661:\n" 3223 ".byte 42\n" 3224 "662:\n" 3225 ".pushsection .data.ignore\n" 3226 ".long 661b - .\n" /* This reference to 661 generates an external sym 3227 which shouldn't somehow overwrite the offset that's 3228 already determined for it. */ 3229 ".popsection\n" 3230 ".byte 662b - 661b\n" /* So that this value is undeniably 1. */); 3231 3232 void asm_local_label_diff (void) 3233 { 3234 printf ("asm_local_label_diff: %d %d\n", alld_stuff[0], alld_stuff[1]); 3235 } 3236 3237 /* This checks that static local variables are available from assembler. */ 3238 void asm_local_statics (void) 3239 { 3240 static int localint = 41; 3241 asm("incl %0" : "+m" (localint)); 3242 printf ("asm_local_statics: %d\n", localint); 3243 } 3244 #endif 3245 3246 static 2398 3247 unsigned int set; 2399 3248 3249 void fancy_copy (unsigned *in, unsigned *out) 3250 { 3251 asm volatile ("" : "=r" (*out) : "0" (*in)); 3252 } 3253 3254 void fancy_copy2 (unsigned *in, unsigned *out) 3255 { 3256 asm volatile ("mov %0,(%1)" : : "r" (*in), "r" (out) : "memory"); 3257 } 3258 3259 #if defined __x86_64__ && !defined _WIN64 3260 void clobber_r12(void) 3261 { 3262 asm volatile("mov $1, %%r12" ::: "r12"); 3263 } 3264 #endif 3265 3266 void test_high_clobbers(void) 3267 { 3268 #if defined __x86_64__ && !defined _WIN64 3269 register long val asm("r12"); 3270 long val2; 3271 /* This tests if asm clobbers correctly save/restore callee saved 3272 registers if they are clobbered and if it's the high 8 x86-64 3273 registers. This is fragile for GCC as the constraints do not 3274 correctly capture the data flow, but good enough for us. */ 3275 asm volatile("mov $0x4542, %%r12" : "=r" (val):: "memory"); 3276 clobber_r12(); 3277 asm volatile("mov %%r12, %0" : "=r" (val2) : "r" (val): "memory"); 3278 printf("asmhc: 0x%x\n", val2); 3279 #endif 3280 } 3281 3282 static long cpu_number; 3283 void trace_console(long len, long len2) 3284 { 3285 #ifdef __x86_64__ 3286 /* This generated invalid code when the emission of the switch 3287 table isn't disabled. The asms are necessary to show the bug, 3288 normal statements don't work (they need to generate some code 3289 even under nocode_wanted, which normal statements don't do, 3290 but asms do). Also at least these number of cases is necessary 3291 to generate enough "random" bytes. They ultimately are enough 3292 to create invalid instruction patterns to which the first 3293 skip-to-decision-table jump jumps. If decision table emission 3294 is disabled all of this is no problem. 3295 3296 It also is necessary that the switches are in a statement expression 3297 (which has the property of not being enterable from outside. no 3298 matter what). */ 3299 if (0 3300 && 3301 ({ 3302 long pscr_ret__; 3303 switch(len) { 3304 case 4: 3305 { 3306 long pfo_ret__; 3307 switch (len2) { 3308 case 8: printf("bla"); pfo_ret__ = 42; break; 3309 } 3310 pscr_ret__ = pfo_ret__; 3311 } 3312 break; 3313 case 8: 3314 { 3315 long pfo_ret__; 3316 switch (len2) { 3317 case 1:asm("movq %1,%0": "=r" (pfo_ret__) : "m" (cpu_number)); break; 3318 case 2:asm("movq %1,%0": "=r" (pfo_ret__) : "m" (cpu_number)); break; 3319 case 4:asm("movq %1,%0": "=r" (pfo_ret__) : "m" (cpu_number)); break; 3320 case 8:asm("movq %1,%0": "=r" (pfo_ret__) : "m" (cpu_number)); break; 3321 default: printf("impossible\n"); 3322 } 3323 pscr_ret__ = pfo_ret__; 3324 }; 3325 break; 3326 } 3327 pscr_ret__; 3328 })) 3329 { 3330 printf("huh?\n"); 3331 } 3332 #endif 3333 } 3334 3335 void test_asm_dead_code(void) 3336 { 3337 long rdi; 3338 /* Try to make sure that xdi contains a zero, and hence will 3339 lead to a segfault if the next asm is evaluated without 3340 arguments being set up. */ 3341 asm volatile ("" : "=D" (rdi) : "0" (0)); 3342 (void)sizeof (({ 3343 int var; 3344 /* This shouldn't trigger a segfault, either the argument 3345 registers need to be set up and the asm emitted despite 3346 this being in an unevaluated context, or both the argument 3347 setup _and_ the asm emission need to be suppressed. The latter 3348 is better. Disabling asm code gen when suppression is on 3349 also fixes the above trace_console bug, but that came earlier 3350 than asm suppression. */ 3351 asm volatile ("movl $0,(%0)" : : "D" (&var) : "memory"); 3352 var; 3353 })); 3354 } 3355 3356 void test_asm_call(void) 3357 { 3358 #if defined __x86_64__ && !defined _WIN64 3359 static char str[] = "PATH"; 3360 char *s; 3361 /* This tests if a reference to an undefined symbol from an asm 3362 block, which isn't otherwise referenced in this file, is correctly 3363 regarded as global symbol, so that it's resolved by other object files 3364 or libraries. We chose getenv here, which isn't used anywhere else 3365 in this file. (If we used e.g. printf, which is used we already 3366 would have a global symbol entry, not triggering the bug which is 3367 tested here). */ 3368 /* two pushes so stack remains aligned */ 3369 asm volatile ("push %%rdi; push %%rdi; mov %0, %%rdi;" 3370 #if 1 && !defined(__TINYC__) && (defined(__PIC__) || defined(__PIE__)) 3371 "call getenv@plt;" 3372 #else 3373 "call getenv;" 3374 #endif 3375 "pop %%rdi; pop %%rdi" 3376 : "=a" (s) : "r" (str)); 3377 printf("asmd: %s\n", s); 3378 #endif 3379 } 3380 3381 #if defined __x86_64__ 3382 # define RX "(%rip)" 3383 #else 3384 # define RX 3385 #endif 3386 3387 void asm_dot_test(void) 3388 { 3389 int x; 3390 for (x = 1;; ++x) { 3391 int r = x; 3392 switch (x) { 3393 case 1: 3394 asm(".text; lea S"RX",%eax; lea ."RX",%ecx; sub %ecx,%eax; S=.; jmp p0"); 3395 case 2: 3396 asm(".text; jmp .+6; .int 123; mov .-4"RX",%eax; jmp p0"); 3397 case 3: 3398 asm(".data; Y=.; .int 999; X=Y; .int 456; X=.-4"); 3399 asm(".text; mov X"RX",%eax; jmp p0"); 3400 case 4: 3401 asm(".data; X=.; .int 789; Y=.; .int 999"); 3402 asm(".text; mov X"RX",%eax; X=Y; jmp p0"); 3403 case 0: 3404 asm(".text; p0=.; mov %%eax,%0;" : "=m"(r)); break; 3405 } 3406 if (r == x) 3407 break; 3408 printf("asm_dot_test %d: %d\n", x, r); 3409 } 3410 } 3411 2400 3412 void asm_test(void) 2401 3413 { 2402 3414 char buf[128]; 2403 unsigned int val; 3415 unsigned int val, val2; 3416 struct struct123 s1; 3417 struct struct1231 s2 = { (unsigned long)&s1 }; 3418 /* Hide the outer base_func, but check later that the inline 3419 asm block gets the outer one. */ 3420 int base_func = 42; 3421 void override_func3 (void); 3422 unsigned long asmret; 3423 #ifdef BOOL_ISOC99 3424 _Bool somebool; 3425 #endif 3426 register int regvar asm("%esi"); 2404 3427 2405 3428 printf("inline asm:\n"); 3429 3430 // parse 0x1E-1 as 3 tokens in asm mode 3431 asm volatile ("mov $0x1E-1,%eax"); 3432 2406 3433 /* test the no operand case */ 2407 3434 asm volatile ("xorl %eax, %eax"); … … 2419 3446 printf("inc64=0x%Lx\n", inc64(0x12345678ffffffff)); 2420 3447 3448 s1.a = 42; 3449 s1.b = 43; 3450 printf("mconstraint: %d", mconstraint_test(&s2)); 3451 printf(" %d %d\n", s1.a, s1.b); 3452 other_constraints_test(); 2421 3453 set = 0xff; 2422 3454 sigdelset1(&set, 2); … … 2427 3459 label2: 2428 3460 __asm__("btsl %1,%0" : "=m"(set) : "Ir"(20) : "cc"); 2429 #ifdef __GNUC__ // works strange with GCC 4.32430 set=0x1080fd;2431 #endif2432 3461 printf("set=0x%x\n", set); 2433 3462 val = 0x01020304; 2434 3463 printf("swab32(0x%08x) = 0x%0x\n", val, swab32(val)); 3464 #ifndef _WIN32 3465 override_func1(); 3466 override_func2(); 3467 /* The base_func ref from the following inline asm should find 3468 the global one, not the local decl from this function. */ 3469 asm volatile(".weak override_func3\n.set override_func3, base_func"); 3470 override_func3(); 3471 printf("asmstr: %s\n", get_asm_string()); 3472 asm_local_label_diff(); 3473 asm_local_statics(); 3474 #endif 3475 /* Check that we can also load structs of appropriate layout 3476 into registers. */ 3477 asm volatile("" : "=r" (asmret) : "0"(s2)); 3478 if (asmret != s2.addr) 3479 printf("asmstr: failed\n"); 3480 #ifdef BOOL_ISOC99 3481 /* Check that the typesize correctly sets the register size to 3482 8 bit. */ 3483 asm volatile("cmp %1,%2; sete %0" : "=a"(somebool) : "r"(1), "r"(2)); 3484 if (!somebool) 3485 printf("asmbool: failed\n"); 3486 #endif 3487 val = 43; 3488 fancy_copy (&val, &val2); 3489 printf ("fancycpy(%d)=%d\n", val, val2); 3490 val = 44; 3491 fancy_copy2 (&val, &val2); 3492 printf ("fancycpy2(%d)=%d\n", val, val2); 3493 asm volatile ("mov $0x4243, %%esi" : "=r" (regvar)); 3494 printf ("regvar=%x\n", regvar); 3495 test_high_clobbers(); 3496 trace_console(8, 8); 3497 test_asm_dead_code(); 3498 test_asm_call(); 3499 asm_dot_test(); 2435 3500 return; 2436 3501 label1: … … 2456 3521 void builtin_test(void) 2457 3522 { 3523 short s; 3524 int i; 3525 long long ll; 2458 3526 #if GCC_MAJOR >= 3 2459 3527 COMPAT_TYPE(int, int); … … 2466 3534 COMPAT_TYPE(int *, const int *); 2467 3535 COMPAT_TYPE(char *, unsigned char *); 3536 COMPAT_TYPE(char *, signed char *); 3537 COMPAT_TYPE(char *, char *); 2468 3538 /* space is needed because tcc preprocessor introduces a space between each token */ 2469 3539 COMPAT_TYPE(char * *, void *); … … 2473 3543 printf("res = %d\n", __builtin_constant_p(&constant_p_var)); 2474 3544 printf("res = %d\n", __builtin_constant_p(constant_p_var)); 3545 printf("res = %d\n", __builtin_constant_p(100000 / constant_p_var)); 3546 s = 1; 3547 ll = 2; 3548 i = __builtin_choose_expr (1 != 0, ll, s); 3549 printf("bce: %d\n", i); 3550 i = __builtin_choose_expr (1 != 1, ll, s); 3551 printf("bce: %d\n", i); 3552 i = sizeof (__builtin_choose_expr (1, ll, s)); 3553 printf("bce: %d\n", i); 3554 i = sizeof (__builtin_choose_expr (0, ll, s)); 3555 printf("bce: %d\n", i); 3556 3557 //printf("bera: %p\n", __builtin_extract_return_addr((void*)43)); 2475 3558 } 2476 3559 … … 2525 3608 printf("weak_asm_v2=%d\n",&weak_asm_v2 != NULL); 2526 3609 printf("weak_asm_v3=%d\n",&weak_asm_v3 != NULL); 3610 printf("some_lib_func=%d\n", &some_lib_func ? some_lib_func() : 0); 2527 3611 } 2528 3612 … … 2678 3762 void callsave_test(void) 2679 3763 { 2680 #if defined __i386__ || defined __x86_64__ 3764 #if defined __i386__ || defined __x86_64__ || defined __arm__ 2681 3765 int i, s; double *d; double t; 2682 3766 s = sizeof (double); … … 2707 3791 { 2708 3792 printf("bfa1: %s\n", (char *)__builtin_frame_address(1) + str_offset); 2709 #if defined(__arm__) && !defined(__GNUC__)2710 3793 bfa2(str_offset); 2711 #endif2712 3794 } 2713 3795 2714 3796 void builtin_frame_address_test(void) 2715 3797 { 3798 /* builtin_frame_address fails on ARM with gcc which make test3 fail */ 3799 #ifndef __arm__ 2716 3800 char str[] = "__builtin_frame_address"; 2717 3801 char *fp0 = __builtin_frame_address(0); … … 2719 3803 printf("str: %s\n", str); 2720 3804 bfa1(str-fp0); 2721 } 3805 #endif 3806 } 3807 3808 char via_volatile (char i) 3809 { 3810 char volatile vi; 3811 vi = i; 3812 return vi; 3813 } 3814 3815 struct __attribute__((__packed__)) Spacked { 3816 char a; 3817 short b; 3818 int c; 3819 }; 3820 struct Spacked spacked; 3821 typedef struct __attribute__((__packed__)) { 3822 char a; 3823 short b; 3824 int c; 3825 } Spacked2; 3826 Spacked2 spacked2; 3827 typedef struct Spacked3_s { 3828 char a; 3829 short b; 3830 int c; 3831 } __attribute__((__packed__)) Spacked3; 3832 Spacked3 spacked3; 3833 struct gate_struct64 { 3834 unsigned short offset_low; 3835 unsigned short segment; 3836 unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1; 3837 unsigned short offset_middle; 3838 unsigned offset_high; 3839 unsigned zero1; 3840 } __attribute__((packed)); 3841 typedef struct gate_struct64 gate_desc; 3842 gate_desc a_gate_desc; 3843 void attrib_test(void) 3844 { 3845 #ifndef _WIN32 3846 printf("attr: %d %d %d %d\n", sizeof(struct Spacked), 3847 sizeof(spacked), sizeof(Spacked2), sizeof(spacked2)); 3848 printf("attr: %d %d\n", sizeof(Spacked3), sizeof(spacked3)); 3849 printf("attr: %d %d\n", sizeof(gate_desc), sizeof(a_gate_desc)); 3850 #endif 3851 } 3852 extern __attribute__((__unused__)) char * __attribute__((__unused__)) * 3853 strange_attrib_placement (void); 3854 3855 void * __attribute__((__unused__)) get_void_ptr (void *a) 3856 { 3857 return a; 3858 } 3859 3860 /* This part checks for a bug in TOK_GET (used for inline expansion), 3861 where the large long long constant left the the high bits set for 3862 the integer constant token. */ 3863 static inline 3864 int __get_order(unsigned long long size) 3865 { 3866 int order; 3867 size -= 0xffff880000000000ULL; // this const left high bits set in the token 3868 { 3869 struct S { int i : 1; } s; // constructed for this '1' 3870 } 3871 order = size; 3872 return order; 3873 } 3874 3875 /* This just forces the above inline function to be actually emitted. */ 3876 int force_get_order(unsigned long s) 3877 { 3878 return __get_order(s); 3879 } -
EcnlProtoTool/trunk/tcc-0.9.27/x86_64-asm.h
r321 r331 6 6 DEF_ASM_OP0(lahf, 0x9f) 7 7 DEF_ASM_OP0(sahf, 0x9e) 8 DEF_ASM_OP0(pushf l, 0x9c)9 DEF_ASM_OP0(popf l, 0x9d)8 DEF_ASM_OP0(pushfq, 0x9c) 9 DEF_ASM_OP0(popfq, 0x9d) 10 10 DEF_ASM_OP0(pushf, 0x9c) 11 11 DEF_ASM_OP0(popf, 0x9d) … … 35 35 DEF_ASM_OP0(wait, 0x9b) 36 36 DEF_ASM_OP0(nop, 0x90) 37 DEF_ASM_OP0(pause, 0xf390) 37 38 DEF_ASM_OP0(xlat, 0xd7) 38 39 39 40 /* strings */ 40 ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL Q))41 ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL Q))42 43 ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL Q))44 ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL Q))45 46 ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL Q))47 ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL Q))48 49 ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL Q))50 ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL Q))51 52 ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL Q))53 ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL Q))54 55 ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL Q))56 ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL Q))41 ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWLX)) 42 ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWLX)) 43 44 ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL)) 45 ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL)) 46 47 ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWLX)) 48 ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWLX)) 49 50 ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWLX)) 51 ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWLX)) 52 53 ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWLX)) 54 ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWLX)) 55 56 ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWLX)) 57 ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWLX)) 57 58 58 59 /* bits */ 59 60 60 ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL Q, OPT_REGW | OPT_EA, OPT_REGW))61 ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL Q, OPT_REGW | OPT_EA, OPT_REGW))62 63 ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL Q, OPT_REGW, OPT_REGW | OPT_EA))64 ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL Q, OPT_IM8, OPT_REGW | OPT_EA))65 66 ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL Q, OPT_REGW, OPT_REGW | OPT_EA))67 ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL Q, OPT_IM8, OPT_REGW | OPT_EA))68 69 ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL Q, OPT_REGW, OPT_REGW | OPT_EA))70 ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL Q, OPT_IM8, OPT_REGW | OPT_EA))71 72 ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL Q, OPT_REGW, OPT_REGW | OPT_EA))73 ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL Q, OPT_IM8, OPT_REGW | OPT_EA))61 ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW)) 62 ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW)) 63 64 ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA)) 65 ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA)) 66 67 ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA)) 68 ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA)) 69 70 ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA)) 71 ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA)) 72 73 ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA)) 74 ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA)) 74 75 75 76 /* prefixes */ … … 88 89 DEF_ASM_OP0(rdmsr, 0x0f32) 89 90 DEF_ASM_OP0(rdpmc, 0x0f33) 91 92 DEF_ASM_OP0(syscall, 0x0f05) 93 DEF_ASM_OP0(sysret, 0x0f07) 94 DEF_ASM_OP0L(sysretq, 0x480f07, 0, 0) 90 95 DEF_ASM_OP0(ud2, 0x0f0b) 91 96 92 97 /* NOTE: we took the same order as gas opcode definition order */ 93 ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWLQ, OPT_ADDR, OPT_EAX)) 94 ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWLQ, OPT_EAX, OPT_ADDR)) 95 ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_EA | OPT_REG)) 96 ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWLQ, OPT_EA | OPT_REG, OPT_REG)) 97 ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWLQ, OPT_IM, OPT_REG)) 98 ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWLQ, OPT_IM, OPT_REG | OPT_EA)) 99 100 ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WLQ, OPT_SEG, OPT_EA | OPT_REG)) 101 ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WLQ, OPT_EA | OPT_REG, OPT_SEG)) 102 103 ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WLQ, OPT_CR, OPT_REG64)) 104 ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WLQ, OPT_DB, OPT_REG64)) 105 ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WLQ, OPT_TR, OPT_REG64)) 106 ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WLQ, OPT_REG64, OPT_CR)) 107 ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WLQ, OPT_REG64, OPT_DB)) 108 ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WLQ, OPT_REG64, OPT_TR)) 109 98 /* Right now we can't express the fact that 0xa1/0xa3 can't use $eax and a 99 32 bit moffset as operands. 100 ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWLX, OPT_ADDR, OPT_EAX)) 101 ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWLX, OPT_EAX, OPT_ADDR)) */ 102 ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) 103 ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) 104 /* The moves are special: the 0xb8 form supports IM64 (the only insn that 105 does) with REG64. It doesn't support IM32 with REG64, it would use 106 the full movabs form (64bit immediate). For IM32->REG64 we prefer 107 the 0xc7 opcode. So disallow all 64bit forms and code the rest by hand. */ 108 ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWLX, OPT_IM, OPT_REG)) 109 ALT(DEF_ASM_OP2(mov, 0xb8, 0, OPC_REG, OPT_IM64, OPT_REG64)) 110 ALT(DEF_ASM_OP2(movq, 0xb8, 0, OPC_REG, OPT_IM64, OPT_REG64)) 111 ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWLX, OPT_IM, OPT_REG | OPT_EA)) 112 113 ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WLX, OPT_SEG, OPT_EA | OPT_REG)) 114 ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WLX, OPT_EA | OPT_REG, OPT_SEG)) 115 116 ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WLX, OPT_CR, OPT_REG64)) 117 ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WLX, OPT_DB, OPT_REG64)) 118 ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WLX, OPT_REG64, OPT_CR)) 119 ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WLX, OPT_REG64, OPT_DB)) 120 121 ALT(DEF_ASM_OP2(movsbw, 0x660fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG16)) 110 122 ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32)) 111 ALT(DEF_ASM_OP2(movsb w, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))123 ALT(DEF_ASM_OP2(movsbq, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REGW)) 112 124 ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32)) 113 ALT(DEF_ASM_OP2(movslq, 0x4863, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG)) 114 ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW)) 125 ALT(DEF_ASM_OP2(movswq, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG)) 126 ALT(DEF_ASM_OP2(movslq, 0x63, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG)) 127 ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WLX, OPT_REG8 | OPT_EA, OPT_REGW)) 115 128 ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32)) 116 117 ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WLQ, OPT_REG64)) 118 ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WLQ, OPT_REG64 | OPT_EA)) 119 ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WLQ, OPT_IM32)) 120 ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WLQ, OPT_SEG)) 121 DEF_ASM_OP1(pushb, 0x6a, 0, OPC_B, OPT_IM8S) 122 123 ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WLQ, OPT_REGW)) 124 ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WLQ, OPT_REGW | OPT_EA)) 125 ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WLQ, OPT_SEG)) 126 127 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WLQ, OPT_REG, OPT_EAX)) 128 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WLQ, OPT_EAX, OPT_REG)) 129 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_EA | OPT_REG)) 130 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWLQ, OPT_EA | OPT_REG, OPT_REG)) 129 ALT(DEF_ASM_OP2(movzwq, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG)) 130 131 ALT(DEF_ASM_OP1(pushq, 0x6a, 0, 0, OPT_IM8S)) 132 ALT(DEF_ASM_OP1(push, 0x6a, 0, 0, OPT_IM8S)) 133 ALT(DEF_ASM_OP1(pushw, 0x666a, 0, 0, OPT_IM8S)) 134 ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WLX, OPT_REG64)) 135 ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WLX, OPT_REG16)) 136 ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WLX, OPT_REG64 | OPT_EA)) 137 ALT(DEF_ASM_OP1(pushw, 0x6668, 0, 0, OPT_IM16)) 138 ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WLX, OPT_IM32)) 139 ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WLX, OPT_SEG)) 140 141 ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WLX, OPT_REG64)) 142 ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WLX, OPT_REG16)) 143 ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA)) 144 ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WLX, OPT_SEG)) 145 146 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WLX, OPT_REGW, OPT_EAX)) 147 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WLX, OPT_EAX, OPT_REGW)) 148 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) 149 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) 131 150 132 151 ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX)) … … 140 159 ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX)) 141 160 142 ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL Q, OPT_EA, OPT_REG))161 ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WLX, OPT_EA, OPT_REG)) 143 162 144 163 ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32)) … … 149 168 150 169 /* arith */ 151 ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */ 152 ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWLQ, OPT_EA | OPT_REG, OPT_REG)) 153 ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWLQ, OPT_IMNO64, OPT_EAX)) 154 ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLQ, OPT_IMNO64, OPT_EA | OPT_REG)) 155 ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLQ, OPT_IM8S, OPT_EA | OPT_REG)) 156 157 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLQ, OPT_EA | OPT_REG, OPT_REG)) 158 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_EA | OPT_REG)) 159 ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWLQ, OPT_IMNO64, OPT_EAX)) 160 ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWLQ, OPT_IMNO64, OPT_EA | OPT_REG)) 161 162 ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WLQ, OPT_REGW)) 163 ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA)) 164 ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WLQ, OPT_REGW)) 165 ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA)) 166 167 ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA)) 168 ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA)) 169 170 ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA)) 171 ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA)) 172 173 ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WLQ, OPT_REG | OPT_EA, OPT_REG)) 174 ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WLQ, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW)) 175 ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WLQ, OPT_IM8S, OPT_REGW)) 176 ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WLQ, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW)) 177 ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WLQ, OPT_IMW, OPT_REGW)) 178 179 ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA)) 180 ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA, OPT_EAX)) 181 ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA)) 182 ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA, OPT_EAX)) 170 ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */ 171 ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) 172 ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWLX, OPT_IM, OPT_EAX)) 173 ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_EA | OPT_REGW)) 174 ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG)) 175 176 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) 177 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) 178 ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWLX, OPT_IM, OPT_EAX)) 179 ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG)) 180 181 ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 182 ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 183 184 ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 185 ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 186 187 ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 188 ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 189 190 ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WLX, OPT_REG | OPT_EA, OPT_REG)) 191 ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW)) 192 ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_REGW)) 193 ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WLX, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW)) 194 ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WLX, OPT_IMW, OPT_REGW)) 195 196 ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 197 ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA, OPT_EAX)) 198 ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA)) 199 ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA, OPT_EAX)) 183 200 184 201 /* shifts */ 185 ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL Q| OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))186 ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL Q| OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))187 ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL Q| OPC_SHIFT, OPT_EA | OPT_REG))188 189 ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL Q, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))190 ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL Q, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))191 ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL Q, OPT_REGW, OPT_EA | OPT_REGW))192 ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL Q, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))193 ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL Q, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))194 ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL Q, OPT_REGW, OPT_EA | OPT_REGW))202 ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG)) 203 ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG)) 204 ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_EA | OPT_REG)) 205 206 ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW)) 207 ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WLX, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW)) 208 ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_EA | OPT_REGW)) 209 ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW)) 210 ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WLX, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW)) 211 ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_EA | OPT_REGW)) 195 212 196 213 ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR)) 197 ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))214 ALT(DEF_ASM_OP1(call, 0xe8, 0, 0, OPT_DISP)) 198 215 ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR)) 199 ALT(DEF_ASM_OP1(jmp, 0xff, 0, OPC_JMP | OPC_WL, OPT_REGW)) 200 ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR)) 201 202 ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA)) 203 ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA)) 216 ALT(DEF_ASM_OP1(jmp, 0xeb, 0, 0, OPT_DISP8)) 217 218 ALT(DEF_ASM_OP1(lcall, 0xff, 3, OPC_MODRM, OPT_EA)) 219 ALT(DEF_ASM_OP1(ljmp, 0xff, 5, OPC_MODRM, OPT_EA)) 220 DEF_ASM_OP1(ljmpw, 0x66ff, 5, OPC_MODRM, OPT_EA) 221 DEF_ASM_OP1(ljmpl, 0xff, 5, OPC_MODRM, OPT_EA) 204 222 205 223 ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8)) 206 224 ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA)) 225 ALT(DEF_ASM_OP1(setob, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA)) 207 226 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8) 208 227 DEF_ASM_OP0(leave, 0xc9) 209 228 DEF_ASM_OP0(ret, 0xc3) 229 DEF_ASM_OP0(retq, 0xc3) 230 ALT(DEF_ASM_OP1(retq, 0xc2, 0, 0, OPT_IM16)) 210 231 ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16)) 211 232 DEF_ASM_OP0(lret, 0xcb) 212 233 ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16)) 213 234 214 ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_ SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))215 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)216 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)217 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)218 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)219 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)220 DEF_ASM_OP1(jecxz, 0x e3, 0, OPC_SHORTJMP, OPT_ADDR)235 ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_TEST, OPT_DISP8)) 236 DEF_ASM_OP1(loopne, 0xe0, 0, 0, OPT_DISP8) 237 DEF_ASM_OP1(loopnz, 0xe0, 0, 0, OPT_DISP8) 238 DEF_ASM_OP1(loope, 0xe1, 0, 0, OPT_DISP8) 239 DEF_ASM_OP1(loopz, 0xe1, 0, 0, OPT_DISP8) 240 DEF_ASM_OP1(loop, 0xe2, 0, 0, OPT_DISP8) 241 DEF_ASM_OP1(jecxz, 0x67e3, 0, 0, OPT_DISP8) 221 242 222 243 /* float */ … … 226 247 ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST)) 227 248 ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0)) 249 ALT(DEF_ASM_OP2(fadd, 0xdcc0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST)) 250 ALT(DEF_ASM_OP2(fmul, 0xdcc8, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST)) 228 251 ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH)) 229 252 ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST)) … … 328 351 DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA ) 329 352 DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA ) 353 /* The *q forms of fxrstor/fxsave use a REX prefix. 354 If the operand would use extended registers we would have to modify 355 it instead of generating a second one. Currently that's no 356 problem with TCC, we don't use extended registers. */ 357 DEF_ASM_OP1(fxsaveq, 0x0fae, 0, OPC_MODRM | OPC_48, OPT_EA ) 358 DEF_ASM_OP1(fxrstorq, 0x0fae, 1, OPC_MODRM | OPC_48, OPT_EA ) 330 359 331 360 /* segments */ 332 361 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA) 333 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)362 ALT(DEF_ASM_OP2(larw, 0x0f02, 0, OPC_MODRM | OPC_WLX, OPT_REG | OPT_EA, OPT_REG)) 334 363 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA) 364 DEF_ASM_OP1(lgdtq, 0x0f01, 2, OPC_MODRM, OPT_EA) 335 365 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA) 366 DEF_ASM_OP1(lidtq, 0x0f01, 3, OPC_MODRM, OPT_EA) 336 367 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG) 337 368 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG) 338 ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL , OPT_EA | OPT_REG, OPT_REG))339 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG )369 ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WLX, OPT_EA | OPT_REG, OPT_REG)) 370 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG16) 340 371 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA) 372 DEF_ASM_OP1(sgdtq, 0x0f01, 0, OPC_MODRM, OPT_EA) 341 373 DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA) 374 DEF_ASM_OP1(sidtq, 0x0f01, 1, OPC_MODRM, OPT_EA) 342 375 DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA) 343 376 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA) 344 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA) 377 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG32 | OPT_EA) 378 ALT(DEF_ASM_OP1(str, 0x660f00, 1, OPC_MODRM, OPT_REG16)) 379 ALT(DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM | OPC_48, OPT_REG64)) 345 380 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA) 346 381 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA) 382 DEF_ASM_OP0L(swapgs, 0x0f01, 7, OPC_MODRM) 347 383 348 384 /* 486 */ 385 /* bswap can't be applied to 16bit regs */ 349 386 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 ) 350 ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA )) 351 ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA )) 387 DEF_ASM_OP1(bswapl, 0x0fc8, 0, OPC_REG, OPT_REG32 ) 388 DEF_ASM_OP1(bswapq, 0x0fc8, 0, OPC_REG | OPC_48, OPT_REG64 ) 389 390 ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA )) 391 ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA )) 352 392 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA ) 353 354 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)355 DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)356 393 357 394 /* pentium */ 358 395 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA ) 359 396 397 /* AMD 64 */ 398 DEF_ASM_OP1(cmpxchg16b, 0x0fc7, 1, OPC_MODRM | OPC_48, OPT_EA ) 399 360 400 /* pentium pro */ 361 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 362 ALT(DEF_ASM_OP2(cmovno, 0x0f41, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 363 ALT(DEF_ASM_OP2(cmovc, 0x0f42, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 364 ALT(DEF_ASM_OP2(cmovnc, 0x0f43, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 365 ALT(DEF_ASM_OP2(cmovz, 0x0f44, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 366 ALT(DEF_ASM_OP2(cmovnz, 0x0f45, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 367 ALT(DEF_ASM_OP2(cmovna, 0x0f46, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 368 ALT(DEF_ASM_OP2(cmova, 0x0f47, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32)) 401 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW)) 369 402 370 403 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 ) … … 384 417 /* mmx */ 385 418 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */ 386 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX ) 387 ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 )) 419 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMXSSE ) 420 /* movd shouldn't accept REG64, but AMD64 spec uses it for 32 and 64 bit 421 moves, so let's be compatible. */ 422 ALT(DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG64, OPT_MMXSSE )) 423 ALT(DEF_ASM_OP2(movq, 0x0f6e, 0, OPC_MODRM | OPC_48, OPT_REG64, OPT_MMXSSE )) 388 424 ALT(DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )) 425 ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG32 )) 426 ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG64 )) 389 427 ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX )) 390 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 391 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 392 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 393 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 394 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 395 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 396 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 397 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 398 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 399 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 400 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 401 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 402 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 403 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 404 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 405 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 406 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 407 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 408 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 409 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 410 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 411 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 412 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 413 ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX )) 414 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 415 ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX )) 416 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 417 ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX )) 418 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 419 ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX )) 420 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 421 ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX )) 422 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 423 ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX )) 424 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 425 ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX )) 426 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 427 ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX )) 428 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 429 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 430 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 431 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 432 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 433 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 434 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 435 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 436 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 437 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 438 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 439 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 440 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 441 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ) 442 428 ALT(DEF_ASM_OP2(movq, 0x660fd6, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_SSE )) 429 ALT(DEF_ASM_OP2(movq, 0xf30f7e, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )) 430 ALT(DEF_ASM_OP2(movq, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG64 )) 431 432 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 433 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 434 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 435 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 436 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 437 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 438 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 439 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 440 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 441 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 442 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 443 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 444 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 445 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 446 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 447 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 448 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 449 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 450 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 451 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 452 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 453 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 454 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 455 ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 456 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 457 ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 458 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 459 ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 460 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 461 ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 462 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 463 ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 464 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 465 ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 466 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 467 ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 468 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 469 ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE )) 470 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 471 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 472 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 473 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 474 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 475 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 476 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 477 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 478 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 479 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 480 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 481 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 482 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 483 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 484 485 /* sse */ 486 DEF_ASM_OP2(movups, 0x0f10, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE ) 487 ALT(DEF_ASM_OP2(movups, 0x0f11, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 )) 488 DEF_ASM_OP2(movaps, 0x0f28, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE ) 489 ALT(DEF_ASM_OP2(movaps, 0x0f29, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 )) 490 DEF_ASM_OP2(movhps, 0x0f16, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE ) 491 ALT(DEF_ASM_OP2(movhps, 0x0f17, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 )) 492 DEF_ASM_OP2(addps, 0x0f58, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 493 DEF_ASM_OP2(cvtpi2ps, 0x0f2a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_SSE ) 494 DEF_ASM_OP2(cvtps2pi, 0x0f2d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX ) 495 DEF_ASM_OP2(cvttps2pi, 0x0f2c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX ) 496 DEF_ASM_OP2(divps, 0x0f5e, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 497 DEF_ASM_OP2(maxps, 0x0f5f, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 498 DEF_ASM_OP2(minps, 0x0f5d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 499 DEF_ASM_OP2(mulps, 0x0f59, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 500 DEF_ASM_OP2(pavgb, 0x0fe0, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 501 DEF_ASM_OP2(pavgw, 0x0fe3, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 502 DEF_ASM_OP2(pmaxsw, 0x0fee, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 503 DEF_ASM_OP2(pmaxub, 0x0fde, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 504 DEF_ASM_OP2(pminsw, 0x0fea, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 505 DEF_ASM_OP2(pminub, 0x0fda, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE ) 506 DEF_ASM_OP2(rcpss, 0x0f53, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 507 DEF_ASM_OP2(rsqrtps, 0x0f52, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 508 DEF_ASM_OP2(sqrtps, 0x0f51, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 509 DEF_ASM_OP2(subps, 0x0f5c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ) 510 511 DEF_ASM_OP1(prefetchnta, 0x0f18, 0, OPC_MODRM, OPT_EA) 512 DEF_ASM_OP1(prefetcht0, 0x0f18, 1, OPC_MODRM, OPT_EA) 513 DEF_ASM_OP1(prefetcht1, 0x0f18, 2, OPC_MODRM, OPT_EA) 514 DEF_ASM_OP1(prefetcht2, 0x0f18, 3, OPC_MODRM, OPT_EA) 515 DEF_ASM_OP1(prefetchw, 0x0f0d, 1, OPC_MODRM, OPT_EA) 516 DEF_ASM_OP0L(lfence, 0x0fae, 5, OPC_MODRM) 517 DEF_ASM_OP0L(mfence, 0x0fae, 6, OPC_MODRM) 518 DEF_ASM_OP0L(sfence, 0x0fae, 7, OPC_MODRM) 519 DEF_ASM_OP1(clflush, 0x0fae, 7, OPC_MODRM, OPT_EA) 443 520 #undef ALT 444 521 #undef DEF_ASM_OP0 -
EcnlProtoTool/trunk/tcc-0.9.27/x86_64-gen.c
r321 r331 24 24 25 25 /* number of available registers */ 26 #define NB_REGS 5 27 #define NB_ASM_REGS 8 26 #define NB_REGS 25 27 #define NB_ASM_REGS 16 28 #define CONFIG_TCC_ASM 28 29 29 30 /* a register can belong to several classes. The classes must be … … 35 36 #define RC_RCX 0x0008 36 37 #define RC_RDX 0x0010 38 #define RC_ST0 0x0080 /* only for long double */ 37 39 #define RC_R8 0x0100 38 40 #define RC_R9 0x0200 39 41 #define RC_R10 0x0400 40 42 #define RC_R11 0x0800 41 #define RC_XMM0 0x0020 42 #define RC_ST0 0x0040 /* only for long double */ 43 #define RC_XMM0 0x1000 44 #define RC_XMM1 0x2000 45 #define RC_XMM2 0x4000 46 #define RC_XMM3 0x8000 47 #define RC_XMM4 0x10000 48 #define RC_XMM5 0x20000 49 #define RC_XMM6 0x40000 50 #define RC_XMM7 0x80000 43 51 #define RC_IRET RC_RAX /* function return: integer register */ 44 52 #define RC_LRET RC_RDX /* function return: second integer register */ 45 53 #define RC_FRET RC_XMM0 /* function return: float register */ 54 #define RC_QRET RC_XMM1 /* function return: second float register */ 46 55 47 56 /* pretty names for the registers */ … … 50 59 TREG_RCX = 1, 51 60 TREG_RDX = 2, 52 TREG_XMM0 = 3, 53 TREG_ST0 = 4, 54 61 TREG_RSP = 4, 55 62 TREG_RSI = 6, 56 63 TREG_RDI = 7, 64 57 65 TREG_R8 = 8, 58 66 TREG_R9 = 9, 59 60 67 TREG_R10 = 10, 61 68 TREG_R11 = 11, 62 69 63 TREG_MEM = 0x10, 70 TREG_XMM0 = 16, 71 TREG_XMM1 = 17, 72 TREG_XMM2 = 18, 73 TREG_XMM3 = 19, 74 TREG_XMM4 = 20, 75 TREG_XMM5 = 21, 76 TREG_XMM6 = 22, 77 TREG_XMM7 = 23, 78 79 TREG_ST0 = 24, 80 81 TREG_MEM = 0x20 64 82 }; 65 83 … … 71 89 #define REG_LRET TREG_RDX /* second word return register (for long long) */ 72 90 #define REG_FRET TREG_XMM0 /* float return register */ 91 #define REG_QRET TREG_XMM1 /* second float return register */ 73 92 74 93 /* defined if function parameters must be evaluated in reverse order */ … … 80 99 /* long double size and alignment, in bytes */ 81 100 #define LDOUBLE_SIZE 16 82 #define LDOUBLE_ALIGN 8101 #define LDOUBLE_ALIGN 16 83 102 /* maximum alignment (for aligned attribute support) */ 84 #define MAX_ALIGN 8 85 86 /******************************************************/ 87 /* ELF defines */ 88 89 #define EM_TCC_TARGET EM_X86_64 90 91 /* relocation type for 32 bit data relocation */ 92 #define R_DATA_32 R_X86_64_32 93 #define R_DATA_PTR R_X86_64_64 94 #define R_JMP_SLOT R_X86_64_JUMP_SLOT 95 #define R_COPY R_X86_64_COPY 96 97 #define ELF_START_ADDR 0x08048000 98 #define ELF_PAGE_SIZE 0x1000 103 #define MAX_ALIGN 16 99 104 100 105 /******************************************************/ … … 104 109 #include <assert.h> 105 110 106 ST_DATA const int reg_classes[NB_REGS +7] = {111 ST_DATA const int reg_classes[NB_REGS] = { 107 112 /* eax */ RC_INT | RC_RAX, 108 113 /* ecx */ RC_INT | RC_RCX, 109 114 /* edx */ RC_INT | RC_RDX, 110 /* xmm0 */ RC_FLOAT | RC_XMM0,111 /* st0 */ RC_ST0,112 115 0, 113 116 0, 114 117 0, 115 RC_INT | RC_R8, 116 RC_INT | RC_R9, 117 RC_INT | RC_R10, 118 RC_INT | RC_R11 118 0, 119 0, 120 RC_R8, 121 RC_R9, 122 RC_R10, 123 RC_R11, 124 0, 125 0, 126 0, 127 0, 128 /* xmm0 */ RC_FLOAT | RC_XMM0, 129 /* xmm1 */ RC_FLOAT | RC_XMM1, 130 /* xmm2 */ RC_FLOAT | RC_XMM2, 131 /* xmm3 */ RC_FLOAT | RC_XMM3, 132 /* xmm4 */ RC_FLOAT | RC_XMM4, 133 /* xmm5 */ RC_FLOAT | RC_XMM5, 134 /* xmm6 an xmm7 are included so gv() can be used on them, 135 but they are not tagged with RC_FLOAT because they are 136 callee saved on Windows */ 137 RC_XMM6, 138 RC_XMM7, 139 /* st0 */ RC_ST0 119 140 }; 120 141 … … 123 144 124 145 /* XXX: make it faster ? */ 125 void g(int c)146 ST_FUNC void g(int c) 126 147 { 127 148 int ind1; 149 if (nocode_wanted) 150 return; 128 151 ind1 = ind + 1; 129 152 if (ind1 > cur_text_section->data_allocated) … … 133 156 } 134 157 135 void o(unsigned int c)158 ST_FUNC void o(unsigned int c) 136 159 { 137 160 while (c) { … … 141 164 } 142 165 143 void gen_le16(int v)166 ST_FUNC void gen_le16(int v) 144 167 { 145 168 g(v); … … 147 170 } 148 171 149 void gen_le32(int c)172 ST_FUNC void gen_le32(int c) 150 173 { 151 174 g(c); … … 155 178 } 156 179 157 void gen_le64(int64_t c)180 ST_FUNC void gen_le64(int64_t c) 158 181 { 159 182 g(c); … … 167 190 } 168 191 169 void orex(int ll, int r, int r2, int b)192 static void orex(int ll, int r, int r2, int b) 170 193 { 171 194 if ((r & VT_VALMASK) >= VT_CONST) … … 179 202 180 203 /* output a symbol and patch all calls to it */ 181 void gsym_addr(int t, int a) 182 { 183 int n, *ptr; 204 ST_FUNC void gsym_addr(int t, int a) 205 { 184 206 while (t) { 185 ptr = (int *)(cur_text_section->data + t);186 n = *ptr; /* next value */187 *ptr = a - t - 4;207 unsigned char *ptr = cur_text_section->data + t; 208 uint32_t n = read32le(ptr); /* next value */ 209 write32le(ptr, a - t - 4); 188 210 t = n; 189 211 } … … 195 217 } 196 218 197 /* psym is used to put an instruction with a data field which is a198 reference to a symbol. It is in fact the same as oad ! */199 #define psym oad200 219 201 220 static int is64_type(int t) … … 206 225 } 207 226 208 static int is_sse_float(int t) {209 int bt;210 bt = t & VT_BTYPE;211 return bt == VT_DOUBLE || bt == VT_FLOAT;212 }213 214 215 227 /* instruction + 4 bytes data. Return the address of the data */ 216 ST_FUNC int oad(int c, int s) 217 { 218 int ind1; 219 228 static int oad(int c, int s) 229 { 230 int t; 231 if (nocode_wanted) 232 return s; 220 233 o(c); 221 ind1 = ind + 4; 222 if (ind1 > cur_text_section->data_allocated) 223 section_realloc(cur_text_section, ind1); 224 *(int *)(cur_text_section->data + ind) = s; 225 s = ind; 226 ind = ind1; 227 return s; 228 } 234 t = ind; 235 gen_le32(s); 236 return t; 237 } 238 239 /* generate jmp to a label */ 240 #define gjmp2(instr,lbl) oad(instr,lbl) 229 241 230 242 ST_FUNC void gen_addr32(int r, Sym *sym, int c) 231 243 { 232 244 if (r & VT_SYM) 233 greloc (cur_text_section, sym, ind, R_X86_64_32);245 greloca(cur_text_section, sym, ind, R_X86_64_32S, c), c=0; 234 246 gen_le32(c); 235 247 } … … 239 251 { 240 252 if (r & VT_SYM) 241 greloc (cur_text_section, sym, ind, R_X86_64_64);253 greloca(cur_text_section, sym, ind, R_X86_64_64, c), c=0; 242 254 gen_le64(c); 243 255 } … … 247 259 { 248 260 if (r & VT_SYM) 249 greloc (cur_text_section, sym, ind, R_X86_64_PC32);261 greloca(cur_text_section, sym, ind, R_X86_64_PC32, c-4), c=4; 250 262 gen_le32(c-4); 251 263 } … … 254 266 static void gen_gotpcrel(int r, Sym *sym, int c) 255 267 { 256 #ifndef TCC_TARGET_PE 257 Section *sr; 258 ElfW(Rela) *rel; 259 greloc(cur_text_section, sym, ind, R_X86_64_GOTPCREL); 260 sr = cur_text_section->reloc; 261 rel = (ElfW(Rela) *)(sr->data + sr->data_offset - sizeof(ElfW(Rela))); 262 rel->r_addend = -4; 263 #else 264 printf("picpic: %s %x %x | %02x %02x %02x\n", get_tok_str(sym->v, NULL), c, r, 268 #ifdef TCC_TARGET_PE 269 tcc_error("internal error: no GOT on PE: %s %x %x | %02x %02x %02x\n", 270 get_tok_str(sym->v, NULL), c, r, 265 271 cur_text_section->data[ind-3], 266 272 cur_text_section->data[ind-2], 267 273 cur_text_section->data[ind-1] 268 274 ); 269 greloc(cur_text_section, sym, ind, R_X86_64_PC32);270 275 #endif 276 greloca(cur_text_section, sym, ind, R_X86_64_GOTPCREL, -4); 271 277 gen_le32(0); 272 278 if (c) { … … 283 289 if ((r & VT_VALMASK) == VT_CONST) { 284 290 /* constant memory reference */ 285 o(0x05 | op_reg); 286 if (is_got) { 287 gen_gotpcrel(r, sym, c); 288 } else { 289 gen_addrpc32(r, sym, c); 290 } 291 if (!(r & VT_SYM)) { 292 /* Absolute memory reference */ 293 o(0x04 | op_reg); /* [sib] | destreg */ 294 oad(0x25, c); /* disp32 */ 295 } else { 296 o(0x05 | op_reg); /* (%rip)+disp32 | destreg */ 297 if (is_got) { 298 gen_gotpcrel(r, sym, c); 299 } else { 300 gen_addrpc32(r, sym, c); 301 } 302 } 291 303 } else if ((r & VT_VALMASK) == VT_LOCAL) { 292 304 /* currently, we use only ebp as base */ … … 310 322 } 311 323 312 /* generate a modrm reference. 'op_reg' contains the add tionnal 3324 /* generate a modrm reference. 'op_reg' contains the additional 3 313 325 opcode bits */ 314 326 static void gen_modrm(int op_reg, int r, Sym *sym, int c) … … 317 329 } 318 330 319 /* generate a modrm reference. 'op_reg' contains the add tionnal 3331 /* generate a modrm reference. 'op_reg' contains the additional 3 320 332 opcode bits */ 321 333 static void gen_modrm64(int opcode, int op_reg, int r, Sym *sym, int c) … … 340 352 341 353 fr = sv->r; 342 ft = sv->type.t; 343 fc = sv->c.ul; 354 ft = sv->type.t & ~VT_DEFSIGN; 355 fc = sv->c.i; 356 if (fc != sv->c.i && (fr & VT_SYM)) 357 tcc_error("64 bit addend in load"); 358 359 ft &= ~(VT_VOLATILE | VT_CONSTANT); 344 360 345 361 #ifndef TCC_TARGET_PE … … 366 382 v1.type.t = VT_PTR; 367 383 v1.r = VT_LOCAL | VT_LVAL; 368 v1.c. ul= fc;384 v1.c.i = fc; 369 385 fr = r; 370 if (!(reg_classes[fr] & RC_INT))386 if (!(reg_classes[fr] & (RC_INT|RC_R11))) 371 387 fr = get_reg(RC_INT); 372 388 load(fr, &v1); 373 389 } 390 if (fc != sv->c.i) { 391 /* If the addends doesn't fit into a 32bit signed 392 we must use a 64bit move. We've checked above 393 that this doesn't have a sym associated. */ 394 v1.type.t = VT_LLONG; 395 v1.r = VT_CONST; 396 v1.c.i = sv->c.i; 397 fr = r; 398 if (!(reg_classes[fr] & (RC_INT|RC_R11))) 399 fr = get_reg(RC_INT); 400 load(fr, &v1); 401 fc = 0; 402 } 374 403 ll = 0; 404 /* Like GCC we can load from small enough properly sized 405 structs and unions as well. 406 XXX maybe move to generic operand handling, but should 407 occur only with asm, so tccasm.c might also be a better place */ 408 if ((ft & VT_BTYPE) == VT_STRUCT) { 409 int align; 410 switch (type_size(&sv->type, &align)) { 411 case 1: ft = VT_BYTE; break; 412 case 2: ft = VT_SHORT; break; 413 case 4: ft = VT_INT; break; 414 case 8: ft = VT_LLONG; break; 415 default: 416 tcc_error("invalid aggregate type for register load"); 417 break; 418 } 419 } 375 420 if ((ft & VT_BTYPE) == VT_FLOAT) { 376 b = 0x6e0f66, r = 0; /* movd */ 421 b = 0x6e0f66; 422 r = REG_VALUE(r); /* movd */ 377 423 } else if ((ft & VT_BTYPE) == VT_DOUBLE) { 378 b = 0x7e0ff3, r = 0; /* movq */ 424 b = 0x7e0ff3; /* movq */ 425 r = REG_VALUE(r); 379 426 } else if ((ft & VT_BTYPE) == VT_LDOUBLE) { 380 427 b = 0xdb, r = 5; /* fldt */ 381 } else if ((ft & VT_TYPE) == VT_BYTE ) {428 } else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) { 382 429 b = 0xbe0f; /* movsbl */ 383 430 } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { … … 388 435 b = 0xb70f; /* movzwl */ 389 436 } else { 437 assert(((ft & VT_BTYPE) == VT_INT) 438 || ((ft & VT_BTYPE) == VT_LLONG) 439 || ((ft & VT_BTYPE) == VT_PTR) 440 || ((ft & VT_BTYPE) == VT_FUNC) 441 ); 390 442 ll = is64_type(ft); 391 443 b = 0x8b; … … 417 469 } else if (is64_type(ft)) { 418 470 orex(1,r,0, 0xb8 + REG_VALUE(r)); /* mov $xx, r */ 419 gen_le64(sv->c. ull);471 gen_le64(sv->c.i); 420 472 } else { 421 473 orex(0,r,0, 0xb8 + REG_VALUE(r)); /* mov $xx, r */ … … 451 503 oad(0xb8 + REG_VALUE(r), t ^ 1); /* mov $0, r */ 452 504 } else if (v != r) { 453 if (r == TREG_XMM0) { 454 assert(v == TREG_ST0); 455 /* gen_cvt_ftof(VT_DOUBLE); */ 456 o(0xf0245cdd); /* fstpl -0x10(%rsp) */ 457 /* movsd -0x10(%rsp),%xmm0 */ 458 o(0x44100ff2); 459 o(0xf024); 505 if ((r >= TREG_XMM0) && (r <= TREG_XMM7)) { 506 if (v == TREG_ST0) { 507 /* gen_cvt_ftof(VT_DOUBLE); */ 508 o(0xf0245cdd); /* fstpl -0x10(%rsp) */ 509 /* movsd -0x10(%rsp),%xmmN */ 510 o(0x100ff2); 511 o(0x44 + REG_VALUE(r)*8); /* %xmmN */ 512 o(0xf024); 513 } else { 514 assert((v >= TREG_XMM0) && (v <= TREG_XMM7)); 515 if ((ft & VT_BTYPE) == VT_FLOAT) { 516 o(0x100ff3); 517 } else { 518 assert((ft & VT_BTYPE) == VT_DOUBLE); 519 o(0x100ff2); 520 } 521 o(0xc0 + REG_VALUE(v) + REG_VALUE(r)*8); 522 } 460 523 } else if (r == TREG_ST0) { 461 assert( v == TREG_XMM0);524 assert((v >= TREG_XMM0) && (v <= TREG_XMM7)); 462 525 /* gen_cvt_ftof(VT_LDOUBLE); */ 463 /* movsd %xmm0,-0x10(%rsp) */ 464 o(0x44110ff2); 526 /* movsd %xmmN,-0x10(%rsp) */ 527 o(0x110ff2); 528 o(0x44 + REG_VALUE(r)*8); /* %xmmN */ 465 529 o(0xf024); 466 530 o(0xf02444dd); /* fldl -0x10(%rsp) */ … … 486 550 #endif 487 551 552 fr = v->r & VT_VALMASK; 488 553 ft = v->type.t; 489 fc = v->c.ul; 490 fr = v->r & VT_VALMASK; 554 fc = v->c.i; 555 if (fc != v->c.i && (fr & VT_SYM)) 556 tcc_error("64 bit addend in store"); 557 ft &= ~(VT_VOLATILE | VT_CONSTANT); 491 558 bt = ft & VT_BTYPE; 492 559 … … 496 563 /* mov xx(%rip), %r11 */ 497 564 o(0x1d8b4c); 498 gen_gotpcrel(TREG_R11, v->sym, v->c. ul);565 gen_gotpcrel(TREG_R11, v->sym, v->c.i); 499 566 pic = is64_type(bt) ? 0x49 : 0x41; 500 567 } … … 506 573 o(pic); 507 574 o(0x7e0f); /* movd */ 508 r = 0;575 r = REG_VALUE(r); 509 576 } else if (bt == VT_DOUBLE) { 510 577 o(0x66); 511 578 o(pic); 512 579 o(0xd60f); /* movq */ 513 r = 0;580 r = REG_VALUE(r); 514 581 } else if (bt == VT_LDOUBLE) { 515 582 o(0xc0d9); /* fld %st(0) */ … … 556 623 { 557 624 int r; 558 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { 625 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && 626 ((vtop->r & VT_SYM) || (vtop->c.i-4) == (int)(vtop->c.i-4))) { 559 627 /* constant case */ 560 628 if (vtop->r & VT_SYM) { 561 629 /* relocation case */ 562 greloc(cur_text_section, vtop->sym, 563 ind + 1, R_X86_64_PC32); 630 #ifdef TCC_TARGET_PE 631 greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32, (int)(vtop->c.i-4)); 632 #else 633 greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4)); 634 #endif 564 635 } else { 565 636 /* put an empty PC32 relocation */ 566 put_elf_reloc (symtab_section, cur_text_section,567 ind + 1, R_X86_64_PC32, 0 );568 } 569 oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */637 put_elf_reloca(symtab_section, cur_text_section, 638 ind + 1, R_X86_64_PC32, 0, (int)(vtop->c.i-4)); 639 } 640 oad(0xe8 + is_jmp, 0); /* call/jmp im */ 570 641 } else { 571 642 /* otherwise, indirect call */ … … 578 649 } 579 650 651 #if defined(CONFIG_TCC_BCHECK) 652 #ifndef TCC_TARGET_PE 653 static addr_t func_bound_offset; 654 static unsigned long func_bound_ind; 655 #endif 656 657 static void gen_static_call(int v) 658 { 659 Sym *sym = external_global_sym(v, &func_old_type, 0); 660 oad(0xe8, 0); 661 greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4); 662 } 663 664 /* generate a bounded pointer addition */ 665 ST_FUNC void gen_bounded_ptr_add(void) 666 { 667 /* save all temporary registers */ 668 save_regs(0); 669 670 /* prepare fast x86_64 function call */ 671 gv(RC_RAX); 672 o(0xc68948); // mov %rax,%rsi ## second arg in %rsi, this must be size 673 vtop--; 674 675 gv(RC_RAX); 676 o(0xc78948); // mov %rax,%rdi ## first arg in %rdi, this must be ptr 677 vtop--; 678 679 /* do a fast function call */ 680 gen_static_call(TOK___bound_ptr_add); 681 682 /* returned pointer is in rax */ 683 vtop++; 684 vtop->r = TREG_RAX | VT_BOUNDED; 685 686 687 /* relocation offset of the bounding function call point */ 688 vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(ElfW(Rela))); 689 } 690 691 /* patch pointer addition in vtop so that pointer dereferencing is 692 also tested */ 693 ST_FUNC void gen_bounded_ptr_deref(void) 694 { 695 addr_t func; 696 int size, align; 697 ElfW(Rela) *rel; 698 Sym *sym; 699 700 size = 0; 701 /* XXX: put that code in generic part of tcc */ 702 if (!is_float(vtop->type.t)) { 703 if (vtop->r & VT_LVAL_BYTE) 704 size = 1; 705 else if (vtop->r & VT_LVAL_SHORT) 706 size = 2; 707 } 708 if (!size) 709 size = type_size(&vtop->type, &align); 710 switch(size) { 711 case 1: func = TOK___bound_ptr_indir1; break; 712 case 2: func = TOK___bound_ptr_indir2; break; 713 case 4: func = TOK___bound_ptr_indir4; break; 714 case 8: func = TOK___bound_ptr_indir8; break; 715 case 12: func = TOK___bound_ptr_indir12; break; 716 case 16: func = TOK___bound_ptr_indir16; break; 717 default: 718 tcc_error("unhandled size when dereferencing bounded pointer"); 719 func = 0; 720 break; 721 } 722 723 sym = external_global_sym(func, &func_old_type, 0); 724 if (!sym->c) 725 put_extern_sym(sym, NULL, 0, 0); 726 727 /* patch relocation */ 728 /* XXX: find a better solution ? */ 729 730 rel = (ElfW(Rela) *)(cur_text_section->reloc->data + vtop->c.i); 731 rel->r_info = ELF64_R_INFO(sym->c, ELF64_R_TYPE(rel->r_info)); 732 } 733 #endif 734 580 735 #ifdef TCC_TARGET_PE 581 736 582 737 #define REGN 4 583 static const uint8_t arg_regs[ ] = {738 static const uint8_t arg_regs[REGN] = { 584 739 TREG_RCX, TREG_RDX, TREG_R8, TREG_R9 585 740 }; 586 741 587 static int func_scratch; 742 /* Prepare arguments in R10 and R11 rather than RCX and RDX 743 because gv() will not ever use these */ 744 static int arg_prepare_reg(int idx) { 745 if (idx == 0 || idx == 1) 746 /* idx=0: r10, idx=1: r11 */ 747 return idx + 10; 748 else 749 return arg_regs[idx]; 750 } 751 752 static int func_scratch, func_alloca; 588 753 589 754 /* Generate function call. The function address is pushed first, then … … 591 756 parameters and the function address. */ 592 757 593 void gen_offs_sp(int b, int r, int d)758 static void gen_offs_sp(int b, int r, int d) 594 759 { 595 760 orex(1,0,r & 0x100 ? 0 : r, b); … … 603 768 } 604 769 770 static int using_regs(int size) 771 { 772 return !(size > 8 || (size & (size - 1))); 773 } 774 775 /* Return the number of registers needed to return the struct, or 0 if 776 returning via struct pointer. */ 777 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) 778 { 779 int size, align; 780 *ret_align = 1; // Never have to re-align return values for x86-64 781 *regsize = 8; 782 size = type_size(vt, &align); 783 if (!using_regs(size)) 784 return 0; 785 if (size == 8) 786 ret->t = VT_LLONG; 787 else if (size == 4) 788 ret->t = VT_INT; 789 else if (size == 2) 790 ret->t = VT_SHORT; 791 else 792 ret->t = VT_BYTE; 793 ret->ref = NULL; 794 return 1; 795 } 796 797 static int is_sse_float(int t) { 798 int bt; 799 bt = t & VT_BTYPE; 800 return bt == VT_DOUBLE || bt == VT_FLOAT; 801 } 802 803 static int gfunc_arg_size(CType *type) { 804 int align; 805 if (type->t & (VT_ARRAY|VT_BITFIELD)) 806 return 8; 807 return type_size(type, &align); 808 } 809 605 810 void gfunc_call(int nb_args) 606 811 { 607 int size, align, r, args_size, i, d, j, bt, struct_size;608 int nb_reg_args, gen_reg;609 610 nb_reg_args = nb_args;611 arg s_size = (nb_reg_args < REGN ? REGN : nb_reg_args) * PTR_SIZE;812 int size, r, args_size, i, d, bt, struct_size; 813 int arg; 814 815 args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE; 816 arg = nb_args; 612 817 613 818 /* for struct arguments, we need to call memcpy and the function … … 616 821 struct_size = args_size; 617 822 for(i = 0; i < nb_args; i++) { 618 SValue *sv = &vtop[-i]; 823 SValue *sv; 824 825 --arg; 826 sv = &vtop[-i]; 619 827 bt = (sv->type.t & VT_BTYPE); 828 size = gfunc_arg_size(&sv->type); 829 830 if (using_regs(size)) 831 continue; /* arguments smaller than 8 bytes passed in registers or on stack */ 832 620 833 if (bt == VT_STRUCT) { 621 size = type_size(&sv->type, &align);622 834 /* align to stack align size */ 623 835 size = (size + 15) & ~15; … … 632 844 vstore(); 633 845 --vtop; 634 635 846 } else if (bt == VT_LDOUBLE) { 636 637 847 gv(RC_ST0); 638 848 gen_offs_sp(0xdb, 0x107, struct_size); 639 849 struct_size += 16; 640 641 850 } 642 851 } … … 644 853 if (func_scratch < struct_size) 645 854 func_scratch = struct_size; 646 #if 1 647 for (i = 0; i < REGN; ++i) 648 save_reg(arg_regs[i]); 649 save_reg(TREG_RAX); 650 #endif 651 gen_reg = nb_reg_args; 855 856 arg = nb_args; 652 857 struct_size = args_size; 653 858 654 859 for(i = 0; i < nb_args; i++) { 860 --arg; 655 861 bt = (vtop->type.t & VT_BTYPE); 656 862 657 if (bt == VT_STRUCT || bt == VT_LDOUBLE) { 658 if (bt == VT_LDOUBLE) 659 size = 16; 660 else 661 size = type_size(&vtop->type, &align); 863 size = gfunc_arg_size(&vtop->type); 864 if (!using_regs(size)) { 662 865 /* align to stack align size */ 663 866 size = (size + 15) & ~15; 664 j = --gen_reg; 665 if (j >= REGN) { 666 d = TREG_RAX; 867 if (arg >= REGN) { 868 d = get_reg(RC_INT); 667 869 gen_offs_sp(0x8d, d, struct_size); 668 gen_offs_sp(0x89, d, j*8);870 gen_offs_sp(0x89, d, arg*8); 669 871 } else { 670 d = arg_ regs[j];872 d = arg_prepare_reg(arg); 671 873 gen_offs_sp(0x8d, d, struct_size); 672 874 } 673 875 struct_size += size; 674 675 } else if (is_sse_float(vtop->type.t)) { 676 gv(RC_FLOAT); /* only one float register */ 677 j = --gen_reg; 678 if (j >= REGN) { 679 /* movq %xmm0, j*8(%rsp) */ 680 gen_offs_sp(0xd60f66, 0x100, j*8); 876 } else { 877 if (is_sse_float(vtop->type.t)) { 878 if (tcc_state->nosse) 879 tcc_error("SSE disabled"); 880 gv(RC_XMM0); /* only use one float register */ 881 if (arg >= REGN) { 882 /* movq %xmm0, j*8(%rsp) */ 883 gen_offs_sp(0xd60f66, 0x100, arg*8); 884 } else { 885 /* movaps %xmm0, %xmmN */ 886 o(0x280f); 887 o(0xc0 + (arg << 3)); 888 d = arg_prepare_reg(arg); 889 /* mov %xmm0, %rxx */ 890 o(0x66); 891 orex(1,d,0, 0x7e0f); 892 o(0xc0 + REG_VALUE(d)); 893 } 681 894 } else { 682 /* movaps %xmm0, %xmmN */ 683 o(0x280f); 684 o(0xc0 + (j << 3)); 685 d = arg_regs[j]; 686 /* mov %xmm0, %rxx */ 687 o(0x66); 688 orex(1,d,0, 0x7e0f); 689 o(0xc0 + REG_VALUE(d)); 690 } 691 } else { 692 j = --gen_reg; 693 if (j >= REGN) { 895 if (bt == VT_STRUCT) { 896 vtop->type.ref = NULL; 897 vtop->type.t = size > 4 ? VT_LLONG : size > 2 ? VT_INT 898 : size > 1 ? VT_SHORT : VT_BYTE; 899 } 900 694 901 r = gv(RC_INT); 695 gen_offs_sp(0x89, r, j*8); 696 } else { 697 d = arg_regs[j]; 698 if (d < NB_REGS) { 699 gv(reg_classes[d] & ~RC_INT); 902 if (arg >= REGN) { 903 gen_offs_sp(0x89, r, arg*8); 700 904 } else { 701 r = gv(RC_INT); 702 if (d != r) { 703 orex(1,d,r, 0x89); 704 o(0xc0 + REG_VALUE(d) + REG_VALUE(r) * 8); 705 } 905 d = arg_prepare_reg(arg); 906 orex(1,d,r,0x89); /* mov */ 907 o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d)); 706 908 } 707 708 909 } 709 910 } … … 711 912 } 712 913 save_regs(0); 914 915 /* Copy R10 and R11 into RCX and RDX, respectively */ 916 if (nb_args > 0) { 917 o(0xd1894c); /* mov %r10, %rcx */ 918 if (nb_args > 1) { 919 o(0xda894c); /* mov %r11, %rdx */ 920 } 921 } 922 713 923 gcall_or_jmp(0); 924 925 if ((vtop->r & VT_SYM) && vtop->sym->v == TOK_alloca) { 926 /* need to add the "func_scratch" area after alloca */ 927 o(0x0548), gen_le32(func_alloca), func_alloca = ind - 4; 928 } 929 930 /* other compilers don't clear the upper bits when returning char/short */ 931 bt = vtop->type.ref->type.t & (VT_BTYPE | VT_UNSIGNED); 932 if (bt == (VT_BYTE | VT_UNSIGNED)) 933 o(0xc0b60f); /* movzbl %al, %eax */ 934 else if (bt == VT_BYTE) 935 o(0xc0be0f); /* movsbl %al, %eax */ 936 else if (bt == VT_SHORT) 937 o(0x98); /* cwtl */ 938 else if (bt == (VT_SHORT | VT_UNSIGNED)) 939 o(0xc0b70f); /* movzbl %al, %eax */ 940 #if 0 /* handled in gen_cast() */ 941 else if (bt == VT_INT) 942 o(0x9848); /* cltq */ 943 else if (bt == (VT_INT | VT_UNSIGNED)) 944 o(0xc089); /* mov %eax,%eax */ 945 #endif 714 946 vtop--; 715 947 } … … 721 953 void gfunc_prolog(CType *func_type) 722 954 { 723 int addr, reg_param_index, bt ;955 int addr, reg_param_index, bt, size; 724 956 Sym *sym; 725 957 CType *type; … … 727 959 func_ret_sub = 0; 728 960 func_scratch = 0; 961 func_alloca = 0; 729 962 loc = 0; 730 963 … … 739 972 implicit pointer parameter */ 740 973 func_vt = sym->type; 741 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { 974 func_var = (sym->f.func_type == FUNC_ELLIPSIS); 975 size = gfunc_arg_size(&func_vt); 976 if (!using_regs(size)) { 742 977 gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); 978 func_vc = addr; 743 979 reg_param_index++; 744 addr += PTR_SIZE;980 addr += 8; 745 981 } 746 982 … … 749 985 type = &sym->type; 750 986 bt = type->t & VT_BTYPE; 751 if (reg_param_index < REGN) { 752 /* save arguments passed by register */ 987 size = gfunc_arg_size(type); 988 if (!using_regs(size)) { 989 if (reg_param_index < REGN) { 990 gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); 991 } 992 sym_push(sym->v & ~SYM_FIELD, type, VT_LLOCAL | VT_LVAL, addr); 993 } else { 994 if (reg_param_index < REGN) { 995 /* save arguments passed by register */ 996 if ((bt == VT_FLOAT) || (bt == VT_DOUBLE)) { 997 if (tcc_state->nosse) 998 tcc_error("SSE disabled"); 999 o(0xd60f66); /* movq */ 1000 gen_modrm(reg_param_index, VT_LOCAL, NULL, addr); 1001 } else { 1002 gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); 1003 } 1004 } 1005 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr); 1006 } 1007 addr += 8; 1008 reg_param_index++; 1009 } 1010 1011 while (reg_param_index < REGN) { 1012 if (func_type->ref->f.func_type == FUNC_ELLIPSIS) { 753 1013 gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); 754 } 755 if (bt == VT_STRUCT || bt == VT_LDOUBLE) { 756 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL | VT_REF, addr); 757 } else { 758 sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr); 1014 addr += 8; 759 1015 } 760 1016 reg_param_index++; 761 addr += PTR_SIZE;762 }763 764 while (reg_param_index < REGN) {765 if (func_type->ref->c == FUNC_ELLIPSIS)766 gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);767 reg_param_index++;768 addr += PTR_SIZE;769 1017 } 770 1018 } … … 787 1035 ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; 788 1036 /* align local size to word & save local variables */ 1037 func_scratch = (func_scratch + 15) & -16; 789 1038 v = (func_scratch + -loc + 15) & -16; 790 1039 … … 792 1041 Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0); 793 1042 oad(0xb8, v); /* mov stacksize, %eax */ 794 oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */795 greloc (cur_text_section, sym, ind-4, R_X86_64_PC32);1043 oad(0xe8, 0); /* call __chkstk, (does the stackframe too) */ 1044 greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4); 796 1045 o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */ 797 1046 } else { … … 801 1050 } 802 1051 1052 /* add the "func_scratch" area after each alloca seen */ 1053 while (func_alloca) { 1054 unsigned char *ptr = cur_text_section->data + func_alloca; 1055 func_alloca = read32le(ptr); 1056 write32le(ptr, func_scratch); 1057 } 1058 803 1059 cur_text_section->data_offset = saved_ind; 804 1060 pe_add_unwind_data(ind, saved_ind, v); … … 818 1074 } 819 1075 1076 typedef enum X86_64_Mode { 1077 x86_64_mode_none, 1078 x86_64_mode_memory, 1079 x86_64_mode_integer, 1080 x86_64_mode_sse, 1081 x86_64_mode_x87 1082 } X86_64_Mode; 1083 1084 static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) 1085 { 1086 if (a == b) 1087 return a; 1088 else if (a == x86_64_mode_none) 1089 return b; 1090 else if (b == x86_64_mode_none) 1091 return a; 1092 else if ((a == x86_64_mode_memory) || (b == x86_64_mode_memory)) 1093 return x86_64_mode_memory; 1094 else if ((a == x86_64_mode_integer) || (b == x86_64_mode_integer)) 1095 return x86_64_mode_integer; 1096 else if ((a == x86_64_mode_x87) || (b == x86_64_mode_x87)) 1097 return x86_64_mode_memory; 1098 else 1099 return x86_64_mode_sse; 1100 } 1101 1102 static X86_64_Mode classify_x86_64_inner(CType *ty) 1103 { 1104 X86_64_Mode mode; 1105 Sym *f; 1106 1107 switch (ty->t & VT_BTYPE) { 1108 case VT_VOID: return x86_64_mode_none; 1109 1110 case VT_INT: 1111 case VT_BYTE: 1112 case VT_SHORT: 1113 case VT_LLONG: 1114 case VT_BOOL: 1115 case VT_PTR: 1116 case VT_FUNC: 1117 return x86_64_mode_integer; 1118 1119 case VT_FLOAT: 1120 case VT_DOUBLE: return x86_64_mode_sse; 1121 1122 case VT_LDOUBLE: return x86_64_mode_x87; 1123 1124 case VT_STRUCT: 1125 f = ty->ref; 1126 1127 mode = x86_64_mode_none; 1128 for (f = f->next; f; f = f->next) 1129 mode = classify_x86_64_merge(mode, classify_x86_64_inner(&f->type)); 1130 1131 return mode; 1132 } 1133 assert(0); 1134 return 0; 1135 } 1136 1137 static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count) 1138 { 1139 X86_64_Mode mode; 1140 int size, align, ret_t = 0; 1141 1142 if (ty->t & (VT_BITFIELD|VT_ARRAY)) { 1143 *psize = 8; 1144 *palign = 8; 1145 *reg_count = 1; 1146 ret_t = ty->t; 1147 mode = x86_64_mode_integer; 1148 } else { 1149 size = type_size(ty, &align); 1150 *psize = (size + 7) & ~7; 1151 *palign = (align + 7) & ~7; 1152 1153 if (size > 16) { 1154 mode = x86_64_mode_memory; 1155 } else { 1156 mode = classify_x86_64_inner(ty); 1157 switch (mode) { 1158 case x86_64_mode_integer: 1159 if (size > 8) { 1160 *reg_count = 2; 1161 ret_t = VT_QLONG; 1162 } else { 1163 *reg_count = 1; 1164 ret_t = (size > 4) ? VT_LLONG : VT_INT; 1165 } 1166 break; 1167 1168 case x86_64_mode_x87: 1169 *reg_count = 1; 1170 ret_t = VT_LDOUBLE; 1171 break; 1172 1173 case x86_64_mode_sse: 1174 if (size > 8) { 1175 *reg_count = 2; 1176 ret_t = VT_QFLOAT; 1177 } else { 1178 *reg_count = 1; 1179 ret_t = (size > 4) ? VT_DOUBLE : VT_FLOAT; 1180 } 1181 break; 1182 default: break; /* nothing to be done for x86_64_mode_memory and x86_64_mode_none*/ 1183 } 1184 } 1185 } 1186 1187 if (ret) { 1188 ret->ref = NULL; 1189 ret->t = ret_t; 1190 } 1191 1192 return mode; 1193 } 1194 1195 ST_FUNC int classify_x86_64_va_arg(CType *ty) 1196 { 1197 /* This definition must be synced with stdarg.h */ 1198 enum __va_arg_type { 1199 __va_gen_reg, __va_float_reg, __va_stack 1200 }; 1201 int size, align, reg_count; 1202 X86_64_Mode mode = classify_x86_64_arg(ty, NULL, &size, &align, ®_count); 1203 switch (mode) { 1204 default: return __va_stack; 1205 case x86_64_mode_integer: return __va_gen_reg; 1206 case x86_64_mode_sse: return __va_float_reg; 1207 } 1208 } 1209 1210 /* Return the number of registers needed to return the struct, or 0 if 1211 returning via struct pointer. */ 1212 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) 1213 { 1214 int size, align, reg_count; 1215 *ret_align = 1; // Never have to re-align return values for x86-64 1216 *regsize = 8; 1217 return (classify_x86_64_arg(vt, ret, &size, &align, ®_count) != x86_64_mode_memory); 1218 } 1219 820 1220 #define REGN 6 821 1221 static const uint8_t arg_regs[REGN] = { … … 823 1223 }; 824 1224 1225 static int arg_prepare_reg(int idx) { 1226 if (idx == 2 || idx == 3) 1227 /* idx=2: r10, idx=3: r11 */ 1228 return idx + 8; 1229 else 1230 return arg_regs[idx]; 1231 } 1232 825 1233 /* Generate function call. The function address is pushed first, then 826 1234 all the parameters in call order. This functions pops all the … … 828 1236 void gfunc_call(int nb_args) 829 1237 { 830 int size, align, r, args_size, i; 1238 X86_64_Mode mode; 1239 CType type; 1240 int size, align, r, args_size, stack_adjust, i, reg_count; 831 1241 int nb_reg_args = 0; 832 1242 int nb_sse_args = 0; 833 1243 int sse_reg, gen_reg; 834 835 /* calculate the number of integer/float arguments */ 836 args_size = 0; 837 for(i = 0; i < nb_args; i++) { 838 if ((vtop[-i].type.t & VT_BTYPE) == VT_STRUCT) { 839 args_size += type_size(&vtop[-i].type, &align); 840 args_size = (args_size + 7) & ~7; 841 } else if ((vtop[-i].type.t & VT_BTYPE) == VT_LDOUBLE) { 842 args_size += 16; 843 } else if (is_sse_float(vtop[-i].type.t)) { 844 nb_sse_args++; 845 if (nb_sse_args > 8) args_size += 8; 846 } else { 847 nb_reg_args++; 848 if (nb_reg_args > REGN) args_size += 8; 849 } 850 } 1244 char _onstack[nb_args], *onstack = _onstack; 1245 1246 /* calculate the number of integer/float register arguments, remember 1247 arguments to be passed via stack (in onstack[]), and also remember 1248 if we have to align the stack pointer to 16 (onstack[i] == 2). Needs 1249 to be done in a left-to-right pass over arguments. */ 1250 stack_adjust = 0; 1251 for(i = nb_args - 1; i >= 0; i--) { 1252 mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count); 1253 if (mode == x86_64_mode_sse && nb_sse_args + reg_count <= 8) { 1254 nb_sse_args += reg_count; 1255 onstack[i] = 0; 1256 } else if (mode == x86_64_mode_integer && nb_reg_args + reg_count <= REGN) { 1257 nb_reg_args += reg_count; 1258 onstack[i] = 0; 1259 } else if (mode == x86_64_mode_none) { 1260 onstack[i] = 0; 1261 } else { 1262 if (align == 16 && (stack_adjust &= 15)) { 1263 onstack[i] = 2; 1264 stack_adjust = 0; 1265 } else 1266 onstack[i] = 1; 1267 stack_adjust += size; 1268 } 1269 } 1270 1271 if (nb_sse_args && tcc_state->nosse) 1272 tcc_error("SSE disabled but floating point arguments passed"); 1273 1274 /* fetch cpu flag before generating any code */ 1275 if (vtop >= vstack && (vtop->r & VT_VALMASK) == VT_CMP) 1276 gv(RC_INT); 851 1277 852 1278 /* for struct arguments, we need to call memcpy and the function … … 855 1281 gen_reg = nb_reg_args; 856 1282 sse_reg = nb_sse_args; 857 858 /* adjust stack to align SSE boundary */ 859 if (args_size &= 15) { 860 /* fetch cpu flag before the following sub will change the value */ 861 if (vtop >= vstack && (vtop->r & VT_VALMASK) == VT_CMP) 862 gv(RC_INT); 863 864 args_size = 16 - args_size; 865 o(0x48); 866 oad(0xec81, args_size); /* sub $xxx, %rsp */ 867 } 868 869 for(i = 0; i < nb_args; i++) { 870 /* Swap argument to top, it will possibly be changed here, 871 and might use more temps. All arguments must remain on the 872 stack, so that get_reg can correctly evict some of them onto 873 stack. We could use also use a vrott(nb_args) at the end 874 of this loop, but this seems faster. */ 875 SValue tmp = vtop[0]; 876 vtop[0] = vtop[-i]; 877 vtop[-i] = tmp; 878 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { 879 size = type_size(&vtop->type, &align); 880 /* align to stack align size */ 881 size = (size + 7) & ~7; 882 /* allocate the necessary size on stack */ 883 o(0x48); 884 oad(0xec81, size); /* sub $xxx, %rsp */ 885 /* generate structure store */ 886 r = get_reg(RC_INT); 887 orex(1, r, 0, 0x89); /* mov %rsp, r */ 888 o(0xe0 + REG_VALUE(r)); 889 vset(&vtop->type, r | VT_LVAL, 0); 890 vswap(); 891 vstore(); 892 args_size += size; 893 } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { 894 gv(RC_ST0); 895 size = LDOUBLE_SIZE; 896 oad(0xec8148, size); /* sub $xxx, %rsp */ 897 o(0x7cdb); /* fstpt 0(%rsp) */ 898 g(0x24); 899 g(0x00); 900 args_size += size; 901 } else if (is_sse_float(vtop->type.t)) { 902 int j = --sse_reg; 903 if (j >= 8) { 904 gv(RC_FLOAT); 905 o(0x50); /* push $rax */ 906 /* movq %xmm0, (%rsp) */ 907 o(0x04d60f66); 908 o(0x24); 909 args_size += 8; 910 } 911 } else { 912 int j = --gen_reg; 913 /* simple type */ 914 /* XXX: implicit cast ? */ 915 if (j >= REGN) { 916 r = gv(RC_INT); 917 orex(0,r,0,0x50 + REG_VALUE(r)); /* push r */ 918 args_size += 8; 919 } 920 } 921 922 /* And swap the argument back to it's original position. */ 923 tmp = vtop[0]; 924 vtop[0] = vtop[-i]; 925 vtop[-i] = tmp; 1283 args_size = 0; 1284 stack_adjust &= 15; 1285 for (i = 0; i < nb_args;) { 1286 mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count); 1287 if (!onstack[i]) { 1288 ++i; 1289 continue; 1290 } 1291 /* Possibly adjust stack to align SSE boundary. We're processing 1292 args from right to left while allocating happens left to right 1293 (stack grows down), so the adjustment needs to happen _after_ 1294 an argument that requires it. */ 1295 if (stack_adjust) { 1296 o(0x50); /* push %rax; aka sub $8,%rsp */ 1297 args_size += 8; 1298 stack_adjust = 0; 1299 } 1300 if (onstack[i] == 2) 1301 stack_adjust = 1; 1302 1303 vrotb(i+1); 1304 1305 switch (vtop->type.t & VT_BTYPE) { 1306 case VT_STRUCT: 1307 /* allocate the necessary size on stack */ 1308 o(0x48); 1309 oad(0xec81, size); /* sub $xxx, %rsp */ 1310 /* generate structure store */ 1311 r = get_reg(RC_INT); 1312 orex(1, r, 0, 0x89); /* mov %rsp, r */ 1313 o(0xe0 + REG_VALUE(r)); 1314 vset(&vtop->type, r | VT_LVAL, 0); 1315 vswap(); 1316 vstore(); 1317 break; 1318 1319 case VT_LDOUBLE: 1320 gv(RC_ST0); 1321 oad(0xec8148, size); /* sub $xxx, %rsp */ 1322 o(0x7cdb); /* fstpt 0(%rsp) */ 1323 g(0x24); 1324 g(0x00); 1325 break; 1326 1327 case VT_FLOAT: 1328 case VT_DOUBLE: 1329 assert(mode == x86_64_mode_sse); 1330 r = gv(RC_FLOAT); 1331 o(0x50); /* push $rax */ 1332 /* movq %xmmN, (%rsp) */ 1333 o(0xd60f66); 1334 o(0x04 + REG_VALUE(r)*8); 1335 o(0x24); 1336 break; 1337 1338 default: 1339 assert(mode == x86_64_mode_integer); 1340 /* simple type */ 1341 /* XXX: implicit cast ? */ 1342 r = gv(RC_INT); 1343 orex(0,r,0,0x50 + REG_VALUE(r)); /* push r */ 1344 break; 1345 } 1346 args_size += size; 1347 1348 vpop(); 1349 --nb_args; 1350 onstack++; 926 1351 } 927 1352 … … 933 1358 may break these temporary registers. Let's use R10 and R11 934 1359 instead of them */ 935 gen_reg = nb_reg_args;936 sse_reg = nb_sse_args;1360 assert(gen_reg <= REGN); 1361 assert(sse_reg <= 8); 937 1362 for(i = 0; i < nb_args; i++) { 938 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT || 939 (vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { 940 } else if (is_sse_float(vtop->type.t)) { 941 int j = --sse_reg; 942 if (j < 8) { 943 gv(RC_FLOAT); /* only one float register */ 944 /* movaps %xmm0, %xmmN */ 945 o(0x280f); 946 o(0xc0 + (sse_reg << 3)); 947 } 948 } else { 949 int j = --gen_reg; 1363 mode = classify_x86_64_arg(&vtop->type, &type, &size, &align, ®_count); 1364 /* Alter stack entry type so that gv() knows how to treat it */ 1365 vtop->type = type; 1366 if (mode == x86_64_mode_sse) { 1367 if (reg_count == 2) { 1368 sse_reg -= 2; 1369 gv(RC_FRET); /* Use pair load into xmm0 & xmm1 */ 1370 if (sse_reg) { /* avoid redundant movaps %xmm0, %xmm0 */ 1371 /* movaps %xmm0, %xmmN */ 1372 o(0x280f); 1373 o(0xc0 + (sse_reg << 3)); 1374 /* movaps %xmm1, %xmmN */ 1375 o(0x280f); 1376 o(0xc1 + ((sse_reg+1) << 3)); 1377 } 1378 } else { 1379 assert(reg_count == 1); 1380 --sse_reg; 1381 /* Load directly to register */ 1382 gv(RC_XMM0 << sse_reg); 1383 } 1384 } else if (mode == x86_64_mode_integer) { 950 1385 /* simple type */ 951 1386 /* XXX: implicit cast ? */ 952 if (j < REGN) { 953 int d = arg_regs[j]; 954 r = gv(RC_INT); 955 if (j == 2 || j == 3) 956 /* j=2: r10, j=3: r11 */ 957 d = j + 8; 958 orex(1,d,r,0x89); /* mov */ 959 o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d)); 1387 int d; 1388 gen_reg -= reg_count; 1389 r = gv(RC_INT); 1390 d = arg_prepare_reg(gen_reg); 1391 orex(1,d,r,0x89); /* mov */ 1392 o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d)); 1393 if (reg_count == 2) { 1394 d = arg_prepare_reg(gen_reg+1); 1395 orex(1,d,vtop->r2,0x89); /* mov */ 1396 o(0xc0 + REG_VALUE(vtop->r2) * 8 + REG_VALUE(d)); 960 1397 } 961 1398 } 962 1399 vtop--; 963 1400 } 1401 assert(gen_reg == 0); 1402 assert(sse_reg == 0); 964 1403 965 1404 /* We shouldn't have many operands on the stack anymore, but the … … 977 1416 } 978 1417 979 oad(0xb8, nb_sse_args < 8 ? nb_sse_args : 8); /* mov nb_sse_args, %eax */ 1418 if (vtop->type.ref->f.func_type != FUNC_NEW) /* implies FUNC_OLD or FUNC_ELLIPSIS */ 1419 oad(0xb8, nb_sse_args < 8 ? nb_sse_args : 8); /* mov nb_sse_args, %eax */ 980 1420 gcall_or_jmp(0); 981 1421 if (args_size) … … 995 1435 void gfunc_prolog(CType *func_type) 996 1436 { 997 int i, addr, align, size; 998 int param_index, param_addr, reg_param_index, sse_param_index; 1437 X86_64_Mode mode; 1438 int i, addr, align, size, reg_count; 1439 int param_addr = 0, reg_param_index, sse_param_index; 999 1440 Sym *sym; 1000 1441 CType *type; … … 1007 1448 func_ret_sub = 0; 1008 1449 1009 if ( func_type->ref->c== FUNC_ELLIPSIS) {1450 if (sym->f.func_type == FUNC_ELLIPSIS) { 1010 1451 int seen_reg_num, seen_sse_num, seen_stack_size; 1011 1452 seen_reg_num = seen_sse_num = 0; … … 1016 1457 while ((sym = sym->next) != NULL) { 1017 1458 type = &sym->type; 1018 if (is_sse_float(type->t)) {1019 if (seen_sse_num < 8) {1020 seen_sse_num++;1021 } else {1022 seen_stack_size += 8;1023 }1024 } else if ((type->t & VT_BTYPE) == VT_STRUCT) {1025 size = type_size(type, &align);1026 size = (size + 7) & ~7;1027 seen_stack_size += size;1028 } else if ((type->t & VT_BTYPE) == VT_LDOUBLE) { 1029 seen_stack_size += LDOUBLE_SIZE;1030 } else {1031 if (seen_reg_num < REGN) {1032 seen_reg_num++;1033 } else { 1034 seen_stack_size += 8;1035 }1459 mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count); 1460 switch (mode) { 1461 default: 1462 stack_arg: 1463 seen_stack_size = ((seen_stack_size + align - 1) & -align) + size; 1464 break; 1465 1466 case x86_64_mode_integer: 1467 if (seen_reg_num + reg_count > REGN) 1468 goto stack_arg; 1469 seen_reg_num += reg_count; 1470 break; 1471 1472 case x86_64_mode_sse: 1473 if (seen_sse_num + reg_count > 8) 1474 goto stack_arg; 1475 seen_sse_num += reg_count; 1476 break; 1036 1477 } 1037 1478 } … … 1051 1492 for (i = 0; i < 8; i++) { 1052 1493 loc -= 16; 1053 o(0xd60f66); /* movq */ 1054 gen_modrm(7 - i, VT_LOCAL, NULL, loc); 1494 if (!tcc_state->nosse) { 1495 o(0xd60f66); /* movq */ 1496 gen_modrm(7 - i, VT_LOCAL, NULL, loc); 1497 } 1055 1498 /* movq $0, loc+8(%rbp) */ 1056 1499 o(0x85c748); … … 1064 1507 1065 1508 sym = func_type->ref; 1066 param_index = 0;1067 1509 reg_param_index = 0; 1068 1510 sse_param_index = 0; … … 1071 1513 implicit pointer parameter */ 1072 1514 func_vt = sym->type; 1073 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { 1515 mode = classify_x86_64_arg(&func_vt, NULL, &size, &align, ®_count); 1516 if (mode == x86_64_mode_memory) { 1074 1517 push_arg_reg(reg_param_index); 1075 param_addr = loc;1076 1077 1518 func_vc = loc; 1078 param_index++;1079 1519 reg_param_index++; 1080 1520 } … … 1082 1522 while ((sym = sym->next) != NULL) { 1083 1523 type = &sym->type; 1084 size = type_size(type, &align); 1085 size = (size + 7) & ~7; 1086 if (is_sse_float(type->t)) { 1087 if (sse_param_index < 8) { 1524 mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count); 1525 switch (mode) { 1526 case x86_64_mode_sse: 1527 if (tcc_state->nosse) 1528 tcc_error("SSE disabled but floating point arguments used"); 1529 if (sse_param_index + reg_count <= 8) { 1088 1530 /* save arguments passed by register */ 1089 loc -= 8; 1090 o(0xd60f66); /* movq */ 1091 gen_modrm(sse_param_index, VT_LOCAL, NULL, loc); 1531 loc -= reg_count * 8; 1092 1532 param_addr = loc; 1533 for (i = 0; i < reg_count; ++i) { 1534 o(0xd60f66); /* movq */ 1535 gen_modrm(sse_param_index, VT_LOCAL, NULL, param_addr + i*8); 1536 ++sse_param_index; 1537 } 1093 1538 } else { 1539 addr = (addr + align - 1) & -align; 1094 1540 param_addr = addr; 1095 1541 addr += size; 1096 1542 } 1097 sse_param_index++; 1098 1099 } else if ((type->t & VT_BTYPE) == VT_STRUCT || 1100 (type->t & VT_BTYPE) == VT_LDOUBLE) { 1543 break; 1544 1545 case x86_64_mode_memory: 1546 case x86_64_mode_x87: 1547 addr = (addr + align - 1) & -align; 1101 1548 param_addr = addr; 1102 1549 addr += size; 1103 } else { 1104 if (reg_param_index < REGN) { 1550 break; 1551 1552 case x86_64_mode_integer: { 1553 if (reg_param_index + reg_count <= REGN) { 1105 1554 /* save arguments passed by register */ 1106 push_arg_reg(reg_param_index);1555 loc -= reg_count * 8; 1107 1556 param_addr = loc; 1557 for (i = 0; i < reg_count; ++i) { 1558 gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, param_addr + i*8); 1559 ++reg_param_index; 1560 } 1108 1561 } else { 1562 addr = (addr + align - 1) & -align; 1109 1563 param_addr = addr; 1110 addr += 8; 1111 } 1112 reg_param_index++; 1564 addr += size; 1565 } 1566 break; 1567 } 1568 default: break; /* nothing to be done for x86_64_mode_none */ 1113 1569 } 1114 1570 sym_push(sym->v & ~SYM_FIELD, type, 1115 1571 VT_LOCAL | VT_LVAL, param_addr); 1116 param_index++; 1117 } 1572 } 1573 1574 #ifdef CONFIG_TCC_BCHECK 1575 /* leave some room for bound checking code */ 1576 if (tcc_state->do_bounds_check) { 1577 func_bound_offset = lbounds_section->data_offset; 1578 func_bound_ind = ind; 1579 oad(0xb8, 0); /* lbound section pointer */ 1580 o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */ 1581 oad(0xb8, 0); /* call to function */ 1582 } 1583 #endif 1118 1584 } 1119 1585 … … 1123 1589 int v, saved_ind; 1124 1590 1591 #ifdef CONFIG_TCC_BCHECK 1592 if (tcc_state->do_bounds_check 1593 && func_bound_offset != lbounds_section->data_offset) 1594 { 1595 addr_t saved_ind; 1596 addr_t *bounds_ptr; 1597 Sym *sym_data; 1598 1599 /* add end of table info */ 1600 bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); 1601 *bounds_ptr = 0; 1602 1603 /* generate bound local allocation */ 1604 sym_data = get_sym_ref(&char_pointer_type, lbounds_section, 1605 func_bound_offset, lbounds_section->data_offset); 1606 saved_ind = ind; 1607 ind = func_bound_ind; 1608 greloca(cur_text_section, sym_data, ind + 1, R_X86_64_64, 0); 1609 ind = ind + 5 + 3; 1610 gen_static_call(TOK___bound_local_new); 1611 ind = saved_ind; 1612 1613 /* generate bound check local freeing */ 1614 o(0x5250); /* save returned value, if any */ 1615 greloca(cur_text_section, sym_data, ind + 1, R_X86_64_64, 0); 1616 oad(0xb8, 0); /* mov xxx, %rax */ 1617 o(0xc78948); /* mov %rax,%rdi # first arg in %rdi, this must be ptr */ 1618 gen_static_call(TOK___bound_local_delete); 1619 o(0x585a); /* restore returned value, if any */ 1620 } 1621 #endif 1125 1622 o(0xc9); /* leave */ 1126 1623 if (func_ret_sub == 0) { … … 1146 1643 int gjmp(int t) 1147 1644 { 1148 return psym(0xe9, t);1645 return gjmp2(0xe9, t); 1149 1646 } 1150 1647 … … 1162 1659 } 1163 1660 1661 ST_FUNC void gtst_addr(int inv, int a) 1662 { 1663 int v = vtop->r & VT_VALMASK; 1664 if (v == VT_CMP) { 1665 inv ^= (vtop--)->c.i; 1666 a -= ind + 2; 1667 if (a == (char)a) { 1668 g(inv - 32); 1669 g(a); 1670 } else { 1671 g(0x0f); 1672 oad(inv - 16, a - 4); 1673 } 1674 } else if ((v & ~1) == VT_JMP) { 1675 if ((v & 1) != inv) { 1676 gjmp_addr(a); 1677 gsym(vtop->c.i); 1678 } else { 1679 gsym(vtop->c.i); 1680 o(0x05eb); 1681 gjmp_addr(a); 1682 } 1683 vtop--; 1684 } 1685 } 1686 1164 1687 /* generate a test. set 'inv' to invert test. Stack entry is popped */ 1165 int gtst(int inv, int t) 1166 { 1167 int v, *p; 1168 1169 v = vtop->r & VT_VALMASK; 1170 if (v == VT_CMP) { 1688 ST_FUNC int gtst(int inv, int t) 1689 { 1690 int v = vtop->r & VT_VALMASK; 1691 1692 if (nocode_wanted) { 1693 ; 1694 } else if (v == VT_CMP) { 1171 1695 /* fast case : can jump directly since flags are set */ 1172 1696 if (vtop->c.i & 0x100) … … 1180 1704 otherwise if unordered we don't want to jump. */ 1181 1705 vtop->c.i &= ~0x100; 1182 if (!inv == (vtop->c.i != TOK_NE))1706 if (inv == (vtop->c.i == TOK_NE)) 1183 1707 o(0x067a); /* jp +6 */ 1184 1708 else 1185 1709 { 1186 1710 g(0x0f); 1187 t = psym(0x8a, t); /* jp t */1711 t = gjmp2(0x8a, t); /* jp t */ 1188 1712 } 1189 1713 } 1190 1714 g(0x0f); 1191 t = psym((vtop->c.i - 16) ^ inv, t);1715 t = gjmp2((vtop->c.i - 16) ^ inv, t); 1192 1716 } else if (v == VT_JMP || v == VT_JMPI) { 1193 1717 /* && or || optimization */ 1194 1718 if ((v & 1) == inv) { 1195 1719 /* insert vtop->c jump list in t */ 1196 p = &vtop->c.i; 1197 while (*p != 0) 1198 p = (int *)(cur_text_section->data + *p); 1199 *p = t; 1200 t = vtop->c.i; 1720 uint32_t n1, n = vtop->c.i; 1721 if (n) { 1722 while ((n1 = read32le(cur_text_section->data + n))) 1723 n = n1; 1724 write32le(cur_text_section->data + n, t); 1725 t = vtop->c.i; 1726 } 1201 1727 } else { 1202 1728 t = gjmp(t); 1203 1729 gsym(vtop->c.i); 1204 }1205 } else {1206 if (is_float(vtop->type.t) ||1207 (vtop->type.t & VT_BTYPE) == VT_LLONG) {1208 vpushi(0);1209 gen_op(TOK_NE);1210 }1211 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {1212 /* constant jmp optimization */1213 if ((vtop->c.i != 0) != inv)1214 t = gjmp(t);1215 } else {1216 v = gv(RC_INT);1217 orex(0,v,v,0x85);1218 o(0xc0 + REG_VALUE(v) * 9);1219 g(0x0f);1220 t = psym(0x85 ^ inv, t);1221 1730 } 1222 1731 } … … 1240 1749 opc = 0; 1241 1750 gen_op8: 1242 if (cc && (!ll || (int)vtop->c. ll == vtop->c.ll)) {1751 if (cc && (!ll || (int)vtop->c.i == vtop->c.i)) { 1243 1752 /* constant case */ 1244 1753 vswap(); … … 1359 1868 1360 1869 /* generate a floating point operation 'v = t1 op t2' instruction. The 1361 two operands are guarante d to have the same floating point type */1870 two operands are guaranteed to have the same floating point type */ 1362 1871 /* XXX: need to use ST1 too */ 1363 1872 void gen_opf(int op) … … 1401 1910 if (swapped) 1402 1911 o(0xc9d9); /* fxch %st(1) */ 1403 o(0xe9da); /* fucompp */ 1912 if (op == TOK_EQ || op == TOK_NE) 1913 o(0xe9da); /* fucompp */ 1914 else 1915 o(0xd9de); /* fcompp */ 1404 1916 o(0xe0df); /* fnstsw %ax */ 1405 1917 if (op == TOK_EQ) { … … 1445 1957 } 1446 1958 ft = vtop->type.t; 1447 fc = vtop->c. ul;1959 fc = vtop->c.i; 1448 1960 o(0xde); /* fxxxp %st, %st(1) */ 1449 1961 o(0xc1 + (a << 3)); … … 1454 1966 /* if saved lvalue, then we must reload it */ 1455 1967 r = vtop->r; 1456 fc = vtop->c. ul;1968 fc = vtop->c.i; 1457 1969 if ((r & VT_VALMASK) == VT_LLOCAL) { 1458 1970 SValue v1; … … 1460 1972 v1.type.t = VT_PTR; 1461 1973 v1.r = VT_LOCAL | VT_LVAL; 1462 v1.c. ul= fc;1974 v1.c.i = fc; 1463 1975 load(r, &v1); 1464 1976 fc = 0; … … 1478 1990 1479 1991 if (swapped) { 1480 o(0x7e0ff3); /* movq */ 1481 gen_modrm(1, r, vtop->sym, fc); 1482 1483 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) { 1484 o(0x66); 1485 } 1486 o(0x2e0f); /* ucomisd %xmm0, %xmm1 */ 1487 o(0xc8); 1992 gv(RC_FLOAT); 1993 vswap(); 1994 } 1995 assert(!(vtop[-1].r & VT_LVAL)); 1996 1997 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) 1998 o(0x66); 1999 if (op == TOK_EQ || op == TOK_NE) 2000 o(0x2e0f); /* ucomisd */ 2001 else 2002 o(0x2f0f); /* comisd */ 2003 2004 if (vtop->r & VT_LVAL) { 2005 gen_modrm(vtop[-1].r, r, vtop->sym, fc); 1488 2006 } else { 1489 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) { 1490 o(0x66); 1491 } 1492 o(0x2e0f); /* ucomisd */ 1493 gen_modrm(0, r, vtop->sym, fc); 2007 o(0xc0 + REG_VALUE(vtop[0].r) + REG_VALUE(vtop[-1].r)*8); 1494 2008 } 1495 2009 … … 1498 2012 vtop->c.i = op | 0x100; 1499 2013 } else { 1500 /* no memory reference possible for long double operations */ 1501 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { 1502 load(TREG_XMM0, vtop); 1503 swapped = !swapped; 1504 } 2014 assert((vtop->type.t & VT_BTYPE) != VT_LDOUBLE); 1505 2015 switch(op) { 1506 2016 default: … … 1519 2029 } 1520 2030 ft = vtop->type.t; 1521 fc = vtop->c.ul; 1522 if ((ft & VT_BTYPE) == VT_LDOUBLE) { 1523 o(0xde); /* fxxxp %st, %st(1) */ 1524 o(0xc1 + (a << 3)); 2031 fc = vtop->c.i; 2032 assert((ft & VT_BTYPE) != VT_LDOUBLE); 2033 2034 r = vtop->r; 2035 /* if saved lvalue, then we must reload it */ 2036 if ((vtop->r & VT_VALMASK) == VT_LLOCAL) { 2037 SValue v1; 2038 r = get_reg(RC_INT); 2039 v1.type.t = VT_PTR; 2040 v1.r = VT_LOCAL | VT_LVAL; 2041 v1.c.i = fc; 2042 load(r, &v1); 2043 fc = 0; 2044 } 2045 2046 assert(!(vtop[-1].r & VT_LVAL)); 2047 if (swapped) { 2048 assert(vtop->r & VT_LVAL); 2049 gv(RC_FLOAT); 2050 vswap(); 2051 } 2052 2053 if ((ft & VT_BTYPE) == VT_DOUBLE) { 2054 o(0xf2); 1525 2055 } else { 1526 /* if saved lvalue, then we must reload it */ 1527 r = vtop->r; 1528 if ((r & VT_VALMASK) == VT_LLOCAL) { 1529 SValue v1; 1530 r = get_reg(RC_INT); 1531 v1.type.t = VT_PTR; 1532 v1.r = VT_LOCAL | VT_LVAL; 1533 v1.c.ul = fc; 1534 load(r, &v1); 1535 fc = 0; 1536 } 1537 if (swapped) { 1538 /* movq %xmm0,%xmm1 */ 1539 o(0x7e0ff3); 1540 o(0xc8); 1541 load(TREG_XMM0, vtop); 1542 /* subsd %xmm1,%xmm0 (f2 0f 5c c1) */ 1543 if ((ft & VT_BTYPE) == VT_DOUBLE) { 1544 o(0xf2); 1545 } else { 1546 o(0xf3); 1547 } 1548 o(0x0f); 1549 o(0x58 + a); 1550 o(0xc1); 1551 } else { 1552 if ((ft & VT_BTYPE) == VT_DOUBLE) { 1553 o(0xf2); 1554 } else { 1555 o(0xf3); 1556 } 1557 o(0x0f); 1558 o(0x58 + a); 1559 gen_modrm(0, r, vtop->sym, fc); 1560 } 1561 } 2056 o(0xf3); 2057 } 2058 o(0x0f); 2059 o(0x58 + a); 2060 2061 if (vtop->r & VT_LVAL) { 2062 gen_modrm(vtop[-1].r, r, vtop->sym, fc); 2063 } else { 2064 o(0xc0 + REG_VALUE(vtop[0].r) + REG_VALUE(vtop[-1].r)*8); 2065 } 2066 1562 2067 vtop--; 1563 2068 } … … 1594 2099 vtop->r = TREG_ST0; 1595 2100 } else { 1596 save_reg(TREG_XMM0);2101 int r = get_reg(RC_FLOAT); 1597 2102 gv(RC_INT); 1598 o(0xf2 + ((t & VT_BTYPE) == VT_FLOAT ));2103 o(0xf2 + ((t & VT_BTYPE) == VT_FLOAT?1:0)); 1599 2104 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == 1600 2105 (VT_INT | VT_UNSIGNED) || … … 1603 2108 } 1604 2109 o(0x2a0f); 1605 o(0xc0 + (vtop->r & VT_VALMASK) ); /* cvtsi2sd */1606 vtop->r = TREG_XMM0;2110 o(0xc0 + (vtop->r & VT_VALMASK) + REG_VALUE(r)*8); /* cvtsi2sd */ 2111 vtop->r = r; 1607 2112 } 1608 2113 } … … 1616 2121 bt = ft & VT_BTYPE; 1617 2122 tbt = t & VT_BTYPE; 1618 2123 1619 2124 if (bt == VT_FLOAT) { 1620 2125 gv(RC_FLOAT); 1621 2126 if (tbt == VT_DOUBLE) { 1622 o(0xc0140f); /* unpcklps */ 1623 o(0xc05a0f); /* cvtps2pd */ 2127 o(0x140f); /* unpcklps */ 2128 o(0xc0 + REG_VALUE(vtop->r)*9); 2129 o(0x5a0f); /* cvtps2pd */ 2130 o(0xc0 + REG_VALUE(vtop->r)*9); 1624 2131 } else if (tbt == VT_LDOUBLE) { 2132 save_reg(RC_ST0); 1625 2133 /* movss %xmm0,-0x10(%rsp) */ 1626 o(0x44110ff3); 2134 o(0x110ff3); 2135 o(0x44 + REG_VALUE(vtop->r)*8); 1627 2136 o(0xf024); 1628 2137 o(0xf02444d9); /* flds -0x10(%rsp) */ … … 1632 2141 gv(RC_FLOAT); 1633 2142 if (tbt == VT_FLOAT) { 1634 o(0xc0140f66); /* unpcklpd */ 1635 o(0xc05a0f66); /* cvtpd2ps */ 2143 o(0x140f66); /* unpcklpd */ 2144 o(0xc0 + REG_VALUE(vtop->r)*9); 2145 o(0x5a0f66); /* cvtpd2ps */ 2146 o(0xc0 + REG_VALUE(vtop->r)*9); 1636 2147 } else if (tbt == VT_LDOUBLE) { 2148 save_reg(RC_ST0); 1637 2149 /* movsd %xmm0,-0x10(%rsp) */ 1638 o(0x44110ff2); 2150 o(0x110ff2); 2151 o(0x44 + REG_VALUE(vtop->r)*8); 1639 2152 o(0xf024); 1640 2153 o(0xf02444dd); /* fldl -0x10(%rsp) */ … … 1642 2155 } 1643 2156 } else { 2157 int r; 1644 2158 gv(RC_ST0); 2159 r = get_reg(RC_FLOAT); 1645 2160 if (tbt == VT_DOUBLE) { 1646 2161 o(0xf0245cdd); /* fstpl -0x10(%rsp) */ 1647 2162 /* movsd -0x10(%rsp),%xmm0 */ 1648 o(0x44100ff2); 2163 o(0x100ff2); 2164 o(0x44 + REG_VALUE(r)*8); 1649 2165 o(0xf024); 1650 vtop->r = TREG_XMM0;2166 vtop->r = r; 1651 2167 } else if (tbt == VT_FLOAT) { 1652 2168 o(0xf0245cd9); /* fstps -0x10(%rsp) */ 1653 2169 /* movss -0x10(%rsp),%xmm0 */ 1654 o(0x44100ff3); 2170 o(0x100ff3); 2171 o(0x44 + REG_VALUE(r)*8); 1655 2172 o(0xf024); 1656 vtop->r = TREG_XMM0;2173 vtop->r = r; 1657 2174 } 1658 2175 } … … 1685 2202 } 1686 2203 orex(size == 8, r, 0, 0x2c0f); /* cvttss2si or cvttsd2si */ 1687 o(0xc0 + (REG_VALUE(r) << 3));2204 o(0xc0 + REG_VALUE(vtop->r) + REG_VALUE(r)*8); 1688 2205 vtop->r = r; 1689 2206 } … … 1695 2212 vtop--; 1696 2213 } 2214 2215 /* Save the stack pointer onto the stack and return the location of its address */ 2216 ST_FUNC void gen_vla_sp_save(int addr) { 2217 /* mov %rsp,addr(%rbp)*/ 2218 gen_modrm64(0x89, TREG_RSP, VT_LOCAL, NULL, addr); 2219 } 2220 2221 /* Restore the SP from a location on the stack */ 2222 ST_FUNC void gen_vla_sp_restore(int addr) { 2223 gen_modrm64(0x8b, TREG_RSP, VT_LOCAL, NULL, addr); 2224 } 2225 2226 #ifdef TCC_TARGET_PE 2227 /* Save result of gen_vla_alloc onto the stack */ 2228 ST_FUNC void gen_vla_result(int addr) { 2229 /* mov %rax,addr(%rbp)*/ 2230 gen_modrm64(0x89, TREG_RAX, VT_LOCAL, NULL, addr); 2231 } 2232 #endif 2233 2234 /* Subtract from the stack pointer, and push the resulting value onto the stack */ 2235 ST_FUNC void gen_vla_alloc(CType *type, int align) { 2236 #ifdef TCC_TARGET_PE 2237 /* alloca does more than just adjust %rsp on Windows */ 2238 vpush_global_sym(&func_old_type, TOK_alloca); 2239 vswap(); /* Move alloca ref past allocation size */ 2240 gfunc_call(1); 2241 #else 2242 int r; 2243 r = gv(RC_INT); /* allocation size */ 2244 /* sub r,%rsp */ 2245 o(0x2b48); 2246 o(0xe0 | REG_VALUE(r)); 2247 /* We align to 16 bytes rather than align */ 2248 /* and ~15, %rsp */ 2249 o(0xf0e48348); 2250 vpop(); 2251 #endif 2252 } 2253 1697 2254 1698 2255 /* end of x86-64 code generator */
Note:
See TracChangeset
for help on using the changeset viewer.