From 9f79b62ec4d84d07cf4a2fba969cb67c8f6ed8e5 Mon Sep 17 00:00:00 2001 From: grischka Date: Sun, 9 Jul 2017 12:07:40 +0200 Subject: [PATCH] unsorted adjustments - 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 for TOK_EOF * -funsigned-char: apply to "string" literals as well - tccpe/tools.c: -impdef: support both 32 and 64 bit dlls anyway --- Makefile | 29 +++++++++++++++++------------ configure | 14 ++++++-------- i386-gen.c | 2 +- lib/alloca86_64.S | 4 ---- libtcc.c | 14 ++++++++------ tcc.h | 22 ++++++++++------------ tccgen.c | 14 ++++++++++---- tccpe.c | 37 ++++++++++++++++++------------------- tccpp.c | 11 +++++++---- tcctools.c | 3 +-- x86_64-gen.c | 35 +++++++++++++++++++++++++++-------- 11 files changed, 105 insertions(+), 80 deletions(-) diff --git a/Makefile b/Makefile index 565ce2c..ee8dcd9 100644 --- a/Makefile +++ b/Makefile @@ -151,8 +151,8 @@ DEF-win += -DCONFIG_TCCDIR="\"$(tccdir)/win32\"" endif endif -# include custom cross-compiler configuration (see make help) --include config-cross.mak +# include custom configuration (see make help) +-include config-extra.mak CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c CORE_FILES += tcc.h config.h libtcc.h tcctok.h @@ -318,7 +318,7 @@ install-win : INSTALL = cp # uninstall on windows uninstall-win: - rm -r "$(tccdir)/"* + rm -r "$(tccdir)" # -------------------------------------------------------------------------- # other stuff @@ -374,19 +374,24 @@ help: @echo " build one specific cross compiler for 'TARGET', as in" @echo " $(TCC_X)" @echo "" - @echo "Cross compiler configuration:" - @echo " make will read custom configuration for cross compilers from a file" - @echo " 'config-cross.mak' if present. For example for a windows->i386-linux" - @echo " cross-compiler that expects the linux files in /i386-linux:" + @echo "Custom configuration:" + @echo " The makefile includes a file 'config-extra.mak' if it is present." + @echo " This file may contain some custom configuration. For example:" @echo "" - @echo " ROOT-i386 = {B}/i386-linux" - @echo " CRT-i386 = {B}/i386-linux/usr/lib" - @echo " LIB-i386 = {B}/i386-linux/lib:{B}/i386-linux/usr/lib" - @echo " INC-i386 = {B}/lib/include:{B}/i386-linux/usr/include" - @echo " DEF-i386 += -D__linux__" + @echo " NATIVE_DEFINES += -D..." + @echo "" + @echo " Or for example to configure the search paths for a cross-compiler" + @echo " that expects the linux files in /i386-linux:" + @echo "" + @echo " ROOT-i386 = {B}/i386-linux" + @echo " CRT-i386 = {B}/i386-linux/usr/lib" + @echo " LIB-i386 = {B}/i386-linux/lib:{B}/i386-linux/usr/lib" + @echo " INC-i386 = {B}/lib/include:{B}/i386-linux/usr/include" + @echo " DEF-i386 += -D__linux__" @echo "" @echo "Other supported make targets:" @echo " install install-strip test tags ETAGS tar clean distclean help" + @echo "" # -------------------------------------------------------------------------- endif # ($(INCLUDED),no) diff --git a/configure b/configure index 7708b53..4a337e7 100755 --- a/configure +++ b/configure @@ -161,7 +161,7 @@ fi case "$cpu" in x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386) - cpu="x86" + cpu="i386" ;; x86_64|amd64|x86-64) cpu="x86_64" @@ -184,7 +184,7 @@ case "$cpu" in cpu="arm" ;; aarch64) - cpu="arm64" + cpu="aarch64" ;; alpha) cpu="alpha" @@ -301,7 +301,7 @@ Advanced options (experts only): --disable-static make libtcc.so instead of libtcc.a --enable-static make libtcc.a instead of libtcc.dll (win32) --disable-rpath disable use of -rpath with the above - --with-libgcc use libgcc_s.so.1 instead of libtcc1.a in dynamic link + --with-libgcc use libgcc_s.so.1 instead of libtcc1.a --enable-mingw32 build windows version on linux with mingw32 --enable-cross build cross compilers --with-selinux use mmap for executable memory (with tcc -run) @@ -340,7 +340,7 @@ if test -z "$cross_prefix" ; then fi if test -z "$triplet"; then - if test $cpu = "x86_64" -o $cpu = "arm64" ; then + if test $cpu = "x86_64" -o $cpu = "aarch64" ; then if test -f "/usr/lib64/crti.o" ; then tcc_lddir="lib64" fi @@ -473,13 +473,11 @@ print_mak_int TCC_CPU_VERSION "$cpuver" echo "#define GCC_MAJOR $gcc_major" >> $TMPH echo "#define GCC_MINOR $gcc_minor" >> $TMPH - -if test "$cpu" = "x86" ; then - echo "ARCH=i386" >> config.mak +if test "$cpu" = "aarch64" ; then + echo "ARCH=arm64" >> config.mak else echo "ARCH=$cpu" >> config.mak fi - echo "TARGETOS=$targetos" >> config.mak for v in $confvars ; do diff --git a/i386-gen.c b/i386-gen.c index 829bcda..9990676 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -210,7 +210,7 @@ ST_FUNC void load(int r, SValue *sv) #endif fr = sv->r; - ft = sv->type.t; + ft = sv->type.t & ~VT_DEFSIGN; fc = sv->c.i; ft &= ~(VT_VOLATILE | VT_CONSTANT); diff --git a/lib/alloca86_64.S b/lib/alloca86_64.S index e4ca15e..4f4dad7 100644 --- a/lib/alloca86_64.S +++ b/lib/alloca86_64.S @@ -27,10 +27,6 @@ p2: sub %rax,%rsp mov %rsp,%rax -#ifdef TCC_TARGET_PE - add $32,%rax -#endif - p3: push %rdx ret diff --git a/libtcc.c b/libtcc.c index ba50ddf..1adcca6 100644 --- a/libtcc.c +++ b/libtcc.c @@ -264,7 +264,7 @@ struct mem_debug_header { int line_num; char file_name[MEM_DEBUG_FILE_LEN + 1]; unsigned magic2; - __attribute__((aligned(16))) unsigned magic3; + ALIGNED(16) unsigned magic3; }; 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) bf->buf_end = bf->buffer + initlen; bf->buf_end[0] = CH_EOB; /* put eob symbol */ pstrcpy(bf->filename, sizeof(bf->filename), filename); - pstrcpy(bf->filename2, sizeof(bf->filename2), filename); -#ifdef _WIN32 - normalize_slashes(bf->filename); -#endif + bf->true_filename = bf->filename; bf->line_num = 1; bf->ifdef_stack_ptr = s1->ifdef_stack_ptr; bf->fd = -1; @@ -599,6 +596,8 @@ ST_FUNC void tcc_close(void) close(bf->fd); total_lines += bf->line_num; } + if (bf->true_filename != bf->filename) + tcc_free(bf->true_filename); file = bf->prev; tcc_free(bf); } @@ -615,8 +614,10 @@ ST_FUNC int tcc_open(TCCState *s1, const char *filename) (int)(s1->include_stack_ptr - s1->include_stack), "", filename); if (fd < 0) return -1; - tcc_open_bf(s1, filename, 0); +#ifdef _WIN32 + normalize_slashes(file->filename); +#endif file->fd = fd; return fd; } @@ -737,6 +738,7 @@ LIBTCCAPI TCCState *tcc_new(void) s->alacarte_link = 1; s->nocommon = 1; s->warn_implicit_function_declaration = 1; + s->ms_extensions = 1; #ifdef CHAR_IS_UNSIGNED s->char_is_unsigned = 1; diff --git a/tcc.h b/tcc.h index 67d09a0..958dae7 100644 --- a/tcc.h +++ b/tcc.h @@ -41,10 +41,11 @@ # include # endif /* XXX: need to define this to use them in non ISOC99 context */ - extern float strtof (const char *__nptr, char **__endptr); - extern long double strtold (const char *__nptr, char **__endptr); +extern float strtof (const char *__nptr, char **__endptr); +extern long double strtold (const char *__nptr, char **__endptr); +#endif -#else /* on _WIN32: */ +#ifdef _WIN32 # include # include /* open, close etc. */ # include /* getcwd */ @@ -52,7 +53,6 @@ # include # endif # define inline __inline -# define inp next_inp /* inp is an intrinsic on msvc */ # define snprintf _snprintf # define vsnprintf _vsnprintf # ifndef __GNUC__ @@ -65,6 +65,7 @@ # define LIBTCCAPI __declspec(dllexport) # define PUB_FUNC LIBTCCAPI # endif +# define inp next_inp /* inp is an intrinsic on msvc/mingw */ # ifdef _MSC_VER # pragma warning (disable : 4244) // conversion from 'uint64_t' to 'int', possible loss of data # pragma warning (disable : 4267) // conversion from 'size_t' to 'int', possible loss of data @@ -72,9 +73,6 @@ # pragma warning (disable : 4018) // signed/unsigned mismatch # pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned # define ssize_t intptr_t -# define __attribute__(x) __declspec x -# define aligned align -# else # endif # undef CONFIG_TCC_STATIC #endif @@ -83,12 +81,12 @@ # define O_BINARY 0 #endif -#ifdef __GNUC__ -# define NORETURN __attribute__ ((noreturn)) -#elif defined _MSC_VER +#ifdef _MSC_VER # define NORETURN __declspec(noreturn) +# define ALIGNED(x) __declspec(align(x)) #else -# define NORETURN +# define NORETURN __attribute__((noreturn)) +# define ALIGNED(x) __attribute__((aligned(x))) #endif #ifdef _WIN32 @@ -540,7 +538,7 @@ typedef struct BufferedFile { int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */ int include_next_index; /* next search path */ char filename[1024]; /* filename */ - char filename2[1024]; /* filename not modified by # line directive */ + char *true_filename; /* filename not modified by # line directive */ unsigned char unget[4]; unsigned char buffer[1]; /* extra size for CH_EOB char */ } BufferedFile; diff --git a/tccgen.c b/tccgen.c index af8d2a7..40bed59 100644 --- a/tccgen.c +++ b/tccgen.c @@ -1752,8 +1752,8 @@ static void gen_opic(int op) vtop--; } else if (!const_wanted && c2 && ((l2 == 0 && (op == '&' || op == '*')) || - (l2 == -1 && op == '|') || - (l2 == 0xffffffff && t2 != VT_LLONG && op == '|') || + (op == '|' && + (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))) || (l2 == 1 && (op == '%' || op == TOK_UMOD)))) { /* treat (x & 0), (x * 0), (x | -1) and (x % 1) as constant */ if (l2 == 1) @@ -1767,7 +1767,7 @@ static void gen_opic(int op) op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) && l2 == 0) || (op == '&' && - l2 == -1))) { + (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))))) { /* filter out NOP operations like x*1, x-0, x&-1... */ vtop--; } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) { @@ -1817,6 +1817,10 @@ static void gen_opif(int op) { int c1, c2; SValue *v1, *v2; +#if defined _MSC_VER && defined _AMD64_ + /* avoid bad optimization with f1 -= f2 for f1:-0.0, f2:0.0 */ + volatile +#endif long double f1, f2; v1 = vtop - 1; @@ -3497,7 +3501,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) if (v < TOK_IDENT) expect("struct/union/enum name"); s = struct_find(v); - if (s && (s->scope == local_scope || (tok != '{' && tok != ';'))) { + if (s && (s->scope == local_scope || tok != '{')) { if (s->type.t != a) tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); goto do_decl; @@ -4381,6 +4385,8 @@ ST_FUNC void unary(void) case TOK_STR: /* string parsing */ t = VT_BYTE; + if (tcc_state->char_is_unsigned) + t = VT_BYTE | VT_UNSIGNED; str_init: if (tcc_state->warn_write_strings) t |= VT_CONSTANT; diff --git a/tccpe.c b/tccpe.c index 5877b2a..78a43c5 100644 --- a/tccpe.c +++ b/tccpe.c @@ -1547,11 +1547,7 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp) IMAGE_DOS_HEADER dh; IMAGE_FILE_HEADER ih; DWORD sig, ref, addr, ptr, namep; -#ifdef TCC_TARGET_X86_64 - IMAGE_OPTIONAL_HEADER64 oh; -#else - IMAGE_OPTIONAL_HEADER32 oh; -#endif + int pef_hdroffset, opt_hdroffset, sec_hdroffset; n = n0 = 0; @@ -1562,7 +1558,6 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp) if (fd < 0) goto the_end_1; ret = 1; - if (!read_mem(fd, 0, &dh, sizeof dh)) goto the_end; 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) pef_hdroffset = dh.e_lfanew + sizeof sig; if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih)) goto the_end; - if (IMAGE_FILE_MACHINE != ih.Machine) { - if (ih.Machine == 0x014C) - ret = 32; - else if (ih.Machine == 0x8664) - ret = 64; - goto the_end; - } opt_hdroffset = pef_hdroffset + sizeof ih; - sec_hdroffset = opt_hdroffset + sizeof oh; - if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) + if (ih.Machine == 0x014C) { + IMAGE_OPTIONAL_HEADER32 oh; + sec_hdroffset = opt_hdroffset + sizeof oh; + if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) + goto the_end; + if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) + goto the_end_0; + addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } else if (ih.Machine == 0x8664) { + IMAGE_OPTIONAL_HEADER64 oh; + sec_hdroffset = opt_hdroffset + sizeof oh; + if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) + goto the_end; + if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) + goto the_end_0; + addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } else goto the_end; - if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) - goto the_end_0; - - addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; //printf("addr: %08x\n", addr); for (i = 0; i < ih.NumberOfSections; ++i) { if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish)) diff --git a/tccpp.c b/tccpp.c index b81b4b5..99d3c0a 100644 --- a/tccpp.c +++ b/tccpp.c @@ -531,7 +531,6 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv) break; /* above tokens have value, the ones below don't */ - case TOK_LT: v = '<'; goto addv; @@ -544,6 +543,8 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv) return strcpy(p, "<<="); case TOK_A_SAR: return strcpy(p, ">>="); + case TOK_EOF: + return strcpy(p, ""); default: if (v < TOK_IDENT) { /* search in two bytes table */ @@ -1791,7 +1792,7 @@ ST_FUNC void preprocess(int is_bof) if (c != '\"') continue; /* https://savannah.nongnu.org/bugs/index.php?50847 */ - path = file->filename2; + path = file->true_filename; pstrncpy(buf1, path, tcc_basename(path) - path); } else { @@ -1921,9 +1922,11 @@ include_done: _line_num: next(); if (tok != TOK_LINEFEED) { - if (tok == TOK_STR) + if (tok == TOK_STR) { + if (file->true_filename == file->filename) + file->true_filename = tcc_strdup(file->filename); pstrcpy(file->filename, sizeof(file->filename), (char *)tokc.str.data); - else if (parse_flags & PARSE_FLAG_ASM_FILE) + } else if (parse_flags & PARSE_FLAG_ASM_FILE) break; else goto _line_err; diff --git a/tcctools.c b/tcctools.c index a316527..53d88be 100644 --- a/tcctools.c +++ b/tcctools.c @@ -363,9 +363,8 @@ usage: ret = tcc_get_dllexports(file, &p); if (ret || !p) { fprintf(stderr, "tcc: impdef: %s '%s'\n", - ret == 32 ? "can't read symbols from 32bit" : - ret == 64 ? "can't read symbols from 64bit" : ret == -1 ? "can't find file" : + ret == 1 ? "can't read symbols" : ret == 0 ? "no symbols found in" : "unknown file type", file); ret = 1; diff --git a/x86_64-gen.c b/x86_64-gen.c index 19d5dd7..1873a9d 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -728,13 +728,13 @@ static int arg_prepare_reg(int idx) { return arg_regs[idx]; } -static int func_scratch; +static int func_scratch, func_alloca; /* Generate function call. The function address is pushed first, then all the parameters in call order. This functions pops all the parameters and the function address. */ -void gen_offs_sp(int b, int r, int d) +static void gen_offs_sp(int b, int r, int d) { orex(1,0,r & 0x100 ? 0 : r, b); if (d == (char)d) { @@ -746,6 +746,11 @@ void gen_offs_sp(int b, int r, int d) } } +static int using_regs(int size) +{ + return !(size > 8 || (size & (size - 1))); +} + /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) @@ -754,7 +759,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *ret_align = 1; // Never have to re-align return values for x86-64 *regsize = 8; size = type_size(vt, &align); - if (size > 8 || (size & (size - 1))) + if (!using_regs(size)) return 0; if (size == 8) ret->t = VT_LLONG; @@ -774,7 +779,7 @@ static int is_sse_float(int t) { return bt == VT_DOUBLE || bt == VT_FLOAT; } -int gfunc_arg_size(CType *type) { +static int gfunc_arg_size(CType *type) { int align; if (type->t & (VT_ARRAY|VT_BITFIELD)) return 8; @@ -801,7 +806,7 @@ void gfunc_call(int nb_args) bt = (sv->type.t & VT_BTYPE); size = gfunc_arg_size(&sv->type); - if (size <= 8) + if (using_regs(size)) continue; /* arguments smaller than 8 bytes passed in registers or on stack */ if (bt == VT_STRUCT) { @@ -835,7 +840,7 @@ void gfunc_call(int nb_args) bt = (vtop->type.t & VT_BTYPE); size = gfunc_arg_size(&vtop->type); - if (size > 8) { + if (!using_regs(size)) { /* align to stack align size */ size = (size + 15) & ~15; if (arg >= REGN) { @@ -895,6 +900,12 @@ void gfunc_call(int nb_args) } gcall_or_jmp(0); + + if ((vtop->r & VT_SYM) && vtop->sym->v == TOK_alloca) { + /* need to add the "func_scratch" area after alloca */ + o(0x0548), gen_le32(func_alloca), func_alloca = ind - 4; + } + /* other compilers don't clear the upper bits when returning char/short */ bt = vtop->type.ref->type.t & (VT_BTYPE | VT_UNSIGNED); if (bt == (VT_BYTE | VT_UNSIGNED)) @@ -926,6 +937,7 @@ void gfunc_prolog(CType *func_type) func_ret_sub = 0; func_scratch = 0; + func_alloca = 0; loc = 0; addr = PTR_SIZE * 2; @@ -940,7 +952,7 @@ void gfunc_prolog(CType *func_type) func_vt = sym->type; func_var = (sym->c == FUNC_ELLIPSIS); size = gfunc_arg_size(&func_vt); - if (size > 8) { + if (!using_regs(size)) { gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); func_vc = addr; reg_param_index++; @@ -952,7 +964,7 @@ void gfunc_prolog(CType *func_type) type = &sym->type; bt = type->t & VT_BTYPE; size = gfunc_arg_size(type); - if (size > 8) { + if (!using_regs(size)) { if (reg_param_index < REGN) { gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); } @@ -1015,6 +1027,13 @@ void gfunc_epilog(void) gen_le32(v); } + /* add the "func_scratch" area after each alloca seen */ + while (func_alloca) { + unsigned char *ptr = cur_text_section->data + func_alloca; + func_alloca = read32le(ptr); + write32le(ptr, func_scratch); + } + cur_text_section->data_offset = saved_ind; pe_add_unwind_data(ind, saved_ind, v); ind = cur_text_section->data_offset;