debug_modes, re-unalign, cleanups

tccgen.c: debug_modes
- don't waste debug function calls during normal execution.
libtcc.c:
- mem_debug: no C99 features in tcc please, for example
  ({compound expressions}): do not use.
tccgen.c: struct_layout:
- unaligned access is completely ok for most targets.
- Moreover the patch was triggering single byte mode even
  for normal aligned access (as with tcc's SymAttr)

static Sym label: don't do this

arm-gen.c:
- use some #ifdefs to explain some code
tccpp.c:
- cleanup UCN chars
libtcc.c:
- replace openbsd library search
configure:
- cleanup strip fallouts
tccgen.c:
- expr_cond(): remove an exotic optimization that eventually
  got fixed to do the contrary by a gv(RC_InT)
- pop_local_syms(): remove some args
- init_putv() : use write##le functions to avoid cross-compiler
  unaligned access
- __bt_init(): remove unused param 'mode'
This commit is contained in:
grischka 2021-01-24 16:20:48 +01:00
parent 5043268cb1
commit 1ed4b6ba1a
13 changed files with 356 additions and 419 deletions

View file

@ -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

View file

@ -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);

53
configure vendored Executable file → Normal file
View file

@ -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"

View file

@ -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;

156
libtcc.c
View file

@ -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 <glob.h>
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 <dirent.h>
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) {

View file

@ -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);

8
tcc.h
View file

@ -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);

View file

@ -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;

433
tccgen.c
View file

@ -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)) {

42
tccpp.c
View file

@ -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;

View file

@ -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();

View file

@ -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 */

View file

@ -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;