diff --git a/Makefile b/Makefile index ed970c59..68710395 100644 --- a/Makefile +++ b/Makefile @@ -12,8 +12,6 @@ ifeq ($(findstring $(MAKECMDGOALS),clean distclean),) include $(TOP)/config.mak endif -CONFIG_strip = no - ifeq (-$(GCC_MAJOR)-$(findstring $(GCC_MINOR),56789)-,-4--) CFLAGS += -D_FORTIFY_SOURCE=0 endif @@ -221,7 +219,7 @@ $(TCC_FILES) : DEFINES += -DONE_SOURCE=0 $(X)tccpp.o : $(TCCDEFS_H) endif -ifeq ($(CONFIG_strip),no) +ifeq ($(CONFIG_debug),yes) CFLAGS += -g LDFLAGS += -g else diff --git a/arm-gen.c b/arm-gen.c index a4dc9d28..bc308c2f 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -541,8 +541,13 @@ static int negcc(int cc) Use relative/got addressing to avoid setting DT_TEXTREL */ static void load_value(SValue *sv, int r) { - o(0xE59F0000|(intr(r)<<12)); - o(0xEA000000); + o(0xE59F0000|(intr(r)<<12)); /* ldr r, [pc] */ + o(0xEA000000); /* b $+4 */ +#ifndef CONFIG_TCC_PIE + if(sv->r & VT_SYM) + greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); + o(sv->c.i); +#else if(sv->r & VT_SYM) { if (sv->sym->type.t & VT_STATIC) { greloc(cur_text_section, sv->sym, ind, R_ARM_REL32); @@ -561,6 +566,7 @@ static void load_value(SValue *sv, int r) } else o(sv->c.i); +#endif } /* load 'r' from value 'sv' */ @@ -1731,11 +1737,13 @@ void gen_opi(int op) } } fr=intr(gv(RC_INT)); +#ifdef CONFIG_TCC_BCHECK if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { vswap(); c=intr(gv(RC_INT)); vswap(); } +#endif if ((opc & 0xfff00000) == 0xe1500000) // cmp rx,ry o(opc|(c<<16)|fr); else { @@ -1761,11 +1769,13 @@ done: o(opc|r|(c<<7)|(fr<<12)); } else { fr=intr(gv(RC_INT)); +#ifdef CONFIG_TCC_BCHECK if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { vswap(); r=intr(gv(RC_INT)); vswap(); } +#endif c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r))); o(opc|r|(c<<12)|(fr<<8)|0x10); } @@ -1877,12 +1887,14 @@ void gen_opf(int op) r2=gv(RC_FLOAT); x|=vfpr(r2)<<16; r|=regmask(r2); +#ifdef CONFIG_TCC_BCHECK if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { vswap(); r=gv(RC_FLOAT); vswap(); x=(x&~0xf)|vfpr(r); } +#endif } vtop->r=get_reg_ex(RC_FLOAT,r); if(!fneg) @@ -1965,11 +1977,13 @@ void gen_opf(int op) r2=c2&0xf; } else { r2=fpr(gv(RC_FLOAT)); +#ifdef CONFIG_TCC_BCHECK if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { vswap(); r=fpr(gv(RC_FLOAT)); vswap(); } +#endif } break; case '-': @@ -1991,11 +2005,13 @@ void gen_opf(int op) r=fpr(gv(RC_FLOAT)); vswap(); r2=fpr(gv(RC_FLOAT)); +#ifdef CONFIG_TCC_BCHECK if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { vswap(); r=fpr(gv(RC_FLOAT)); vswap(); } +#endif } break; case '*': @@ -2010,11 +2026,13 @@ void gen_opf(int op) r2=c2; else { r2=fpr(gv(RC_FLOAT)); +#ifdef CONFIG_TCC_BCHECK if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { vswap(); r=fpr(gv(RC_FLOAT)); vswap(); } +#endif } x|=0x100000; // muf break; @@ -2036,11 +2054,13 @@ void gen_opf(int op) r=fpr(gv(RC_FLOAT)); vswap(); r2=fpr(gv(RC_FLOAT)); +#ifdef CONFIG_TCC_BCHECK if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { vswap(); r=fpr(gv(RC_FLOAT)); vswap(); } +#endif } break; default: @@ -2093,11 +2113,13 @@ void gen_opf(int op) r2=c2&0xf; } else { r2=fpr(gv(RC_FLOAT)); +#ifdef CONFIG_TCC_BCHECK if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { vswap(); r=fpr(gv(RC_FLOAT)); vswap(); } +#endif } --vtop; vset_VT_CMP(op); diff --git a/configure b/configure old mode 100755 new mode 100644 index 4050570b..1562d0fb --- a/configure +++ b/configure @@ -29,7 +29,6 @@ sysroot="" cross_prefix="" cc="gcc" ar="ar" -strip="strip" bigendian="no" mingw32="no" LIBSUF=".a" @@ -44,13 +43,14 @@ triplet= tcc_lddir= confvars= suggest="yes" -cpu= -cpuver= gcc_major=0 gcc_minor=0 cc_name="gcc" ar_set= +cpu=`uname -m` +cpuver= + # OS specific targetos=`uname` case $targetos in @@ -140,9 +140,7 @@ for opt do ;; --disable-rpath) confvars="$confvars rpath=no" ;; - --strip-binaries) echo deprecate, use 'make install-strip' to strip binaries - ;; - --debug) confvars="$confvars strip=no" + --debug) confvars="$confvars debug" ;; --with-libgcc) confvars="$confvars libgcc" ;; @@ -161,15 +159,6 @@ done cc="${cross_prefix}${cc}" ar="${cross_prefix}${ar}" -strip="${cross_prefix}${strip}" - -if test -z "$cpu" ; then - if test -n "$ARCH" ; then - cpu="$ARCH" - else - cpu=`uname -m` - fi -fi case "$cpu" in x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386) @@ -181,7 +170,7 @@ case "$cpu" in evbarm) case "`uname -p`" in aarch64|arm64) - cpu="aarch64" + cpu="arm64" ;; earmv*) cpu="arm" @@ -189,7 +178,7 @@ case "$cpu" in esac ;; aarch64|arm64|evbarm) - cpu="aarch64" + cpu="arm64" ;; arm*) case "$cpu" in @@ -302,30 +291,33 @@ Standard options: Advanced options (experts only): --source-path=PATH path of source code [$source_path] --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix] - --sysroot=PREFIX prepend PREFIX to library/include paths [] + --sysroot=PREFIX prepend PREFIX to library/include paths [$sysroot] --cc=CC use C compiler CC [$cc] --ar=AR create archives using AR [$ar] --extra-cflags= specify compiler flags [$CFLAGS] - --extra-ldflags= specify linker options [] + --extra-ldflags= specify linker options [$LDFLAGS] --cpu=CPU CPU [$cpu] - --strip-binaries strip symbol tables from resulting binaries + --debug include debug info with resulting binaries --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 + --disable-rpath disable use of -rpath with libtcc.so --with-libgcc use libgcc_s.so.1 instead of libtcc1.a - --enable-cross build cross compilers - --with-selinux use mmap for executable memory (with tcc -run) + --with-selinux use mmap for executable memory (tcc -run) + --enable-cross build cross compilers (see also 'make help') + --sysincludepaths=... specify system include paths, colon separated --libpaths=... specify system library paths, colon separated --crtprefix=... specify locations of crt?.o, colon separated --elfinterp=... specify elf interpreter --triplet=... specify system library/include directory triplet - --config-uClibc,-musl,-mingw32... enable system specific configurations - --config-bcheck=no/-backtrace=no disable bounds checker/stack backtraces + + --config-uClibc,-musl enable system specific configurations + --config-mingw32 build on windows using msys, busybox, etc. + --config-backtrace=no disable stack backtraces (with -run or -bt) + --config-bcheck=no disable bounds checker (-b) --config-predefs=no do not compile tccdefs.h, instead just include EOF -#echo "NOTE: The object files are build at the place where configure is launched" exit 1 fi @@ -349,7 +341,7 @@ if test -z "$cross_prefix" ; then fi if test -z "$triplet"; then - if test $cpu = "x86_64" -o $cpu = "aarch64" -o $cpu = "riscv64" ; then + if test $cpu = "x86_64" -o $cpu = "arm64" -o $cpu = "riscv64" ; then if test -f "/usr/lib64/crti.o" ; then tcc_lddir="lib64" fi @@ -453,7 +445,6 @@ CC_NAME=$cc_name GCC_MAJOR=$gcc_major GCC_MINOR=$gcc_minor AR=$ar -STRIP=$strip -s -R .comment -R .note CFLAGS=$CFLAGS LDFLAGS=$LDFLAGS LIBSUF=$LIBSUF @@ -492,11 +483,7 @@ print_mak CONFIG_LDDIR "$tcc_lddir" print_mak CONFIG_TRIPLET "$triplet" print_mak TCC_CPU_VERSION "$cpuver" num -if test "$cpu" = "aarch64" ; then - echo "ARCH=arm64" >> config.mak -else - echo "ARCH=$cpu" >> config.mak -fi +echo "ARCH=$cpu" >> config.mak echo "TARGETOS=$targetos" >> config.mak predefs="1" diff --git a/lib/bt-exe.c b/lib/bt-exe.c index 992e245c..16ce9c72 100644 --- a/lib/bt-exe.c +++ b/lib/bt-exe.c @@ -12,15 +12,17 @@ int (*__rt_error)(void*, void*, const char *, va_list); #endif __declspec(dllexport) -void __bt_init(rt_context *p, int num_callers, int mode) +void __bt_init(rt_context *p, int num_callers) { __attribute__((weak)) int main(); __attribute__((weak)) void __bound_init(void*, int); struct rt_context *rc = &g_rtctxt; - //fprintf(stderr, "__bt_init %d %p %p %d\n", num_callers, p->stab_sym, p->bounds_start, mode), fflush(stderr); + //fprintf(stderr, "__bt_init %d %p %p\n", num_callers, p->stab_sym, p->bounds_start), fflush(stderr); +#ifdef __APPLE__ /* call __bound_init here due to redirection of sigaction */ if (__bound_init && p->bounds_start) - __bound_init(p->bounds_start, mode); + __bound_init(p->bounds_start, 0); +#endif if (num_callers) { memcpy(rc, p, offsetof(rt_context, next)); rc->num_callers = num_callers - 1; diff --git a/libtcc.c b/libtcc.c index 9d2cbaf9..56fe65a1 100644 --- a/libtcc.c +++ b/libtcc.c @@ -273,20 +273,12 @@ PUB_FUNC char *tcc_strdup(const char *str) #define MEM_DEBUG_MAGIC2 0xFEEDDEB2 #define MEM_DEBUG_MAGIC3 0xFEEDDEB3 #define MEM_DEBUG_FILE_LEN 40 -#define MEM_DEBUG_OFF3 offsetof(mem_debug_header_t, magic3) #define MEM_DEBUG_CHECK3(header) \ - ({unsigned magic3; \ - memcpy(&magic3, (char*)header + MEM_DEBUG_OFF3 + header->size, \ - sizeof (magic3)); \ - magic3;}) -#define MEM_DEBUG_SET3(header) \ - {unsigned magic3 = MEM_DEBUG_MAGIC3; \ - memcpy((char*)header + MEM_DEBUG_OFF3 + header->size, &magic3, \ - sizeof (magic3));} + ((mem_debug_header_t*)((char*)header + header->size))->magic3 #define MEM_USER_PTR(header) \ - ((char *)header + MEM_DEBUG_OFF3) + ((char *)header + offsetof(mem_debug_header_t, magic3)) #define MEM_HEADER_PTR(ptr) \ - (mem_debug_header_t *)((char*)ptr - MEM_DEBUG_OFF3) + (mem_debug_header_t *)((char*)ptr - offsetof(mem_debug_header_t, magic3)) struct mem_debug_header { unsigned magic1; @@ -296,7 +288,7 @@ struct mem_debug_header { int line_num; char file_name[MEM_DEBUG_FILE_LEN + 1]; unsigned magic2; - ALIGNED(16) unsigned magic3; + ALIGNED(16) unsigned char magic3[4]; }; typedef struct mem_debug_header mem_debug_header_t; @@ -310,7 +302,7 @@ static mem_debug_header_t *malloc_check(void *ptr, const char *msg) mem_debug_header_t * header = MEM_HEADER_PTR(ptr); if (header->magic1 != MEM_DEBUG_MAGIC1 || header->magic2 != MEM_DEBUG_MAGIC2 || - MEM_DEBUG_CHECK3(header) != MEM_DEBUG_MAGIC3 || + read32le(MEM_DEBUG_CHECK3(header)) != MEM_DEBUG_MAGIC3 || header->size == (unsigned)-1) { fprintf(stderr, "%s check failed\n", msg); if (header->magic1 == MEM_DEBUG_MAGIC1) @@ -333,7 +325,7 @@ PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line) header->magic1 = MEM_DEBUG_MAGIC1; header->magic2 = MEM_DEBUG_MAGIC2; header->size = size; - MEM_DEBUG_SET3(header); + write32le(MEM_DEBUG_CHECK3(header), MEM_DEBUG_MAGIC3); header->line_num = line; ofs = strlen(file) - MEM_DEBUG_FILE_LEN; strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN); @@ -390,7 +382,7 @@ PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file if (!header) _tcc_error("memory full (realloc)"); header->size = size; - MEM_DEBUG_SET3(header); + write32le(MEM_DEBUG_CHECK3(header), MEM_DEBUG_MAGIC3); if (header->next) header->next->prev = header; if (header->prev) @@ -901,7 +893,6 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) /* add libc crt1/crti objects */ if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) && !s->nostdlib) { -#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD #if TARGETOS_OpenBSD if (output_type != TCC_OUTPUT_DLL) tcc_add_crt(s, "crt0.o"); @@ -929,9 +920,9 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) tcc_add_crt(s, "crtbeginS.o"); else tcc_add_crt(s, "crtbegin.o"); -#endif -#elif !TCC_TARGET_MACHO +#elif TCC_TARGET_MACHO /* Mach-O with LC_MAIN doesn't need any crt startup code. */ +#else if (output_type != TCC_OUTPUT_DLL) tcc_add_crt(s, "crt1.o"); tcc_add_crt(s, "crti.o"); @@ -963,10 +954,41 @@ ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname) } #endif +/* OpenBSD: choose latest from libxxx.so.x.y versions */ +#if defined TARGETOS_OpenBSD && !defined _WIN32 +#include +static int tcc_glob_so(TCCState *s1, const char *pattern, char *buf, int size) +{ + const char *star; + glob_t g; + char *p; + int i, v, v1, v2, v3; + + star = strchr(pattern, '*'); + if (!star || glob(pattern, 0, NULL, &g)) + return -1; + for (v = -1, i = 0; i < g.gl_pathc; ++i) { + p = g.gl_pathv[i]; + if (2 != sscanf(p + (star - pattern), "%d.%d.%d", &v1, &v2, &v3)) + continue; + if ((v1 = v1 * 1000 + v2) > v) + v = v1, pstrcpy(buf, size, p); + } + globfree(&g); + return v; +} +#endif + ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) { int fd, ret = -1; +#if defined TARGETOS_OpenBSD && !defined _WIN32 + char buf[1024]; + if (tcc_glob_so(s1, filename, buf, sizeof buf) >= 0) + filename = buf; +#endif + /* open the file */ fd = _tcc_open(s1, filename); if (fd < 0) { @@ -1111,101 +1133,21 @@ ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename) } #endif -/* OpenBSD only has suffixed .so files; e.g., libc.so.96.0 */ -/* So we must process that */ -#if defined TARGETOS_OpenBSD && !defined _WIN32/* no dirent */ -#include -ST_FUNC char *tcc_openbsd_library_soversion(TCCState *s, const char *libraryname) -{ - DIR *dirp; - struct dirent *dp; - char *e; - char **libpaths, *t, *u, *v; - char soname[1024]; - long long maj, min, tmaj, tmin; - int i; - static char soversion[1024]; - - snprintf(soname, sizeof(soname), "lib%s.so", libraryname); - - libpaths = s->library_paths; - for (i = 0; i < s->nb_library_paths; ++i) { - if ((dirp = opendir(libpaths[i])) == NULL) - continue; - - maj = -1; - min = -1; - - while ((dp = readdir(dirp)) != NULL) { - if (!strncmp(dp->d_name, soname, strlen(soname))) { - t = tcc_strdup(dp->d_name); - u = strrchr(t, '.'); - *u = '\0'; - - tmin = strtoll(u + 1, &e, 10); - - if (*e != 0) { - tcc_free(t); - t = NULL; - continue; - } - - v = strrchr(t, '.'); - tmaj = strtoll(v + 1, &e, 10); - - if (*e != 0) { - tcc_free(t); - t = NULL; - continue; - } - - tcc_free(t); - t = NULL; - - if (maj == tmaj) { - if (min < tmin) - min = tmin; - } else if (maj < tmaj) { - maj = tmaj; - min = tmin; - } - } - } - closedir(dirp); - - if (maj == -1 || min == -1) - continue; - - snprintf(soversion, sizeof(soversion), "%s/%s.%lld.%lld", libpaths[i], - soname, maj, min); - } - - return soversion; -} -#endif - /* the library name is the same as the argument of the '-l' option */ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname) { #if defined TCC_TARGET_PE - const char *libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL }; - const char **pp = s->static_link ? libs + 4 : libs; + static const char * const libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL }; + const char * const *pp = s->static_link ? libs + 4 : libs; #elif defined TCC_TARGET_MACHO - const char *libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL }; - const char **pp = s->static_link ? libs + 1 : libs; -#elif defined TARGETOS_OpenBSD && !defined _WIN32 - const char *libs[] = { s->static_link - ? NULL - /* find exact versionned .so.x.y name as no - symlink exists on OpenBSD. */ - : tcc_openbsd_library_soversion(s, libraryname), - "%s/lib%s.a", - NULL - }; - const char **pp = s->static_link ? libs + 1 : libs; + static const char * const libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL }; + const char * const *pp = s->static_link ? libs + 1 : libs; +#elif defined TARGETOS_OpenBSD + static const char * const libs[] = { "%s/lib%s.so.*", "%s/lib%s.a", NULL }; + const char * const *pp = s->static_link ? libs + 1 : libs; #else - const char *libs[] = { "%s/lib%s.so", "%s/lib%s.a", NULL }; - const char **pp = s->static_link ? libs + 1 : libs; + static const char * const libs[] = { "%s/lib%s.so", "%s/lib%s.a", NULL }; + const char * const *pp = s->static_link ? libs + 1 : libs; #endif int flags = s->filetype & AFF_WHOLE_ARCHIVE; while (*pp) { diff --git a/riscv64-gen.c b/riscv64-gen.c index bef9d76e..8cbfcb77 100644 --- a/riscv64-gen.c +++ b/riscv64-gen.c @@ -166,10 +166,10 @@ ST_FUNC void gsym_addr(int t_, int a_) static int load_symofs(int r, SValue *sv, int forstore) { - static Sym label; int rr, doload = 0; int fc = sv->c.i, v = sv->r & VT_VALMASK; if (sv->r & VT_SYM) { + Sym label = {0}; assert(v == VT_CONST); if (sv->sym->type.t & VT_STATIC) { // XXX do this per linker relax greloca(cur_text_section, sv->sym, ind, @@ -182,11 +182,7 @@ static int load_symofs(int r, SValue *sv, int forstore) R_RISCV_GOT_HI20, 0); doload = 1; } - if (!label.v) { - label.v = tok_alloc(".L0 ", 4)->tok; - label.type.t = VT_VOID | VT_STATIC; - } - label.c = 0; /* force new local ELF symbol */ + label.type.t = VT_VOID | VT_STATIC; put_extern_sym(&label, cur_text_section, ind, 0); rr = is_ireg(r) ? ireg(r) : 5; o(0x17 | (rr << 7)); // auipc RR, 0 %pcrel_hi(sym)+addend @@ -459,10 +455,11 @@ static void gen_bounds_prolog(void) static void gen_bounds_epilog(void) { - static Sym label; addr_t saved_ind; addr_t *bounds_ptr; Sym *sym_data; + Sym label = {0}; + int offset_modified = func_bound_offset != lbounds_section->data_offset; if (!offset_modified && !func_bound_add_epilog) @@ -475,15 +472,11 @@ static void gen_bounds_epilog(void) sym_data = get_sym_ref(&char_pointer_type, lbounds_section, func_bound_offset, lbounds_section->data_offset); - if (!label.v) { - label.v = tok_alloc(".LB0 ", 5)->tok; - label.type.t = VT_VOID | VT_STATIC; - } + label.type.t = VT_VOID | VT_STATIC; /* generate bound local allocation */ if (offset_modified) { saved_ind = ind; ind = func_bound_ind; - label.c = 0; /* force new local ELF symbol */ put_extern_sym(&label, cur_text_section, ind, 0); greloca(cur_text_section, sym_data, ind, R_RISCV_GOT_HI20, 0); o(0x17 | (10 << 7)); // auipc a0, 0 %pcrel_hi(sym)+addend @@ -491,12 +484,12 @@ static void gen_bounds_epilog(void) EI(0x03, 3, 10, 10, 0); // ld a0, 0(a0) gen_bounds_call(TOK___bound_local_new); ind = saved_ind; + label.c = 0; /* force new local ELF symbol */ } /* generate bound check local freeing */ o(0xe02a1101); /* addi sp,sp,-32 sd a0,0(sp) */ o(0xa82ae42e); /* sd a1,8(sp) fsd fa0,16(sp) */ - label.c = 0; /* force new local ELF symbol */ put_extern_sym(&label, cur_text_section, ind, 0); greloca(cur_text_section, sym_data, ind, R_RISCV_GOT_HI20, 0); o(0x17 | (10 << 7)); // auipc a0, 0 %pcrel_hi(sym)+addend @@ -1352,19 +1345,15 @@ ST_FUNC void gen_cvt_ftof(int dt) ST_FUNC void gen_increment_tcov (SValue *sv) { int r1, r2; - static Sym label; + Sym label = {0}; + label.type.t = VT_VOID | VT_STATIC; - if (!label.v) { - label.v = tok_alloc(".T0 ", 4)->tok; - label.type.t = VT_VOID | VT_STATIC; - } vpushv(sv); vtop->r = r1 = get_reg(RC_INT); r2 = get_reg(RC_INT); r1 = ireg(r1); r2 = ireg(r2); greloca(cur_text_section, sv->sym, ind, R_RISCV_PCREL_HI20, 0); - label.c = 0; /* force new local ELF symbol */ put_extern_sym(&label, cur_text_section, ind, 0); o(0x17 | (r1 << 7)); // auipc RR, 0 %pcrel_hi(sym) greloca(cur_text_section, &label, ind, R_RISCV_PCREL_LO12_I, 0); diff --git a/tcc.h b/tcc.h index da34abfe..7879d6ea 100644 --- a/tcc.h +++ b/tcc.h @@ -764,7 +764,6 @@ struct TCCState { unsigned char leading_underscore; unsigned char ms_extensions; /* allow nested named struct w/o identifier behave like unnamed */ unsigned char dollars_in_identifiers; /* allows '$' char in identifiers */ - unsigned char test_coverage; /* generate test coverage code */ unsigned char ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */ /* warning switches */ @@ -782,6 +781,8 @@ struct TCCState { /* compile with built-in memory and bounds checker */ unsigned char do_bounds_check; #endif + unsigned char test_coverage; /* generate test coverage code */ + #ifdef TCC_TARGET_ARM enum float_abi float_abi; /* float ABI of the generated code*/ #endif @@ -1447,6 +1448,7 @@ ST_DATA Sym *define_stack; ST_DATA CType int_type, func_old_type, char_pointer_type; ST_DATA SValue *vtop; ST_DATA int rsym, anon_sym, ind, loc; +ST_DATA char debug_modes; ST_DATA int const_wanted; /* true if constant wanted */ ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */ @@ -1461,9 +1463,7 @@ ST_FUNC void tcc_debug_end(TCCState *s1); ST_FUNC void tcc_debug_bincl(TCCState *s1); ST_FUNC void tcc_debug_eincl(TCCState *s1); ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename); -ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym); -ST_FUNC void tcc_debug_funcend(TCCState *s1, int size); -ST_FUNC void tcc_debug_line(TCCState *s1); +ST_FUNC void tcc_add_tcov(TCCState *s1); ST_FUNC void tccgen_init(TCCState *s1); ST_FUNC int tccgen_compile(TCCState *s1); diff --git a/tccelf.c b/tccelf.c index 4c574391..2b73d72a 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1419,7 +1419,7 @@ ST_FUNC void tcc_add_btstub(TCCState *s1) cstr_printf(&cstr, "__bt_init_dll(0);"); #endif #endif - cstr_printf(&cstr, "__bt_init(__rt_info,%d, 0);}", + cstr_printf(&cstr, "__bt_init(__rt_info,%d);}", s1->output_type == TCC_OUTPUT_DLL ? 0 : s1->rt_num_callers + 1); tcc_compile_string(s1, cstr.data); cstr_free(&cstr); @@ -1450,7 +1450,7 @@ static void tcc_tcov_add_file(TCCState *s1, const char *filename) cstr_free (&cstr); } -static void tcc_add_tcov(TCCState *s1) +ST_FUNC void tcc_add_tcov(TCCState *s1) { CString cstr; diff --git a/tccgen.c b/tccgen.c index 2728af45..93ae3ab6 100644 --- a/tccgen.c +++ b/tccgen.c @@ -46,15 +46,12 @@ static int local_scope; static int in_sizeof; static int in_generic; static int section_sym; +ST_DATA char debug_modes; ST_DATA SValue *vtop; static SValue _vstack[1 + VSTACK_SIZE]; #define vstack (_vstack + 1) -static void tcc_tcov_block_begin(void); -static void tcc_tcov_block_end(int line); -static void tcc_tcov_check_line(int start); - ST_DATA int const_wanted; /* true if constant wanted */ ST_DATA int nocode_wanted; /* no code generation wanted */ #define unevalmask 0xffff /* unevaluated subexpression */ @@ -65,9 +62,11 @@ ST_DATA int nocode_wanted; /* no code generation wanted */ #define CODE_OFF() (nocode_wanted |= 0x20000000) #define CODE_ON() (nocode_wanted &= ~0x20000000) +static void tcc_tcov_block_begin(void); + /* Clear 'nocode_wanted' at label if it was used */ ST_FUNC void gsym(int t) { if (t) { gsym_addr(t, ind); CODE_ON(); }} -static int gind(void) { int t; CODE_ON(); t = ind; tcc_tcov_block_begin(); return t; } +static int gind(void) { int t = ind; CODE_ON(); if (debug_modes) tcc_tcov_block_begin(); return t; } /* Set 'nocode_wanted' after unconditional jumps */ static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); } @@ -214,7 +213,6 @@ static struct { unsigned long last_func_name; int ind; int line; - Sym label; } tcov_data; /********************************************************/ @@ -460,6 +458,74 @@ ST_FUNC void tcc_debug_start(TCCState *s1) SHN_ABS, file->filename); } +/* put end of translation unit info */ +ST_FUNC void tcc_debug_end(TCCState *s1) +{ + if (!s1->do_debug) + return; + put_stabs_r(s1, NULL, N_SO, 0, 0, + text_section->data_offset, text_section, section_sym); + tcc_free(debug_hash); +} + +static BufferedFile* put_new_file(TCCState *s1) +{ + BufferedFile *f = file; + /* use upper file if from inline ":asm:" */ + if (f->filename[0] == ':') + f = f->prev; + if (f && new_file) { + put_stabs_r(s1, f->filename, N_SOL, 0, 0, ind, text_section, section_sym); + new_file = last_line_num = 0; + } + return f; +} + +/* put alternative filename */ +ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename) +{ + if (0 == strcmp(file->filename, filename)) + return; + pstrcpy(file->filename, sizeof(file->filename), filename); + new_file = 1; +} + +/* begin of #include */ +ST_FUNC void tcc_debug_bincl(TCCState *s1) +{ + if (!s1->do_debug) + return; + put_stabs(s1, file->filename, N_BINCL, 0, 0, 0); + new_file = 1; +} + +/* end of #include */ +ST_FUNC void tcc_debug_eincl(TCCState *s1) +{ + if (!s1->do_debug) + return; + put_stabn(s1, N_EINCL, 0, 0, 0); + new_file = 1; +} + +/* generate line number info */ +static void tcc_debug_line(TCCState *s1) +{ + BufferedFile *f; + if (!s1->do_debug + || cur_text_section != text_section + || !(f = put_new_file(s1)) + || last_line_num == f->line_num) + return; + if (func_ind != -1) { + put_stabn(s1, N_SLINE, 0, f->line_num, ind - func_ind); + } else { + /* from tcc_assemble */ + put_stabs_r(s1, NULL, N_SLINE, 0, f->line_num, ind, text_section, section_sym); + } + last_line_num = f->line_num; +} + static void tcc_debug_stabs (TCCState *s1, const char *str, int type, unsigned long value, Section *sec, int sym_index) { @@ -483,8 +549,10 @@ static void tcc_debug_stabs (TCCState *s1, const char *str, int type, unsigned l put_stabs (s1, str, type, 0, 0, value); } -static void tcc_debug_stabn(int type, int value) +static void tcc_debug_stabn(TCCState *s1, int type, int value) { + if (!s1->do_debug) + return; if (type == N_LBRAC) { struct debug_info *info = (struct debug_info *) tcc_mallocz(sizeof (*info)); @@ -659,6 +727,8 @@ static void tcc_debug_finish (TCCState *s1, struct debug_info *cur) static void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e) { CString debug_str; + if (!s1->do_debug) + return; cstr_new (&debug_str); for (; s != e; s = s->prev) { if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL) @@ -671,11 +741,48 @@ static void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e) cstr_free (&debug_str); } -static void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bind) +/* put function symbol */ +static void tcc_debug_funcstart(TCCState *s1, Sym *sym) { - Section *s = s1->sections[sh_num]; + CString debug_str; + BufferedFile *f; + if (!s1->do_debug) + return; + debug_info_root = NULL; + debug_info = NULL; + tcc_debug_stabn(s1, N_LBRAC, ind - func_ind); + if (!(f = put_new_file(s1))) + return; + cstr_new (&debug_str); + cstr_printf(&debug_str, "%s:%c", funcname, sym->type.t & VT_STATIC ? 'f' : 'F'); + tcc_get_debug_info(s1, sym->type.ref, &debug_str); + put_stabs_r(s1, debug_str.data, N_FUN, 0, f->line_num, 0, cur_text_section, sym->c); + cstr_free (&debug_str); + + tcc_debug_line(s1); +} + +/* put function size */ +static void tcc_debug_funcend(TCCState *s1, int size) +{ + if (!s1->do_debug) + return; + tcc_debug_stabn(s1, N_RBRAC, size); + tcc_debug_finish (s1, debug_info_root); +} + + +static void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bind, int sym_type) +{ + Section *s; CString str; + if (!s1->do_debug) + return; + if (sym_type == STT_FUNC || sym->v >= SYM_FIRST_ANOM) + return; + s = s1->sections[sh_num]; + cstr_new (&str); cstr_printf (&str, "%s:%c", get_tok_str(sym->v, NULL), @@ -695,6 +802,8 @@ static void tcc_debug_typedef(TCCState *s1, Sym *sym) { CString str; + if (!s1->do_debug) + return; cstr_new (&str); cstr_printf (&str, "%s:t", (sym->v & ~SYM_FIELD) >= SYM_FIRST_ANOM @@ -704,17 +813,11 @@ static void tcc_debug_typedef(TCCState *s1, Sym *sym) cstr_free (&str); } -/* put end of translation unit info */ -ST_FUNC void tcc_debug_end(TCCState *s1) -{ - if (!s1->do_debug) - return; - put_stabs_r(s1, NULL, N_SO, 0, 0, - text_section->data_offset, text_section, section_sym); - tcc_free(debug_hash); -} - +/* ------------------------------------------------------------------------- */ /* for section layout see lib/tcov.c */ + +static void tcc_tcov_block_end(int line); + static void tcc_tcov_block_begin(void) { SValue sv; @@ -764,21 +867,19 @@ static void tcc_tcov_block_begin(void) if (ind == tcov_data.ind && tcov_data.line == file->line_num) tcov_data.offset = tcov_data.last_offset; else { - if (!tcov_data.label.v) { - tcov_data.label.v = tok_alloc(".TCOV ", 6)->tok; - tcov_data.label.type.t = VT_LLONG | VT_STATIC; - } - tcov_data.label.c = 0; /* force new local ELF symbol */ + Sym label = {0}; + label.type.t = VT_LLONG | VT_STATIC; + ptr = section_ptr_add(tcov_section, 16); tcov_data.line = file->line_num; write64le (ptr, (tcov_data.line << 8) | 0xff); - put_extern_sym(&tcov_data.label, tcov_section, + put_extern_sym(&label, tcov_section, ((unsigned char *)ptr - tcov_section->data) + 8, 0); - sv.type = tcov_data.label.type; + sv.type = label.type; sv.r = VT_SYM | VT_LVAL | VT_CONST; sv.r2 = VT_CONST; sv.c.i = 0; - sv.sym = &tcov_data.label; + sv.sym = &label; #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || \ defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 || \ defined TCC_TARGET_RISCV64 @@ -844,94 +945,6 @@ static void tcc_tcov_end(void) section_ptr_add(tcov_section, 1); } -static BufferedFile* put_new_file(TCCState *s1) -{ - BufferedFile *f = file; - /* use upper file if from inline ":asm:" */ - if (f->filename[0] == ':') - f = f->prev; - if (f && new_file) { - put_stabs_r(s1, f->filename, N_SOL, 0, 0, ind, text_section, section_sym); - new_file = last_line_num = 0; - } - return f; -} - -/* generate line number info */ -ST_FUNC void tcc_debug_line(TCCState *s1) -{ - BufferedFile *f; - if (!s1->do_debug - || cur_text_section != text_section - || !(f = put_new_file(s1)) - || last_line_num == f->line_num) - return; - if (func_ind != -1) { - put_stabn(s1, N_SLINE, 0, f->line_num, ind - func_ind); - } else { - /* from tcc_assemble */ - put_stabs_r(s1, NULL, N_SLINE, 0, f->line_num, ind, text_section, section_sym); - } - last_line_num = f->line_num; -} - -/* put function symbol */ -ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym) -{ - CString debug_str; - BufferedFile *f; - if (!s1->do_debug) - return; - debug_info_root = NULL; - debug_info = NULL; - tcc_debug_stabn(N_LBRAC, ind - func_ind); - if (!(f = put_new_file(s1))) - return; - cstr_new (&debug_str); - cstr_printf(&debug_str, "%s:%c", funcname, sym->type.t & VT_STATIC ? 'f' : 'F'); - tcc_get_debug_info(s1, sym->type.ref, &debug_str); - put_stabs_r(s1, debug_str.data, N_FUN, 0, f->line_num, 0, cur_text_section, sym->c); - cstr_free (&debug_str); - - tcc_debug_line(s1); -} - -/* put function size */ -ST_FUNC void tcc_debug_funcend(TCCState *s1, int size) -{ - if (!s1->do_debug) - return; - tcc_debug_stabn(N_RBRAC, size); - tcc_debug_finish (s1, debug_info_root); -} - -/* put alternative filename */ -ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename) -{ - if (0 == strcmp(file->filename, filename)) - return; - pstrcpy(file->filename, sizeof(file->filename), filename); - new_file = 1; -} - -/* begin of #include */ -ST_FUNC void tcc_debug_bincl(TCCState *s1) -{ - if (!s1->do_debug) - return; - put_stabs(s1, file->filename, N_BINCL, 0, 0, 0); - new_file = 1; -} - -/* end of #include */ -ST_FUNC void tcc_debug_eincl(TCCState *s1) -{ - if (!s1->do_debug) - return; - put_stabn(s1, N_EINCL, 0, 0, 0); - new_file = 1; -} - /* ------------------------------------------------------------------------- */ /* initialize vstack and types. This must be done also for tcc -E */ ST_FUNC void tccgen_init(TCCState *s1) @@ -967,6 +980,7 @@ ST_FUNC int tccgen_compile(TCCState *s1) const_wanted = 0; nocode_wanted = 0x80000000; local_scope = 0; + debug_modes = s1->do_debug | s1->test_coverage << 1; tcc_debug_start(s1); tcc_tcov_start (); @@ -1111,10 +1125,8 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, info = ELFW(ST_INFO)(sym_bind, sym_type); sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name); - if (tcc_state->do_debug - && sym_type != STT_FUNC - && sym->v < SYM_FIRST_ANOM) - tcc_debug_extern_sym(tcc_state, sym, sh_num, sym_bind); + if (debug_modes) + tcc_debug_extern_sym(tcc_state, sym, sh_num, sym_bind, sym_type); } else { esym = elfsym(sym); @@ -2188,15 +2200,15 @@ static void add_local_bounds(Sym *s, Sym *e) #endif /* Wrapper around sym_pop, that potentially also registers local bounds. */ -static void pop_local_syms(Sym **ptop, Sym *b, int keep, int ellipsis) +static void pop_local_syms(Sym *b, int keep) { #ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check && !ellipsis && !keep) - add_local_bounds(*ptop, b); + if (tcc_state->do_bounds_check && !keep && (local_scope || !func_var)) + add_local_bounds(local_stack, b); #endif - if (tcc_state->do_debug) - tcc_add_debug_info (tcc_state, !local_scope, *ptop, b); - sym_pop(ptop, b, keep); + if (debug_modes) + tcc_add_debug_info (tcc_state, !local_scope, local_stack, b); + sym_pop(&local_stack, b, keep); } static void incr_bf_adr(int o) @@ -2246,7 +2258,6 @@ static void load_packed_bf(CType *type, int bit_pos, int bit_size) static void store_packed_bf(int bit_pos, int bit_size) { int bits, n, o, m, c; - c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; vswap(); // X B save_reg_upstack(vtop->r, 1); @@ -4727,10 +4738,12 @@ static void struct_layout(CType *type, AttributeDef *ad) continue; bit_pos = BIT_POS(f->type.t); size = type_size(&f->type, &align); - if (c & 3) /* packed struct */ - goto single_byte; - if (bit_pos + bit_size <= size * 8 && f->c + size <= c && - (f->c & (align - 1)) == 0) + + if (bit_pos + bit_size <= size * 8 && f->c + size <= c +#ifdef TCC_TARGET_ARM + && !(f->c & (align - 1)) +#endif + ) continue; /* try to access the field using a different type */ @@ -4756,7 +4769,11 @@ static void struct_layout(CType *type, AttributeDef *ad) c0 = cx; } - if (px + bit_size <= s * 8 && cx + s <= c) { + if (px + bit_size <= s * 8 && cx + s <= c +#ifdef TCC_TARGET_ARM + && !(cx & (align - 1)) +#endif + ) { /* update offset and bit position */ f->c = cx; bit_pos = px; @@ -4771,7 +4788,6 @@ static void struct_layout(CType *type, AttributeDef *ad) cx, s, align, px, bit_size); #endif } else { -single_byte: /* fall back to load/store single-byte wise */ f->auxtype = VT_STRUCT; #ifdef BF_DEBUG @@ -5696,9 +5712,8 @@ ST_FUNC void unary(void) AttributeDef ad; /* generate line number info */ - if (tcc_state->do_debug) - tcc_debug_line(tcc_state); - tcc_tcov_check_line (1); + if (debug_modes) + tcc_debug_line(tcc_state), tcc_tcov_check_line (1); sizeof_caller = in_sizeof; in_sizeof = 0; @@ -6419,7 +6434,8 @@ special_math_val: } } if (s->f.func_noreturn) { - tcc_tcov_block_end (tcov_data.line); + if (debug_modes) + tcc_tcov_block_end (tcov_data.line); CODE_OFF(); } } else { @@ -6678,13 +6694,6 @@ static void expr_cond(void) if (!g) gexpr(); - if (c < 0 && vtop->r == VT_CMP) { - t1 = gvtst(0, 0); - vpushi(0); - gvtst_set(0, t1); - gv(RC_INT); - } - if ((vtop->type.t & VT_BTYPE) == VT_FUNC) mk_pointer(&vtop->type); sv = *vtop; /* save value to handle it later */ @@ -6705,15 +6714,14 @@ static void expr_cond(void) expr_cond(); if (c < 0 && is_cond_bool(vtop) && is_cond_bool(&sv)) { - if (sv.r == VT_CMP) { - t1 = sv.jtrue; - t2 = u; - } else { - t1 = gvtst(0, 0); - t2 = gjmp(0); - gsym(u); - vpushv(&sv); - } + /* optimize "if (f ? a > b : c || d) ..." for example, where normally + "a < b" and "c || d" would be forced to "(int)0/1" first, whereas + this code jumps directly to the if's then/else branches. */ + t1 = gvtst(0, 0); + t2 = gjmp(0); + gsym(u); + vpushv(&sv); + /* combine jump targets of 2nd op with VT_CMP of 1st op */ gvtst_set(0, t1); gvtst_set(1, t2); nocode_wanted = ncw_prev; @@ -7099,11 +7107,10 @@ void new_scope(struct scope *o) /* record local declaration stack position */ o->lstk = local_stack; o->llstk = local_label_stack; - ++local_scope; - if (tcc_state->do_debug) - tcc_debug_stabn(N_LBRAC, ind - func_ind); + if (debug_modes) + tcc_debug_stabn(tcc_state, N_LBRAC, ind - func_ind); } void prev_scope(struct scope *o, int is_expr) @@ -7125,12 +7132,12 @@ void prev_scope(struct scope *o, int is_expr) tables, though. sym_pop will do that. */ /* pop locally defined symbols */ - pop_local_syms(&local_stack, o->lstk, is_expr, 0); + pop_local_syms(o->lstk, is_expr); cur_scope = o->prev; --local_scope; - if (tcc_state->do_debug) - tcc_debug_stabn(N_RBRAC, ind - func_ind); + if (debug_modes) + tcc_debug_stabn(tcc_state, N_RBRAC, ind - func_ind); } /* leave a scope via break/continue(/goto) */ @@ -7182,8 +7189,9 @@ again: goto expr; next(); - tcc_tcov_check_line (0); - tcc_tcov_block_begin (); + if (debug_modes) + tcc_tcov_check_line (0), tcc_tcov_block_begin (); + if (t == TOK_IF) { skip('('); gexpr(); @@ -7264,7 +7272,8 @@ again: /* jump unless last stmt in top-level block */ if (tok != '}' || local_scope != 1) rsym = gjmp(rsym); - tcc_tcov_block_end (tcov_data.line); + if (debug_modes) + tcc_tcov_block_end (tcov_data.line); CODE_OFF(); } else if (t == TOK_BREAK) { @@ -7498,8 +7507,9 @@ again: } } } - tcc_tcov_check_line (0); - tcc_tcov_block_end (0); + + if (debug_modes) + tcc_tcov_check_line (0), tcc_tcov_block_end (0); } /* This skips over a stream of tokens containing balanced {} and () @@ -7779,6 +7789,7 @@ static void init_putv(init_params *p, CType *type, unsigned long c) CType dtype; int size, align; Section *sec = p->sec; + uint64_t val; dtype = *type; dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */ @@ -7796,7 +7807,6 @@ static void init_putv(init_params *p, CType *type, unsigned long c) if ((vtop->r & VT_SYM) && bt != VT_PTR - && bt != VT_FUNC && (bt != (PTR_SIZE == 8 ? VT_LLONG : VT_INT) || (type->t & VT_BITFIELD)) && !((vtop->r & VT_CONST) && vtop->sym->v >= SYM_FIRST_ANOM) @@ -7809,6 +7819,7 @@ static void init_putv(init_params *p, CType *type, unsigned long c) } ptr = sec->data + c; + val = vtop->c.i; /* XXX: make code faster ? */ if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) && @@ -7868,33 +7879,38 @@ static void init_putv(init_params *p, CType *type, unsigned long c) n = 8 - bit_pos; if (n > bit_size) n = bit_size; - v = vtop->c.i >> bits << bit_pos; + v = val >> bits << bit_pos; m = ((1 << n) - 1) << bit_pos; *p = (*p & ~m) | (v & m); bits += n, bit_size -= n, bit_pos = 0, ++p; } } else switch(bt) { - /* XXX: when cross-compiling we assume that each type has the - same representation on host and target, which is likely to - be wrong in the case of long double */ case VT_BOOL: - vtop->c.i = vtop->c.i != 0; + *(char *)ptr = val != 0; + break; case VT_BYTE: - *(char *)ptr = vtop->c.i; + *(char *)ptr = val; break; case VT_SHORT: - *(short *)ptr = vtop->c.i; + write16le(ptr, val); break; case VT_FLOAT: - *(float*)ptr = vtop->c.f; + write32le(ptr, val); break; case VT_DOUBLE: - *(double *)ptr = vtop->c.d; + write64le(ptr, val); break; case VT_LDOUBLE: #if defined TCC_IS_NATIVE_387 - if (sizeof (long double) >= 10) /* zero pad ten-byte LD */ + /* Host and target platform may be different but both have x87. + On windows, tcc does not use VT_LDOUBLE, except when it is a + cross compiler. In this case a mingw gcc as host compiler + comes here with 10-byte long doubles, while msvc or tcc won't. + tcc itself can still translate by asm. + In any case we avoid possibly random bytes 11 and 12. + */ + if (sizeof (long double) >= 10) memcpy(ptr, &vtop->c.ld, 10); #ifdef __TINYC__ else if (sizeof (long double) == sizeof (double)) @@ -7904,52 +7920,44 @@ static void init_putv(init_params *p, CType *type, unsigned long c) ; else #endif + /* For other platforms it should work natively, but may not work + for cross compilers */ if (sizeof(long double) == LDOUBLE_SIZE) - *(long double*)ptr = vtop->c.ld; + memcpy(ptr, &vtop->c.ld, LDOUBLE_SIZE); else if (sizeof(double) == LDOUBLE_SIZE) - *(double *)ptr = (double)vtop->c.ld; + memcpy(ptr, &vtop->c.ld, LDOUBLE_SIZE); #ifndef TCC_CROSS_TEST else tcc_error("can't cross compile long double constants"); #endif break; -#if PTR_SIZE != 8 + +#if PTR_SIZE == 8 + /* intptr_t may need a reloc too, see tcctest.c:relocation_test() */ case VT_LLONG: - *(long long *)ptr = vtop->c.i; - break; -#else - case VT_LLONG: -#endif case VT_PTR: - { - addr_t val = vtop->c.i; -#if PTR_SIZE == 8 - if (vtop->r & VT_SYM) - greloca(sec, vtop->sym, c, R_DATA_PTR, val); - else - *(addr_t *)ptr = val; + if (vtop->r & VT_SYM) + greloca(sec, vtop->sym, c, R_DATA_PTR, val); + else + write64le(ptr, val); + break; + case VT_INT: + write32le(ptr, val); + break; #else - if (vtop->r & VT_SYM) - greloc(sec, vtop->sym, c, R_DATA_PTR); - *(addr_t *)ptr = val; + case VT_LLONG: + write64le(ptr, val); + break; + case VT_PTR: + case VT_INT: + if (vtop->r & VT_SYM) + greloc(sec, vtop->sym, c, R_DATA_PTR); + write32le(ptr, val); + break; #endif - break; - } default: - { - int val = vtop->c.i; -#if PTR_SIZE == 8 - if (vtop->r & VT_SYM) - greloca(sec, vtop->sym, c, R_DATA_PTR, val); - else - *(int *)ptr = val; -#else - if (vtop->r & VT_SYM) - greloc(sec, vtop->sym, c, R_DATA_PTR); - *(int *)ptr = val; -#endif - break; - } + //tcc_internal_error("unexpected type"); + break; } } vtop--; @@ -7975,9 +7983,8 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f CType *t1; /* generate line number info */ - if (!p->sec && tcc_state->do_debug) - tcc_debug_line(tcc_state); - tcc_tcov_check_line (1); + if (debug_modes && !p->sec) + tcc_debug_line(tcc_state), tcc_tcov_check_line (1); if (!(flags & DIF_HAVE_ELEM) && tok != '{' && /* In case of strings we have special handling for arrays, so @@ -8453,7 +8460,7 @@ static void gen_function(Sym *sym) gsym(rsym); nocode_wanted = 0; /* reset local stack */ - pop_local_syms(&local_stack, NULL, 0, func_var); + pop_local_syms(NULL, 0); gfunc_epilog(); cur_text_section->data_offset = ind; local_scope = 0; @@ -8737,7 +8744,7 @@ found: } sym->a = ad.a; sym->f = ad.f; - if (tcc_state->do_debug) + if (debug_modes) tcc_debug_typedef (tcc_state, sym); } else if ((type.t & VT_BTYPE) == VT_VOID && !(type.t & VT_EXTERN)) { diff --git a/tccpp.c b/tccpp.c index e5970375..b21210d2 100644 --- a/tccpp.c +++ b/tccpp.c @@ -358,18 +358,11 @@ char *unicode_to_utf8 (char *b, uint32_t Uc) /* add a unicode character expanded into utf8 */ void cstr_u8cat(CString *cstr, int ch) { - unsigned char buf[4]; - int size; - int add = (int)((unsigned char*)unicode_to_utf8((char *)&buf[0],(uint32_t)ch) - &buf[0]); - unsigned char *p,*b=buf; - size = cstr->size + add; - if (size > cstr->size_allocated) - cstr_realloc(cstr, size); - for(p = (unsigned char*)cstr->data + (size - add); add; add--) *p++=*b++; - cstr->size = size; + char buf[4], *e; + e = unicode_to_utf8(buf, (uint32_t)ch); + cstr_cat(cstr, buf, e - buf); } - ST_FUNC void cstr_cat(CString *cstr, const char *str, int len) { int size; @@ -617,6 +610,7 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv) } addv: *p++ = v; + case 0: /* nameless anonymous symbol */ *p = '\0'; } else if (v < tok_ident) { return table_ident[v - TOK_IDENT]->str; @@ -2095,7 +2089,7 @@ include_done: /* evaluate escape codes in a string. */ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long) { - int c, n; + int c, n, i; const uint8_t *p; p = buf; @@ -2125,13 +2119,13 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long } c = n; goto add_char_nonext; - case 'x': { unsigned int i; unsigned ucn_chars_nr = -1u; goto parse_hex_or_ucn; - case 'u': ucn_chars_nr = 4; goto parse_hex_or_ucn; - case 'U': ucn_chars_nr = 8; goto parse_hex_or_ucn; - parse_hex_or_ucn:; + case 'x': i = 0; goto parse_hex_or_ucn; + case 'u': i = 4; goto parse_hex_or_ucn; + case 'U': i = 8; goto parse_hex_or_ucn; + parse_hex_or_ucn: p++; n = 0; - for(i=1;i<=ucn_chars_nr;i++) { + do { c = *p; if (c >= 'a' && c <= 'f') c = c - 'a' + 10; @@ -2139,19 +2133,17 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long c = c - 'A' + 10; else if (isnum(c)) c = c - '0'; - else{ - if (ucn_chars_nr!=-1) - tcc_error("%u hex digits expected in universal-character-name\n", ucn_chars_nr); - break; + else if (i > 0) + expect("more hex digits in universal-character-name"); + else { + c = n; + goto add_char_nonext; } n = n * 16 + c; p++; - } - c = n; - if(ucn_chars_nr==-1) goto add_char_nonext; - cstr_u8cat(outstr, c); + } while (--i); + cstr_u8cat(outstr, n); continue; - } case 'a': c = '\a'; break; diff --git a/tccrun.c b/tccrun.c index 954f312f..1d753b0e 100644 --- a/tccrun.c +++ b/tccrun.c @@ -183,7 +183,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) #ifdef CONFIG_TCC_BCHECK if (s1->do_bounds_check) { if ((p = tcc_get_symbol(s1, "__bound_init"))) - ((void(*)(void*, int))p)(bounds_section->data, 1); + ((void(*)(addr_t, int))p)(bounds_section->sh_addr, 1); } #endif set_exception_handler(); diff --git a/tcctok.h b/tcctok.h index 6fc04af7..390eca36 100644 --- a/tcctok.h +++ b/tcctok.h @@ -100,8 +100,10 @@ DEF(TOK___NAN__, "__nan__") DEF(TOK___SNAN__, "__snan__") DEF(TOK___INF__, "__inf__") - DEF(TOK___mzerosf, "__mzerosf") - DEF(TOK___mzerodf, "__mzerodf") +#if defined TCC_TARGET_X86_64 + DEF(TOK___mzerosf, "__mzerosf") /* -0.0 */ + DEF(TOK___mzerodf, "__mzerodf") /* -0.0 */ +#endif /* attribute identifiers */ /* XXX: handle all tokens generically since speed is not critical */ diff --git a/tests/tcctest.c b/tests/tcctest.c index de2546f9..800c4cce 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -2830,9 +2830,6 @@ int reltab[3] = { 1, 2, 3 }; int *rel1 = &reltab[1]; int *rel2 = &reltab[2]; -#ifdef _WIN64 -void relocation_test(void) {} -#else void getmyaddress(void) { printf("in getmyaddress\n"); @@ -2850,7 +2847,7 @@ long __pa_symbol(void) } #endif -unsigned long theaddress = (unsigned long)getmyaddress; +uintptr_t theaddress = (uintptr_t)getmyaddress; void relocation_test(void) { void (*fptr)(void) = (void (*)(void))theaddress; @@ -2861,7 +2858,6 @@ void relocation_test(void) printf("pa_symbol=0x%lx\n", __pa_symbol() >> 63); #endif } -#endif void old_style_f(a,b,c) int a, b;