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