- configure * use aarch64 instead of arm64 - Makefile * rename the custom include file to "config-extra.mak" * Also avoid "rm -r /*" if $(tccdir) is empty - pp/Makefile * fix .expect generation with gcc - tcc.h * cleanup #defines for _MSC_VER - tccgen.c: * fix const-propagation for &,| * fix anonymous named struct (ms-extension) and enable -fms-extension by default - i386-gen.c * clear VT_DEFSIGN - x86_64-gen.c/win64: * fix passing structs in registers * fix alloca (need to keep "func_scratch" below each alloca area on stack) (This allows to compile a working gnu-make on win64) - tccpp.c * alternative approach to 37999a4fbf3487b363fd0c2f9b7ab622401b202a This is to avoid some slowdown with ## token pasting. * get_tok_str() : return <eof> for TOK_EOF * -funsigned-char: apply to "string" literals as well - tccpe/tools.c: -impdef: support both 32 and 64 bit dlls anyway
Unified · Split
| @@ -151,8 +151,8 @@ DEF-win += -DCONFIG_TCCDIR="\"$(tccdir)/win32\"" · 150 unmodified lines | |||
| 151 | endif | 151 | endif |
| 152 | endif | 152 | endif |
| 153 | 153 | ||
| 154 | # include custom cross-compiler configuration (see make help) | 154 | # include custom configuration (see make help) |
| 155 | -include config-cross.mak | 155 | -include config-extra.mak |
| 156 | 156 | ||
| 157 | CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c | 157 | CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c |
| 158 | CORE_FILES += tcc.h config.h libtcc.h tcctok.h | 158 | CORE_FILES += tcc.h config.h libtcc.h tcctok.h |
| @@ -318,7 +318,7 @@ install-win : INSTALL = cp · 159 unmodified lines | |||
| 318 | 318 | ||
| 319 | # uninstall on windows | 319 | # uninstall on windows |
| 320 | uninstall-win: | 320 | uninstall-win: |
| 321 | rm -r "$(tccdir)/"* | 321 | rm -r "$(tccdir)" |
| 322 | 322 | ||
| 323 | # -------------------------------------------------------------------------- | 323 | # -------------------------------------------------------------------------- |
| 324 | # other stuff | 324 | # other stuff |
| @@ -374,19 +374,24 @@ help: · 49 unmodified lines | |||
| 374 | @echo " build one specific cross compiler for 'TARGET', as in" | 374 | @echo " build one specific cross compiler for 'TARGET', as in" |
| 375 | @echo " $(TCC_X)" | 375 | @echo " $(TCC_X)" |
| 376 | @echo "" | 376 | @echo "" |
| 377 | @echo "Cross compiler configuration:" | 377 | @echo "Custom configuration:" |
| 378 | @echo " make will read custom configuration for cross compilers from a file" | 378 | @echo " The makefile includes a file 'config-extra.mak' if it is present." |
| 379 | @echo " 'config-cross.mak' if present. For example for a windows->i386-linux" | 379 | @echo " This file may contain some custom configuration. For example:" |
| 380 | @echo " cross-compiler that expects the linux files in <tccdir>/i386-linux:" | 380 | @echo "" |
| 381 | @echo " NATIVE_DEFINES += -D..." | ||
| 381 | @echo "" | 382 | @echo "" |
| 382 | @echo " ROOT-i386 = {B}/i386-linux" | 383 | @echo " Or for example to configure the search paths for a cross-compiler" |
| 383 | @echo " CRT-i386 = {B}/i386-linux/usr/lib" | 384 | @echo " that expects the linux files in <tccdir>/i386-linux:" |
| 384 | @echo " LIB-i386 = {B}/i386-linux/lib:{B}/i386-linux/usr/lib" | 385 | @echo "" |
| 385 | @echo " INC-i386 = {B}/lib/include:{B}/i386-linux/usr/include" | 386 | @echo " ROOT-i386 = {B}/i386-linux" |
| 386 | @echo " DEF-i386 += -D__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__" | ||
| 387 | @echo "" | 391 | @echo "" |
| 388 | @echo "Other supported make targets:" | 392 | @echo "Other supported make targets:" |
| 389 | @echo " install install-strip test tags ETAGS tar clean distclean help" | 393 | @echo " install install-strip test tags ETAGS tar clean distclean help" |
| 394 | @echo "" | ||
| 390 | 395 | ||
| 391 | # -------------------------------------------------------------------------- | 396 | # -------------------------------------------------------------------------- |
| 392 | endif # ($(INCLUDED),no) | 397 | endif # ($(INCLUDED),no) |
| @@ -161,7 +161,7 @@ fi · 160 unmodified lines | |||
| 161 | 161 | ||
| 162 | case "$cpu" in | 162 | case "$cpu" in |
| 163 | x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386) | 163 | x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386) |
| 164 | cpu="x86" | 164 | cpu="i386" |
| 165 | ;; | 165 | ;; |
| 166 | x86_64|amd64|x86-64) | 166 | x86_64|amd64|x86-64) |
| 167 | cpu="x86_64" | 167 | cpu="x86_64" |
| @@ -184,7 +184,7 @@ case "$cpu" in · 16 unmodified lines | |||
| 184 | cpu="arm" | 184 | cpu="arm" |
| 185 | ;; | 185 | ;; |
| 186 | aarch64) | 186 | aarch64) |
| 187 | cpu="arm64" | 187 | cpu="aarch64" |
| 188 | ;; | 188 | ;; |
| 189 | alpha) | 189 | alpha) |
| 190 | cpu="alpha" | 190 | cpu="alpha" |
| @@ -301,7 +301,7 @@ Advanced options (experts only): · 110 unmodified lines | |||
| 301 | --disable-static make libtcc.so instead of libtcc.a | 301 | --disable-static make libtcc.so instead of libtcc.a |
| 302 | --enable-static make libtcc.a instead of libtcc.dll (win32) | 302 | --enable-static make libtcc.a instead of libtcc.dll (win32) |
| 303 | --disable-rpath disable use of -rpath with the above | 303 | --disable-rpath disable use of -rpath with the above |
| 304 | --with-libgcc use libgcc_s.so.1 instead of libtcc1.a in dynamic link | 304 | --with-libgcc use libgcc_s.so.1 instead of libtcc1.a |
| 305 | --enable-mingw32 build windows version on linux with mingw32 | 305 | --enable-mingw32 build windows version on linux with mingw32 |
| 306 | --enable-cross build cross compilers | 306 | --enable-cross build cross compilers |
| 307 | --with-selinux use mmap for executable memory (with tcc -run) | 307 | --with-selinux use mmap for executable memory (with tcc -run) |
| @@ -340,7 +340,7 @@ if test -z "$cross_prefix" ; then · 32 unmodified lines | |||
| 340 | fi | 340 | fi |
| 341 | 341 | ||
| 342 | if test -z "$triplet"; then | 342 | if test -z "$triplet"; then |
| 343 | if test $cpu = "x86_64" -o $cpu = "arm64" ; then | 343 | if test $cpu = "x86_64" -o $cpu = "aarch64" ; then |
| 344 | if test -f "/usr/lib64/crti.o" ; then | 344 | if test -f "/usr/lib64/crti.o" ; then |
| 345 | tcc_lddir="lib64" | 345 | tcc_lddir="lib64" |
| 346 | fi | 346 | fi |
| @@ -473,13 +473,11 @@ print_mak_int TCC_CPU_VERSION "$cpuver" · 126 unmodified lines | |||
| 473 | 473 | ||
| 474 | echo "#define GCC_MAJOR $gcc_major" >> $TMPH | 474 | echo "#define GCC_MAJOR $gcc_major" >> $TMPH |
| 475 | echo "#define GCC_MINOR $gcc_minor" >> $TMPH | 475 | echo "#define GCC_MINOR $gcc_minor" >> $TMPH |
| 476 | 476 | if test "$cpu" = "aarch64" ; then | |
| 477 | if test "$cpu" = "x86" ; then | 477 | echo "ARCH=arm64" >> config.mak |
| 478 | echo "ARCH=i386" >> config.mak | ||
| 479 | else | 478 | else |
| 480 | echo "ARCH=$cpu" >> config.mak | 479 | echo "ARCH=$cpu" >> config.mak |
| 481 | fi | 480 | fi |
| 482 | |||
| 483 | echo "TARGETOS=$targetos" >> config.mak | 481 | echo "TARGETOS=$targetos" >> config.mak |
| 484 | 482 | ||
| 485 | for v in $confvars ; do | 483 | for v in $confvars ; do |
| @@ -210,7 +210,7 @@ ST_FUNC void load(int r, SValue *sv) · 209 unmodified lines | |||
| 210 | #endif | 210 | #endif |
| 211 | 211 | ||
| 212 | fr = sv->r; | 212 | fr = sv->r; |
| 213 | ft = sv->type.t; | 213 | ft = sv->type.t & ~VT_DEFSIGN; |
| 214 | fc = sv->c.i; | 214 | fc = sv->c.i; |
| 215 | 215 | ||
| 216 | ft &= ~(VT_VOLATILE | VT_CONSTANT); | 216 | ft &= ~(VT_VOLATILE | VT_CONSTANT); |
| @@ -27,10 +27,6 @@ p2: · 26 unmodified lines | |||
| 27 | 27 | ||
| 28 | sub %rax,%rsp | 28 | sub %rax,%rsp |
| 29 | mov %rsp,%rax | 29 | mov %rsp,%rax |
| 30 | #ifdef TCC_TARGET_PE | ||
| 31 | add $32,%rax | ||
| 32 | #endif | ||
| 33 | |||
| 34 | p3: | 30 | p3: |
| 35 | push %rdx | 31 | push %rdx |
| 36 | ret | 32 | ret |
| @@ -264,7 +264,7 @@ struct mem_debug_header { · 263 unmodified lines | |||
| 264 | int line_num; | 264 | int line_num; |
| 265 | char file_name[MEM_DEBUG_FILE_LEN + 1]; | 265 | char file_name[MEM_DEBUG_FILE_LEN + 1]; |
| 266 | unsigned magic2; | 266 | unsigned magic2; |
| 267 | __attribute__((aligned(16))) unsigned magic3; | 267 | ALIGNED(16) unsigned magic3; |
| 268 | }; | 268 | }; |
| 269 | 269 | ||
| 270 | typedef struct mem_debug_header mem_debug_header_t; | 270 | typedef struct mem_debug_header mem_debug_header_t; |
| @@ -581,10 +581,7 @@ ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen) · 310 unmodified lines | |||
| 581 | bf->buf_end = bf->buffer + initlen; | 581 | bf->buf_end = bf->buffer + initlen; |
| 582 | bf->buf_end[0] = CH_EOB; /* put eob symbol */ | 582 | bf->buf_end[0] = CH_EOB; /* put eob symbol */ |
| 583 | pstrcpy(bf->filename, sizeof(bf->filename), filename); | 583 | pstrcpy(bf->filename, sizeof(bf->filename), filename); |
| 584 | pstrcpy(bf->filename2, sizeof(bf->filename2), filename); | 584 | bf->true_filename = bf->filename; |
| 585 | #ifdef _WIN32 | ||
| 586 | normalize_slashes(bf->filename); | ||
| 587 | #endif | ||
| 588 | bf->line_num = 1; | 585 | bf->line_num = 1; |
| 589 | bf->ifdef_stack_ptr = s1->ifdef_stack_ptr; | 586 | bf->ifdef_stack_ptr = s1->ifdef_stack_ptr; |
| 590 | bf->fd = -1; | 587 | bf->fd = -1; |
| @@ -599,6 +596,8 @@ ST_FUNC void tcc_close(void) · 8 unmodified lines | |||
| 599 | close(bf->fd); | 596 | close(bf->fd); |
| 600 | total_lines += bf->line_num; | 597 | total_lines += bf->line_num; |
| 601 | } | 598 | } |
| 599 | if (bf->true_filename != bf->filename) | ||
| 600 | tcc_free(bf->true_filename); | ||
| 602 | file = bf->prev; | 601 | file = bf->prev; |
| 603 | tcc_free(bf); | 602 | tcc_free(bf); |
| 604 | } | 603 | } |
| @@ -615,8 +614,10 @@ ST_FUNC int tcc_open(TCCState *s1, const char *filename) · 10 unmodified lines | |||
| 615 | (int)(s1->include_stack_ptr - s1->include_stack), "", filename); | 614 | (int)(s1->include_stack_ptr - s1->include_stack), "", filename); |
| 616 | if (fd < 0) | 615 | if (fd < 0) |
| 617 | return -1; | 616 | return -1; |
| 618 | |||
| 619 | tcc_open_bf(s1, filename, 0); | 617 | tcc_open_bf(s1, filename, 0); |
| 618 | #ifdef _WIN32 | ||
| 619 | normalize_slashes(file->filename); | ||
| 620 | #endif | ||
| 620 | file->fd = fd; | 621 | file->fd = fd; |
| 621 | return fd; | 622 | return fd; |
| 622 | } | 623 | } |
| @@ -737,6 +738,7 @@ LIBTCCAPI TCCState *tcc_new(void) · 114 unmodified lines | |||
| 737 | s->alacarte_link = 1; | 738 | s->alacarte_link = 1; |
| 738 | s->nocommon = 1; | 739 | s->nocommon = 1; |
| 739 | s->warn_implicit_function_declaration = 1; | 740 | s->warn_implicit_function_declaration = 1; |
| 741 | s->ms_extensions = 1; | ||
| 740 | 742 | ||
| 741 | #ifdef CHAR_IS_UNSIGNED | 743 | #ifdef CHAR_IS_UNSIGNED |
| 742 | s->char_is_unsigned = 1; | 744 | s->char_is_unsigned = 1; |
| @@ -41,10 +41,11 @@ · 40 unmodified lines | |||
| 41 | # include <dlfcn.h> | 41 | # include <dlfcn.h> |
| 42 | # endif | 42 | # endif |
| 43 | /* XXX: need to define this to use them in non ISOC99 context */ | 43 | /* XXX: need to define this to use them in non ISOC99 context */ |
| 44 | extern float strtof (const char *__nptr, char **__endptr); | 44 | extern float strtof (const char *__nptr, char **__endptr); |
| 45 | extern long double strtold (const char *__nptr, char **__endptr); | 45 | extern long double strtold (const char *__nptr, char **__endptr); |
| 46 | #endif | ||
| 46 | 47 | ||
| 47 | #else /* on _WIN32: */ | 48 | #ifdef _WIN32 |
| 48 | # include <windows.h> | 49 | # include <windows.h> |
| 49 | # include <io.h> /* open, close etc. */ | 50 | # include <io.h> /* open, close etc. */ |
| 50 | # include <direct.h> /* getcwd */ | 51 | # include <direct.h> /* getcwd */ |
| @@ -52,7 +53,6 @@ · 1 unmodified line | |||
| 52 | # include <stdint.h> | 53 | # include <stdint.h> |
| 53 | # endif | 54 | # endif |
| 54 | # define inline __inline | 55 | # define inline __inline |
| 55 | # define inp next_inp /* inp is an intrinsic on msvc */ | ||
| 56 | # define snprintf _snprintf | 56 | # define snprintf _snprintf |
| 57 | # define vsnprintf _vsnprintf | 57 | # define vsnprintf _vsnprintf |
| 58 | # ifndef __GNUC__ | 58 | # ifndef __GNUC__ |
| @@ -65,6 +65,7 @@ · 6 unmodified lines | |||
| 65 | # define LIBTCCAPI __declspec(dllexport) | 65 | # define LIBTCCAPI __declspec(dllexport) |
| 66 | # define PUB_FUNC LIBTCCAPI | 66 | # define PUB_FUNC LIBTCCAPI |
| 67 | # endif | 67 | # endif |
| 68 | # define inp next_inp /* inp is an intrinsic on msvc/mingw */ | ||
| 68 | # ifdef _MSC_VER | 69 | # ifdef _MSC_VER |
| 69 | # pragma warning (disable : 4244) // conversion from 'uint64_t' to 'int', possible loss of data | 70 | # pragma warning (disable : 4244) // conversion from 'uint64_t' to 'int', possible loss of data |
| 70 | # pragma warning (disable : 4267) // conversion from 'size_t' to 'int', possible loss of data | 71 | # pragma warning (disable : 4267) // conversion from 'size_t' to 'int', possible loss of data |
| @@ -72,9 +73,6 @@ · 1 unmodified line | |||
| 72 | # pragma warning (disable : 4018) // signed/unsigned mismatch | 73 | # pragma warning (disable : 4018) // signed/unsigned mismatch |
| 73 | # pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned | 74 | # pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned |
| 74 | # define ssize_t intptr_t | 75 | # define ssize_t intptr_t |
| 75 | # define __attribute__(x) __declspec x | ||
| 76 | # define aligned align | ||
| 77 | # else | ||
| 78 | # endif | 76 | # endif |
| 79 | # undef CONFIG_TCC_STATIC | 77 | # undef CONFIG_TCC_STATIC |
| 80 | #endif | 78 | #endif |
| @@ -83,12 +81,12 @@ · 2 unmodified lines | |||
| 83 | # define O_BINARY 0 | 81 | # define O_BINARY 0 |
| 84 | #endif | 82 | #endif |
| 85 | 83 | ||
| 86 | #ifdef __GNUC__ | 84 | #ifdef _MSC_VER |
| 87 | # define NORETURN __attribute__ ((noreturn)) | ||
| 88 | #elif defined _MSC_VER | ||
| 89 | # define NORETURN __declspec(noreturn) | 85 | # define NORETURN __declspec(noreturn) |
| 86 | # define ALIGNED(x) __declspec(align(x)) | ||
| 90 | #else | 87 | #else |
| 91 | # define NORETURN | 88 | # define NORETURN __attribute__((noreturn)) |
| 89 | # define ALIGNED(x) __attribute__((aligned(x))) | ||
| 92 | #endif | 90 | #endif |
| 93 | 91 | ||
| 94 | #ifdef _WIN32 | 92 | #ifdef _WIN32 |
| @@ -540,7 +538,7 @@ typedef struct BufferedFile { · 445 unmodified lines | |||
| 540 | int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */ | 538 | int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */ |
| 541 | int include_next_index; /* next search path */ | 539 | int include_next_index; /* next search path */ |
| 542 | char filename[1024]; /* filename */ | 540 | char filename[1024]; /* filename */ |
| 543 | char filename2[1024]; /* filename not modified by # line directive */ | 541 | char *true_filename; /* filename not modified by # line directive */ |
| 544 | unsigned char unget[4]; | 542 | unsigned char unget[4]; |
| 545 | unsigned char buffer[1]; /* extra size for CH_EOB char */ | 543 | unsigned char buffer[1]; /* extra size for CH_EOB char */ |
| 546 | } BufferedFile; | 544 | } BufferedFile; |
| @@ -1752,8 +1752,8 @@ static void gen_opic(int op) · 1751 unmodified lines | |||
| 1752 | vtop--; | 1752 | vtop--; |
| 1753 | } else if (!const_wanted && | 1753 | } else if (!const_wanted && |
| 1754 | c2 && ((l2 == 0 && (op == '&' || op == '*')) || | 1754 | c2 && ((l2 == 0 && (op == '&' || op == '*')) || |
| 1755 | (l2 == -1 && op == '|') || | 1755 | (op == '|' && |
| 1756 | (l2 == 0xffffffff && t2 != VT_LLONG && op == '|') || | 1756 | (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))) || |
| 1757 | (l2 == 1 && (op == '%' || op == TOK_UMOD)))) { | 1757 | (l2 == 1 && (op == '%' || op == TOK_UMOD)))) { |
| 1758 | /* treat (x & 0), (x * 0), (x | -1) and (x % 1) as constant */ | 1758 | /* treat (x & 0), (x * 0), (x | -1) and (x % 1) as constant */ |
| 1759 | if (l2 == 1) | 1759 | if (l2 == 1) |
| @@ -1767,7 +1767,7 @@ static void gen_opic(int op) · 7 unmodified lines | |||
| 1767 | op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) && | 1767 | op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) && |
| 1768 | l2 == 0) || | 1768 | l2 == 0) || |
| 1769 | (op == '&' && | 1769 | (op == '&' && |
| 1770 | l2 == -1))) { | 1770 | (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))))) { |
| 1771 | /* filter out NOP operations like x*1, x-0, x&-1... */ | 1771 | /* filter out NOP operations like x*1, x-0, x&-1... */ |
| 1772 | vtop--; | 1772 | vtop--; |
| 1773 | } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) { | 1773 | } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) { |
| @@ -1817,6 +1817,10 @@ static void gen_opif(int op) · 43 unmodified lines | |||
| 1817 | { | 1817 | { |
| 1818 | int c1, c2; | 1818 | int c1, c2; |
| 1819 | SValue *v1, *v2; | 1819 | SValue *v1, *v2; |
| 1820 | #if defined _MSC_VER && defined _AMD64_ | ||
| 1821 | /* avoid bad optimization with f1 -= f2 for f1:-0.0, f2:0.0 */ | ||
| 1822 | volatile | ||
| 1823 | #endif | ||
| 1820 | long double f1, f2; | 1824 | long double f1, f2; |
| 1821 | 1825 | ||
| 1822 | v1 = vtop - 1; | 1826 | v1 = vtop - 1; |
| @@ -3497,7 +3501,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 1674 unmodified lines | |||
| 3497 | if (v < TOK_IDENT) | 3501 | if (v < TOK_IDENT) |
| 3498 | expect("struct/union/enum name"); | 3502 | expect("struct/union/enum name"); |
| 3499 | s = struct_find(v); | 3503 | s = struct_find(v); |
| 3500 | if (s && (s->scope == local_scope || (tok != '{' && tok != ';'))) { | 3504 | if (s && (s->scope == local_scope || tok != '{')) { |
| 3501 | if (s->type.t != a) | 3505 | if (s->type.t != a) |
| 3502 | tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); | 3506 | tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); |
| 3503 | goto do_decl; | 3507 | goto do_decl; |
| @@ -4381,6 +4385,8 @@ ST_FUNC void unary(void) · 877 unmodified lines | |||
| 4381 | case TOK_STR: | 4385 | case TOK_STR: |
| 4382 | /* string parsing */ | 4386 | /* string parsing */ |
| 4383 | t = VT_BYTE; | 4387 | t = VT_BYTE; |
| 4388 | if (tcc_state->char_is_unsigned) | ||
| 4389 | t = VT_BYTE | VT_UNSIGNED; | ||
| 4384 | str_init: | 4390 | str_init: |
| 4385 | if (tcc_state->warn_write_strings) | 4391 | if (tcc_state->warn_write_strings) |
| 4386 | t |= VT_CONSTANT; | 4392 | t |= VT_CONSTANT; |
| @@ -1547,11 +1547,7 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp) · 1546 unmodified lines | |||
| 1547 | IMAGE_DOS_HEADER dh; | 1547 | IMAGE_DOS_HEADER dh; |
| 1548 | IMAGE_FILE_HEADER ih; | 1548 | IMAGE_FILE_HEADER ih; |
| 1549 | DWORD sig, ref, addr, ptr, namep; | 1549 | DWORD sig, ref, addr, ptr, namep; |
| 1550 | #ifdef TCC_TARGET_X86_64 | 1550 | |
| 1551 | IMAGE_OPTIONAL_HEADER64 oh; | ||
| 1552 | #else | ||
| 1553 | IMAGE_OPTIONAL_HEADER32 oh; | ||
| 1554 | #endif | ||
| 1555 | int pef_hdroffset, opt_hdroffset, sec_hdroffset; | 1551 | int pef_hdroffset, opt_hdroffset, sec_hdroffset; |
| 1556 | 1552 | ||
| 1557 | n = n0 = 0; | 1553 | n = n0 = 0; |
| @@ -1562,7 +1558,6 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp) · 4 unmodified lines | |||
| 1562 | if (fd < 0) | 1558 | if (fd < 0) |
| 1563 | goto the_end_1; | 1559 | goto the_end_1; |
| 1564 | ret = 1; | 1560 | ret = 1; |
| 1565 | |||
| 1566 | if (!read_mem(fd, 0, &dh, sizeof dh)) | 1561 | if (!read_mem(fd, 0, &dh, sizeof dh)) |
| 1567 | goto the_end; | 1562 | goto the_end; |
| 1568 | if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig)) | 1563 | if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig)) |
| @@ -1572,22 +1567,26 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp) · 3 unmodified lines | |||
| 1572 | pef_hdroffset = dh.e_lfanew + sizeof sig; | 1567 | pef_hdroffset = dh.e_lfanew + sizeof sig; |
| 1573 | if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih)) | 1568 | if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih)) |
| 1574 | goto the_end; | 1569 | goto the_end; |
| 1575 | if (IMAGE_FILE_MACHINE != ih.Machine) { | ||
| 1576 | if (ih.Machine == 0x014C) | ||
| 1577 | ret = 32; | ||
| 1578 | else if (ih.Machine == 0x8664) | ||
| 1579 | ret = 64; | ||
| 1580 | goto the_end; | ||
| 1581 | } | ||
| 1582 | opt_hdroffset = pef_hdroffset + sizeof ih; | 1570 | opt_hdroffset = pef_hdroffset + sizeof ih; |
| 1583 | sec_hdroffset = opt_hdroffset + sizeof oh; | 1571 | if (ih.Machine == 0x014C) { |
| 1584 | if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) | 1572 | IMAGE_OPTIONAL_HEADER32 oh; |
| 1573 | sec_hdroffset = opt_hdroffset + sizeof oh; | ||
| 1574 | if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) | ||
| 1575 | goto the_end; | ||
| 1576 | if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) | ||
| 1577 | goto the_end_0; | ||
| 1578 | addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; | ||
| 1579 | } else if (ih.Machine == 0x8664) { | ||
| 1580 | IMAGE_OPTIONAL_HEADER64 oh; | ||
| 1581 | sec_hdroffset = opt_hdroffset + sizeof oh; | ||
| 1582 | if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) | ||
| 1583 | goto the_end; | ||
| 1584 | if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) | ||
| 1585 | goto the_end_0; | ||
| 1586 | addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; | ||
| 1587 | } else | ||
| 1585 | goto the_end; | 1588 | goto the_end; |
| 1586 | 1589 | ||
| 1587 | if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) | ||
| 1588 | goto the_end_0; | ||
| 1589 | |||
| 1590 | addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; | ||
| 1591 | //printf("addr: %08x\n", addr); | 1590 | //printf("addr: %08x\n", addr); |
| 1592 | for (i = 0; i < ih.NumberOfSections; ++i) { | 1591 | for (i = 0; i < ih.NumberOfSections; ++i) { |
| 1593 | if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish)) | 1592 | if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish)) |
| @@ -531,7 +531,6 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv) · 530 unmodified lines | |||
| 531 | break; | 531 | break; |
| 532 | 532 | ||
| 533 | /* above tokens have value, the ones below don't */ | 533 | /* above tokens have value, the ones below don't */ |
| 534 | |||
| 535 | case TOK_LT: | 534 | case TOK_LT: |
| 536 | v = '<'; | 535 | v = '<'; |
| 537 | goto addv; | 536 | goto addv; |
| @@ -544,6 +543,8 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv) · 6 unmodified lines | |||
| 544 | return strcpy(p, "<<="); | 543 | return strcpy(p, "<<="); |
| 545 | case TOK_A_SAR: | 544 | case TOK_A_SAR: |
| 546 | return strcpy(p, ">>="); | 545 | return strcpy(p, ">>="); |
| 546 | case TOK_EOF: | ||
| 547 | return strcpy(p, "<eof>"); | ||
| 547 | default: | 548 | default: |
| 548 | if (v < TOK_IDENT) { | 549 | if (v < TOK_IDENT) { |
| 549 | /* search in two bytes table */ | 550 | /* search in two bytes table */ |
| @@ -1791,7 +1792,7 @@ ST_FUNC void preprocess(int is_bof) · 1241 unmodified lines | |||
| 1791 | if (c != '\"') | 1792 | if (c != '\"') |
| 1792 | continue; | 1793 | continue; |
| 1793 | /* https://savannah.nongnu.org/bugs/index.php?50847 */ | 1794 | /* https://savannah.nongnu.org/bugs/index.php?50847 */ |
| 1794 | path = file->filename2; | 1795 | path = file->true_filename; |
| 1795 | pstrncpy(buf1, path, tcc_basename(path) - path); | 1796 | pstrncpy(buf1, path, tcc_basename(path) - path); |
| 1796 | 1797 | ||
| 1797 | } else { | 1798 | } else { |
| @@ -1921,9 +1922,11 @@ include_done: · 123 unmodified lines | |||
| 1921 | _line_num: | 1922 | _line_num: |
| 1922 | next(); | 1923 | next(); |
| 1923 | if (tok != TOK_LINEFEED) { | 1924 | if (tok != TOK_LINEFEED) { |
| 1924 | if (tok == TOK_STR) | 1925 | if (tok == TOK_STR) { |
| 1926 | if (file->true_filename == file->filename) | ||
| 1927 | file->true_filename = tcc_strdup(file->filename); | ||
| 1925 | pstrcpy(file->filename, sizeof(file->filename), (char *)tokc.str.data); | 1928 | pstrcpy(file->filename, sizeof(file->filename), (char *)tokc.str.data); |
| 1926 | else if (parse_flags & PARSE_FLAG_ASM_FILE) | 1929 | } else if (parse_flags & PARSE_FLAG_ASM_FILE) |
| 1927 | break; | 1930 | break; |
| 1928 | else | 1931 | else |
| 1929 | goto _line_err; | 1932 | goto _line_err; |
| @@ -363,9 +363,8 @@ usage: · 362 unmodified lines | |||
| 363 | ret = tcc_get_dllexports(file, &p); | 363 | ret = tcc_get_dllexports(file, &p); |
| 364 | if (ret || !p) { | 364 | if (ret || !p) { |
| 365 | fprintf(stderr, "tcc: impdef: %s '%s'\n", | 365 | fprintf(stderr, "tcc: impdef: %s '%s'\n", |
| 366 | ret == 32 ? "can't read symbols from 32bit" : | ||
| 367 | ret == 64 ? "can't read symbols from 64bit" : | ||
| 368 | ret == -1 ? "can't find file" : | 366 | ret == -1 ? "can't find file" : |
| 367 | ret == 1 ? "can't read symbols" : | ||
| 369 | ret == 0 ? "no symbols found in" : | 368 | ret == 0 ? "no symbols found in" : |
| 370 | "unknown file type", file); | 369 | "unknown file type", file); |
| 371 | ret = 1; | 370 | ret = 1; |
| @@ -728,13 +728,13 @@ static int arg_prepare_reg(int idx) { · 727 unmodified lines | |||
| 728 | return arg_regs[idx]; | 728 | return arg_regs[idx]; |
| 729 | } | 729 | } |
| 730 | 730 | ||
| 731 | static int func_scratch; | 731 | static int func_scratch, func_alloca; |
| 732 | 732 | ||
| 733 | /* Generate function call. The function address is pushed first, then | 733 | /* Generate function call. The function address is pushed first, then |
| 734 | all the parameters in call order. This functions pops all the | 734 | all the parameters in call order. This functions pops all the |
| 735 | parameters and the function address. */ | 735 | parameters and the function address. */ |
| 736 | 736 | ||
| 737 | void gen_offs_sp(int b, int r, int d) | 737 | static void gen_offs_sp(int b, int r, int d) |
| 738 | { | 738 | { |
| 739 | orex(1,0,r & 0x100 ? 0 : r, b); | 739 | orex(1,0,r & 0x100 ? 0 : r, b); |
| 740 | if (d == (char)d) { | 740 | if (d == (char)d) { |
| @@ -746,6 +746,11 @@ void gen_offs_sp(int b, int r, int d) · 5 unmodified lines | |||
| 746 | } | 746 | } |
| 747 | } | 747 | } |
| 748 | 748 | ||
| 749 | static int using_regs(int size) | ||
| 750 | { | ||
| 751 | return !(size > 8 || (size & (size - 1))); | ||
| 752 | } | ||
| 753 | |||
| 749 | /* Return the number of registers needed to return the struct, or 0 if | 754 | /* Return the number of registers needed to return the struct, or 0 if |
| 750 | returning via struct pointer. */ | 755 | returning via struct pointer. */ |
| 751 | ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) | 756 | ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) |
| @@ -754,7 +759,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int · 2 unmodified lines | |||
| 754 | *ret_align = 1; // Never have to re-align return values for x86-64 | 759 | *ret_align = 1; // Never have to re-align return values for x86-64 |
| 755 | *regsize = 8; | 760 | *regsize = 8; |
| 756 | size = type_size(vt, &align); | 761 | size = type_size(vt, &align); |
| 757 | if (size > 8 || (size & (size - 1))) | 762 | if (!using_regs(size)) |
| 758 | return 0; | 763 | return 0; |
| 759 | if (size == 8) | 764 | if (size == 8) |
| 760 | ret->t = VT_LLONG; | 765 | ret->t = VT_LLONG; |
| @@ -774,7 +779,7 @@ static int is_sse_float(int t) { · 13 unmodified lines | |||
| 774 | return bt == VT_DOUBLE || bt == VT_FLOAT; | 779 | return bt == VT_DOUBLE || bt == VT_FLOAT; |
| 775 | } | 780 | } |
| 776 | 781 | ||
| 777 | int gfunc_arg_size(CType *type) { | 782 | static int gfunc_arg_size(CType *type) { |
| 778 | int align; | 783 | int align; |
| 779 | if (type->t & (VT_ARRAY|VT_BITFIELD)) | 784 | if (type->t & (VT_ARRAY|VT_BITFIELD)) |
| 780 | return 8; | 785 | return 8; |
| @@ -801,7 +806,7 @@ void gfunc_call(int nb_args) · 20 unmodified lines | |||
| 801 | bt = (sv->type.t & VT_BTYPE); | 806 | bt = (sv->type.t & VT_BTYPE); |
| 802 | size = gfunc_arg_size(&sv->type); | 807 | size = gfunc_arg_size(&sv->type); |
| 803 | 808 | ||
| 804 | if (size <= 8) | 809 | if (using_regs(size)) |
| 805 | continue; /* arguments smaller than 8 bytes passed in registers or on stack */ | 810 | continue; /* arguments smaller than 8 bytes passed in registers or on stack */ |
| 806 | 811 | ||
| 807 | if (bt == VT_STRUCT) { | 812 | if (bt == VT_STRUCT) { |
| @@ -835,7 +840,7 @@ void gfunc_call(int nb_args) · 27 unmodified lines | |||
| 835 | bt = (vtop->type.t & VT_BTYPE); | 840 | bt = (vtop->type.t & VT_BTYPE); |
| 836 | 841 | ||
| 837 | size = gfunc_arg_size(&vtop->type); | 842 | size = gfunc_arg_size(&vtop->type); |
| 838 | if (size > 8) { | 843 | if (!using_regs(size)) { |
| 839 | /* align to stack align size */ | 844 | /* align to stack align size */ |
| 840 | size = (size + 15) & ~15; | 845 | size = (size + 15) & ~15; |
| 841 | if (arg >= REGN) { | 846 | if (arg >= REGN) { |
| @@ -895,6 +900,12 @@ void gfunc_call(int nb_args) · 53 unmodified lines | |||
| 895 | } | 900 | } |
| 896 | 901 | ||
| 897 | gcall_or_jmp(0); | 902 | gcall_or_jmp(0); |
| 903 | |||
| 904 | if ((vtop->r & VT_SYM) && vtop->sym->v == TOK_alloca) { | ||
| 905 | /* need to add the "func_scratch" area after alloca */ | ||
| 906 | o(0x0548), gen_le32(func_alloca), func_alloca = ind - 4; | ||
| 907 | } | ||
| 908 | |||
| 898 | /* other compilers don't clear the upper bits when returning char/short */ | 909 | /* other compilers don't clear the upper bits when returning char/short */ |
| 899 | bt = vtop->type.ref->type.t & (VT_BTYPE | VT_UNSIGNED); | 910 | bt = vtop->type.ref->type.t & (VT_BTYPE | VT_UNSIGNED); |
| 900 | if (bt == (VT_BYTE | VT_UNSIGNED)) | 911 | if (bt == (VT_BYTE | VT_UNSIGNED)) |
| @@ -926,6 +937,7 @@ void gfunc_prolog(CType *func_type) · 25 unmodified lines | |||
| 926 | 937 | ||
| 927 | func_ret_sub = 0; | 938 | func_ret_sub = 0; |
| 928 | func_scratch = 0; | 939 | func_scratch = 0; |
| 940 | func_alloca = 0; | ||
| 929 | loc = 0; | 941 | loc = 0; |
| 930 | 942 | ||
| 931 | addr = PTR_SIZE * 2; | 943 | addr = PTR_SIZE * 2; |
| @@ -940,7 +952,7 @@ void gfunc_prolog(CType *func_type) · 8 unmodified lines | |||
| 940 | func_vt = sym->type; | 952 | func_vt = sym->type; |
| 941 | func_var = (sym->c == FUNC_ELLIPSIS); | 953 | func_var = (sym->c == FUNC_ELLIPSIS); |
| 942 | size = gfunc_arg_size(&func_vt); | 954 | size = gfunc_arg_size(&func_vt); |
| 943 | if (size > 8) { | 955 | if (!using_regs(size)) { |
| 944 | gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); | 956 | gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); |
| 945 | func_vc = addr; | 957 | func_vc = addr; |
| 946 | reg_param_index++; | 958 | reg_param_index++; |
| @@ -952,7 +964,7 @@ void gfunc_prolog(CType *func_type) · 5 unmodified lines | |||
| 952 | type = &sym->type; | 964 | type = &sym->type; |
| 953 | bt = type->t & VT_BTYPE; | 965 | bt = type->t & VT_BTYPE; |
| 954 | size = gfunc_arg_size(type); | 966 | size = gfunc_arg_size(type); |
| 955 | if (size > 8) { | 967 | if (!using_regs(size)) { |
| 956 | if (reg_param_index < REGN) { | 968 | if (reg_param_index < REGN) { |
| 957 | gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); | 969 | gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); |
| 958 | } | 970 | } |
| @@ -1015,6 +1027,13 @@ void gfunc_epilog(void) · 56 unmodified lines | |||
| 1015 | gen_le32(v); | 1027 | gen_le32(v); |
| 1016 | } | 1028 | } |
| 1017 | 1029 | ||
| 1030 | /* add the "func_scratch" area after each alloca seen */ | ||
| 1031 | while (func_alloca) { | ||
| 1032 | unsigned char *ptr = cur_text_section->data + func_alloca; | ||
| 1033 | func_alloca = read32le(ptr); | ||
| 1034 | write32le(ptr, func_scratch); | ||
| 1035 | } | ||
| 1036 | |||
| 1018 | cur_text_section->data_offset = saved_ind; | 1037 | cur_text_section->data_offset = saved_ind; |
| 1019 | pe_add_unwind_data(ind, saved_ind, v); | 1038 | pe_add_unwind_data(ind, saved_ind, v); |
| 1020 | ind = cur_text_section->data_offset; | 1039 | ind = cur_text_section->data_offset; |