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:
parent
5043268cb1
commit
1ed4b6ba1a
13 changed files with 356 additions and 419 deletions
4
Makefile
4
Makefile
|
@ -12,8 +12,6 @@ ifeq ($(findstring $(MAKECMDGOALS),clean distclean),)
|
||||||
include $(TOP)/config.mak
|
include $(TOP)/config.mak
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CONFIG_strip = no
|
|
||||||
|
|
||||||
ifeq (-$(GCC_MAJOR)-$(findstring $(GCC_MINOR),56789)-,-4--)
|
ifeq (-$(GCC_MAJOR)-$(findstring $(GCC_MINOR),56789)-,-4--)
|
||||||
CFLAGS += -D_FORTIFY_SOURCE=0
|
CFLAGS += -D_FORTIFY_SOURCE=0
|
||||||
endif
|
endif
|
||||||
|
@ -221,7 +219,7 @@ $(TCC_FILES) : DEFINES += -DONE_SOURCE=0
|
||||||
$(X)tccpp.o : $(TCCDEFS_H)
|
$(X)tccpp.o : $(TCCDEFS_H)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_strip),no)
|
ifeq ($(CONFIG_debug),yes)
|
||||||
CFLAGS += -g
|
CFLAGS += -g
|
||||||
LDFLAGS += -g
|
LDFLAGS += -g
|
||||||
else
|
else
|
||||||
|
|
26
arm-gen.c
26
arm-gen.c
|
@ -541,8 +541,13 @@ static int negcc(int cc)
|
||||||
Use relative/got addressing to avoid setting DT_TEXTREL */
|
Use relative/got addressing to avoid setting DT_TEXTREL */
|
||||||
static void load_value(SValue *sv, int r)
|
static void load_value(SValue *sv, int r)
|
||||||
{
|
{
|
||||||
o(0xE59F0000|(intr(r)<<12));
|
o(0xE59F0000|(intr(r)<<12)); /* ldr r, [pc] */
|
||||||
o(0xEA000000);
|
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->r & VT_SYM) {
|
||||||
if (sv->sym->type.t & VT_STATIC) {
|
if (sv->sym->type.t & VT_STATIC) {
|
||||||
greloc(cur_text_section, sv->sym, ind, R_ARM_REL32);
|
greloc(cur_text_section, sv->sym, ind, R_ARM_REL32);
|
||||||
|
@ -561,6 +566,7 @@ static void load_value(SValue *sv, int r)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
o(sv->c.i);
|
o(sv->c.i);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load 'r' from value 'sv' */
|
/* load 'r' from value 'sv' */
|
||||||
|
@ -1731,11 +1737,13 @@ void gen_opi(int op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fr=intr(gv(RC_INT));
|
fr=intr(gv(RC_INT));
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
||||||
vswap();
|
vswap();
|
||||||
c=intr(gv(RC_INT));
|
c=intr(gv(RC_INT));
|
||||||
vswap();
|
vswap();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if ((opc & 0xfff00000) == 0xe1500000) // cmp rx,ry
|
if ((opc & 0xfff00000) == 0xe1500000) // cmp rx,ry
|
||||||
o(opc|(c<<16)|fr);
|
o(opc|(c<<16)|fr);
|
||||||
else {
|
else {
|
||||||
|
@ -1761,11 +1769,13 @@ done:
|
||||||
o(opc|r|(c<<7)|(fr<<12));
|
o(opc|r|(c<<7)|(fr<<12));
|
||||||
} else {
|
} else {
|
||||||
fr=intr(gv(RC_INT));
|
fr=intr(gv(RC_INT));
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
||||||
vswap();
|
vswap();
|
||||||
r=intr(gv(RC_INT));
|
r=intr(gv(RC_INT));
|
||||||
vswap();
|
vswap();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
|
c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r)));
|
||||||
o(opc|r|(c<<12)|(fr<<8)|0x10);
|
o(opc|r|(c<<12)|(fr<<8)|0x10);
|
||||||
}
|
}
|
||||||
|
@ -1877,12 +1887,14 @@ void gen_opf(int op)
|
||||||
r2=gv(RC_FLOAT);
|
r2=gv(RC_FLOAT);
|
||||||
x|=vfpr(r2)<<16;
|
x|=vfpr(r2)<<16;
|
||||||
r|=regmask(r2);
|
r|=regmask(r2);
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
||||||
vswap();
|
vswap();
|
||||||
r=gv(RC_FLOAT);
|
r=gv(RC_FLOAT);
|
||||||
vswap();
|
vswap();
|
||||||
x=(x&~0xf)|vfpr(r);
|
x=(x&~0xf)|vfpr(r);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
vtop->r=get_reg_ex(RC_FLOAT,r);
|
vtop->r=get_reg_ex(RC_FLOAT,r);
|
||||||
if(!fneg)
|
if(!fneg)
|
||||||
|
@ -1965,11 +1977,13 @@ void gen_opf(int op)
|
||||||
r2=c2&0xf;
|
r2=c2&0xf;
|
||||||
} else {
|
} else {
|
||||||
r2=fpr(gv(RC_FLOAT));
|
r2=fpr(gv(RC_FLOAT));
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
||||||
vswap();
|
vswap();
|
||||||
r=fpr(gv(RC_FLOAT));
|
r=fpr(gv(RC_FLOAT));
|
||||||
vswap();
|
vswap();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '-':
|
case '-':
|
||||||
|
@ -1991,11 +2005,13 @@ void gen_opf(int op)
|
||||||
r=fpr(gv(RC_FLOAT));
|
r=fpr(gv(RC_FLOAT));
|
||||||
vswap();
|
vswap();
|
||||||
r2=fpr(gv(RC_FLOAT));
|
r2=fpr(gv(RC_FLOAT));
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
||||||
vswap();
|
vswap();
|
||||||
r=fpr(gv(RC_FLOAT));
|
r=fpr(gv(RC_FLOAT));
|
||||||
vswap();
|
vswap();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '*':
|
case '*':
|
||||||
|
@ -2010,11 +2026,13 @@ void gen_opf(int op)
|
||||||
r2=c2;
|
r2=c2;
|
||||||
else {
|
else {
|
||||||
r2=fpr(gv(RC_FLOAT));
|
r2=fpr(gv(RC_FLOAT));
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
||||||
vswap();
|
vswap();
|
||||||
r=fpr(gv(RC_FLOAT));
|
r=fpr(gv(RC_FLOAT));
|
||||||
vswap();
|
vswap();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
x|=0x100000; // muf
|
x|=0x100000; // muf
|
||||||
break;
|
break;
|
||||||
|
@ -2036,11 +2054,13 @@ void gen_opf(int op)
|
||||||
r=fpr(gv(RC_FLOAT));
|
r=fpr(gv(RC_FLOAT));
|
||||||
vswap();
|
vswap();
|
||||||
r2=fpr(gv(RC_FLOAT));
|
r2=fpr(gv(RC_FLOAT));
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
||||||
vswap();
|
vswap();
|
||||||
r=fpr(gv(RC_FLOAT));
|
r=fpr(gv(RC_FLOAT));
|
||||||
vswap();
|
vswap();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -2093,11 +2113,13 @@ void gen_opf(int op)
|
||||||
r2=c2&0xf;
|
r2=c2&0xf;
|
||||||
} else {
|
} else {
|
||||||
r2=fpr(gv(RC_FLOAT));
|
r2=fpr(gv(RC_FLOAT));
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
|
||||||
vswap();
|
vswap();
|
||||||
r=fpr(gv(RC_FLOAT));
|
r=fpr(gv(RC_FLOAT));
|
||||||
vswap();
|
vswap();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
--vtop;
|
--vtop;
|
||||||
vset_VT_CMP(op);
|
vset_VT_CMP(op);
|
||||||
|
|
53
configure
vendored
Executable file → Normal file
53
configure
vendored
Executable file → Normal file
|
@ -29,7 +29,6 @@ sysroot=""
|
||||||
cross_prefix=""
|
cross_prefix=""
|
||||||
cc="gcc"
|
cc="gcc"
|
||||||
ar="ar"
|
ar="ar"
|
||||||
strip="strip"
|
|
||||||
bigendian="no"
|
bigendian="no"
|
||||||
mingw32="no"
|
mingw32="no"
|
||||||
LIBSUF=".a"
|
LIBSUF=".a"
|
||||||
|
@ -44,13 +43,14 @@ triplet=
|
||||||
tcc_lddir=
|
tcc_lddir=
|
||||||
confvars=
|
confvars=
|
||||||
suggest="yes"
|
suggest="yes"
|
||||||
cpu=
|
|
||||||
cpuver=
|
|
||||||
gcc_major=0
|
gcc_major=0
|
||||||
gcc_minor=0
|
gcc_minor=0
|
||||||
cc_name="gcc"
|
cc_name="gcc"
|
||||||
ar_set=
|
ar_set=
|
||||||
|
|
||||||
|
cpu=`uname -m`
|
||||||
|
cpuver=
|
||||||
|
|
||||||
# OS specific
|
# OS specific
|
||||||
targetos=`uname`
|
targetos=`uname`
|
||||||
case $targetos in
|
case $targetos in
|
||||||
|
@ -140,9 +140,7 @@ for opt do
|
||||||
;;
|
;;
|
||||||
--disable-rpath) confvars="$confvars rpath=no"
|
--disable-rpath) confvars="$confvars rpath=no"
|
||||||
;;
|
;;
|
||||||
--strip-binaries) echo deprecate, use 'make install-strip' to strip binaries
|
--debug) confvars="$confvars debug"
|
||||||
;;
|
|
||||||
--debug) confvars="$confvars strip=no"
|
|
||||||
;;
|
;;
|
||||||
--with-libgcc) confvars="$confvars libgcc"
|
--with-libgcc) confvars="$confvars libgcc"
|
||||||
;;
|
;;
|
||||||
|
@ -161,15 +159,6 @@ done
|
||||||
|
|
||||||
cc="${cross_prefix}${cc}"
|
cc="${cross_prefix}${cc}"
|
||||||
ar="${cross_prefix}${ar}"
|
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
|
case "$cpu" in
|
||||||
x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386)
|
x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386)
|
||||||
|
@ -181,7 +170,7 @@ case "$cpu" in
|
||||||
evbarm)
|
evbarm)
|
||||||
case "`uname -p`" in
|
case "`uname -p`" in
|
||||||
aarch64|arm64)
|
aarch64|arm64)
|
||||||
cpu="aarch64"
|
cpu="arm64"
|
||||||
;;
|
;;
|
||||||
earmv*)
|
earmv*)
|
||||||
cpu="arm"
|
cpu="arm"
|
||||||
|
@ -189,7 +178,7 @@ case "$cpu" in
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
aarch64|arm64|evbarm)
|
aarch64|arm64|evbarm)
|
||||||
cpu="aarch64"
|
cpu="arm64"
|
||||||
;;
|
;;
|
||||||
arm*)
|
arm*)
|
||||||
case "$cpu" in
|
case "$cpu" in
|
||||||
|
@ -302,30 +291,33 @@ Standard options:
|
||||||
Advanced options (experts only):
|
Advanced options (experts only):
|
||||||
--source-path=PATH path of source code [$source_path]
|
--source-path=PATH path of source code [$source_path]
|
||||||
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
|
--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]
|
--cc=CC use C compiler CC [$cc]
|
||||||
--ar=AR create archives using AR [$ar]
|
--ar=AR create archives using AR [$ar]
|
||||||
--extra-cflags= specify compiler flags [$CFLAGS]
|
--extra-cflags= specify compiler flags [$CFLAGS]
|
||||||
--extra-ldflags= specify linker options []
|
--extra-ldflags= specify linker options [$LDFLAGS]
|
||||||
--cpu=CPU CPU [$cpu]
|
--cpu=CPU CPU [$cpu]
|
||||||
--strip-binaries strip symbol tables from resulting binaries
|
|
||||||
--debug include debug info with resulting binaries
|
--debug include debug info with resulting binaries
|
||||||
--disable-static make libtcc.so instead of libtcc.a
|
--disable-static make libtcc.so instead of libtcc.a
|
||||||
--enable-static make libtcc.a instead of libtcc.dll (win32)
|
--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
|
--with-libgcc use libgcc_s.so.1 instead of libtcc1.a
|
||||||
--enable-cross build cross compilers
|
--with-selinux use mmap for executable memory (tcc -run)
|
||||||
--with-selinux use mmap for executable memory (with tcc -run)
|
--enable-cross build cross compilers (see also 'make help')
|
||||||
|
|
||||||
--sysincludepaths=... specify system include paths, colon separated
|
--sysincludepaths=... specify system include paths, colon separated
|
||||||
--libpaths=... specify system library paths, colon separated
|
--libpaths=... specify system library paths, colon separated
|
||||||
--crtprefix=... specify locations of crt?.o, colon separated
|
--crtprefix=... specify locations of crt?.o, colon separated
|
||||||
--elfinterp=... specify elf interpreter
|
--elfinterp=... specify elf interpreter
|
||||||
--triplet=... specify system library/include directory triplet
|
--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
|
--config-predefs=no do not compile tccdefs.h, instead just include
|
||||||
EOF
|
EOF
|
||||||
#echo "NOTE: The object files are build at the place where configure is launched"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -349,7 +341,7 @@ if test -z "$cross_prefix" ; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test -z "$triplet"; then
|
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
|
if test -f "/usr/lib64/crti.o" ; then
|
||||||
tcc_lddir="lib64"
|
tcc_lddir="lib64"
|
||||||
fi
|
fi
|
||||||
|
@ -453,7 +445,6 @@ CC_NAME=$cc_name
|
||||||
GCC_MAJOR=$gcc_major
|
GCC_MAJOR=$gcc_major
|
||||||
GCC_MINOR=$gcc_minor
|
GCC_MINOR=$gcc_minor
|
||||||
AR=$ar
|
AR=$ar
|
||||||
STRIP=$strip -s -R .comment -R .note
|
|
||||||
CFLAGS=$CFLAGS
|
CFLAGS=$CFLAGS
|
||||||
LDFLAGS=$LDFLAGS
|
LDFLAGS=$LDFLAGS
|
||||||
LIBSUF=$LIBSUF
|
LIBSUF=$LIBSUF
|
||||||
|
@ -492,11 +483,7 @@ print_mak CONFIG_LDDIR "$tcc_lddir"
|
||||||
print_mak CONFIG_TRIPLET "$triplet"
|
print_mak CONFIG_TRIPLET "$triplet"
|
||||||
print_mak TCC_CPU_VERSION "$cpuver" num
|
print_mak TCC_CPU_VERSION "$cpuver" num
|
||||||
|
|
||||||
if test "$cpu" = "aarch64" ; then
|
echo "ARCH=$cpu" >> config.mak
|
||||||
echo "ARCH=arm64" >> config.mak
|
|
||||||
else
|
|
||||||
echo "ARCH=$cpu" >> config.mak
|
|
||||||
fi
|
|
||||||
echo "TARGETOS=$targetos" >> config.mak
|
echo "TARGETOS=$targetos" >> config.mak
|
||||||
|
|
||||||
predefs="1"
|
predefs="1"
|
||||||
|
|
|
@ -12,15 +12,17 @@ int (*__rt_error)(void*, void*, const char *, va_list);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__declspec(dllexport)
|
__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)) int main();
|
||||||
__attribute__((weak)) void __bound_init(void*, int);
|
__attribute__((weak)) void __bound_init(void*, int);
|
||||||
struct rt_context *rc = &g_rtctxt;
|
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 */
|
/* call __bound_init here due to redirection of sigaction */
|
||||||
if (__bound_init && p->bounds_start)
|
if (__bound_init && p->bounds_start)
|
||||||
__bound_init(p->bounds_start, mode);
|
__bound_init(p->bounds_start, 0);
|
||||||
|
#endif
|
||||||
if (num_callers) {
|
if (num_callers) {
|
||||||
memcpy(rc, p, offsetof(rt_context, next));
|
memcpy(rc, p, offsetof(rt_context, next));
|
||||||
rc->num_callers = num_callers - 1;
|
rc->num_callers = num_callers - 1;
|
||||||
|
|
156
libtcc.c
156
libtcc.c
|
@ -273,20 +273,12 @@ PUB_FUNC char *tcc_strdup(const char *str)
|
||||||
#define MEM_DEBUG_MAGIC2 0xFEEDDEB2
|
#define MEM_DEBUG_MAGIC2 0xFEEDDEB2
|
||||||
#define MEM_DEBUG_MAGIC3 0xFEEDDEB3
|
#define MEM_DEBUG_MAGIC3 0xFEEDDEB3
|
||||||
#define MEM_DEBUG_FILE_LEN 40
|
#define MEM_DEBUG_FILE_LEN 40
|
||||||
#define MEM_DEBUG_OFF3 offsetof(mem_debug_header_t, magic3)
|
|
||||||
#define MEM_DEBUG_CHECK3(header) \
|
#define MEM_DEBUG_CHECK3(header) \
|
||||||
({unsigned magic3; \
|
((mem_debug_header_t*)((char*)header + header->size))->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));}
|
|
||||||
#define MEM_USER_PTR(header) \
|
#define MEM_USER_PTR(header) \
|
||||||
((char *)header + MEM_DEBUG_OFF3)
|
((char *)header + offsetof(mem_debug_header_t, magic3))
|
||||||
#define MEM_HEADER_PTR(ptr) \
|
#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 {
|
struct mem_debug_header {
|
||||||
unsigned magic1;
|
unsigned magic1;
|
||||||
|
@ -296,7 +288,7 @@ struct mem_debug_header {
|
||||||
int line_num;
|
int line_num;
|
||||||
char file_name[MEM_DEBUG_FILE_LEN + 1];
|
char file_name[MEM_DEBUG_FILE_LEN + 1];
|
||||||
unsigned magic2;
|
unsigned magic2;
|
||||||
ALIGNED(16) unsigned magic3;
|
ALIGNED(16) unsigned char magic3[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct mem_debug_header mem_debug_header_t;
|
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);
|
mem_debug_header_t * header = MEM_HEADER_PTR(ptr);
|
||||||
if (header->magic1 != MEM_DEBUG_MAGIC1 ||
|
if (header->magic1 != MEM_DEBUG_MAGIC1 ||
|
||||||
header->magic2 != MEM_DEBUG_MAGIC2 ||
|
header->magic2 != MEM_DEBUG_MAGIC2 ||
|
||||||
MEM_DEBUG_CHECK3(header) != MEM_DEBUG_MAGIC3 ||
|
read32le(MEM_DEBUG_CHECK3(header)) != MEM_DEBUG_MAGIC3 ||
|
||||||
header->size == (unsigned)-1) {
|
header->size == (unsigned)-1) {
|
||||||
fprintf(stderr, "%s check failed\n", msg);
|
fprintf(stderr, "%s check failed\n", msg);
|
||||||
if (header->magic1 == MEM_DEBUG_MAGIC1)
|
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->magic1 = MEM_DEBUG_MAGIC1;
|
||||||
header->magic2 = MEM_DEBUG_MAGIC2;
|
header->magic2 = MEM_DEBUG_MAGIC2;
|
||||||
header->size = size;
|
header->size = size;
|
||||||
MEM_DEBUG_SET3(header);
|
write32le(MEM_DEBUG_CHECK3(header), MEM_DEBUG_MAGIC3);
|
||||||
header->line_num = line;
|
header->line_num = line;
|
||||||
ofs = strlen(file) - MEM_DEBUG_FILE_LEN;
|
ofs = strlen(file) - MEM_DEBUG_FILE_LEN;
|
||||||
strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), 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)
|
if (!header)
|
||||||
_tcc_error("memory full (realloc)");
|
_tcc_error("memory full (realloc)");
|
||||||
header->size = size;
|
header->size = size;
|
||||||
MEM_DEBUG_SET3(header);
|
write32le(MEM_DEBUG_CHECK3(header), MEM_DEBUG_MAGIC3);
|
||||||
if (header->next)
|
if (header->next)
|
||||||
header->next->prev = header;
|
header->next->prev = header;
|
||||||
if (header->prev)
|
if (header->prev)
|
||||||
|
@ -901,7 +893,6 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
||||||
/* add libc crt1/crti objects */
|
/* add libc crt1/crti objects */
|
||||||
if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
|
if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
|
||||||
!s->nostdlib) {
|
!s->nostdlib) {
|
||||||
#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD
|
|
||||||
#if TARGETOS_OpenBSD
|
#if TARGETOS_OpenBSD
|
||||||
if (output_type != TCC_OUTPUT_DLL)
|
if (output_type != TCC_OUTPUT_DLL)
|
||||||
tcc_add_crt(s, "crt0.o");
|
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");
|
tcc_add_crt(s, "crtbeginS.o");
|
||||||
else
|
else
|
||||||
tcc_add_crt(s, "crtbegin.o");
|
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. */
|
/* Mach-O with LC_MAIN doesn't need any crt startup code. */
|
||||||
|
#else
|
||||||
if (output_type != TCC_OUTPUT_DLL)
|
if (output_type != TCC_OUTPUT_DLL)
|
||||||
tcc_add_crt(s, "crt1.o");
|
tcc_add_crt(s, "crt1.o");
|
||||||
tcc_add_crt(s, "crti.o");
|
tcc_add_crt(s, "crti.o");
|
||||||
|
@ -963,10 +954,41 @@ ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname)
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||||
{
|
{
|
||||||
int fd, ret = -1;
|
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 */
|
/* open the file */
|
||||||
fd = _tcc_open(s1, filename);
|
fd = _tcc_open(s1, filename);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
@ -1111,101 +1133,21 @@ ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
|
||||||
}
|
}
|
||||||
#endif
|
#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 */
|
/* the library name is the same as the argument of the '-l' option */
|
||||||
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
|
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
|
||||||
{
|
{
|
||||||
#if defined TCC_TARGET_PE
|
#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 };
|
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 **pp = s->static_link ? libs + 4 : libs;
|
const char * const *pp = s->static_link ? libs + 4 : libs;
|
||||||
#elif defined TCC_TARGET_MACHO
|
#elif defined TCC_TARGET_MACHO
|
||||||
const char *libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL };
|
static const char * const libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL };
|
||||||
const char **pp = s->static_link ? libs + 1 : libs;
|
const char * const *pp = s->static_link ? libs + 1 : libs;
|
||||||
#elif defined TARGETOS_OpenBSD && !defined _WIN32
|
#elif defined TARGETOS_OpenBSD
|
||||||
const char *libs[] = { s->static_link
|
static const char * const libs[] = { "%s/lib%s.so.*", "%s/lib%s.a", NULL };
|
||||||
? NULL
|
const char * const *pp = s->static_link ? libs + 1 : libs;
|
||||||
/* 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;
|
|
||||||
#else
|
#else
|
||||||
const char *libs[] = { "%s/lib%s.so", "%s/lib%s.a", NULL };
|
static const char * const libs[] = { "%s/lib%s.so", "%s/lib%s.a", NULL };
|
||||||
const char **pp = s->static_link ? libs + 1 : libs;
|
const char * const *pp = s->static_link ? libs + 1 : libs;
|
||||||
#endif
|
#endif
|
||||||
int flags = s->filetype & AFF_WHOLE_ARCHIVE;
|
int flags = s->filetype & AFF_WHOLE_ARCHIVE;
|
||||||
while (*pp) {
|
while (*pp) {
|
||||||
|
|
|
@ -166,10 +166,10 @@ ST_FUNC void gsym_addr(int t_, int a_)
|
||||||
|
|
||||||
static int load_symofs(int r, SValue *sv, int forstore)
|
static int load_symofs(int r, SValue *sv, int forstore)
|
||||||
{
|
{
|
||||||
static Sym label;
|
|
||||||
int rr, doload = 0;
|
int rr, doload = 0;
|
||||||
int fc = sv->c.i, v = sv->r & VT_VALMASK;
|
int fc = sv->c.i, v = sv->r & VT_VALMASK;
|
||||||
if (sv->r & VT_SYM) {
|
if (sv->r & VT_SYM) {
|
||||||
|
Sym label = {0};
|
||||||
assert(v == VT_CONST);
|
assert(v == VT_CONST);
|
||||||
if (sv->sym->type.t & VT_STATIC) { // XXX do this per linker relax
|
if (sv->sym->type.t & VT_STATIC) { // XXX do this per linker relax
|
||||||
greloca(cur_text_section, sv->sym, ind,
|
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);
|
R_RISCV_GOT_HI20, 0);
|
||||||
doload = 1;
|
doload = 1;
|
||||||
}
|
}
|
||||||
if (!label.v) {
|
label.type.t = VT_VOID | VT_STATIC;
|
||||||
label.v = tok_alloc(".L0 ", 4)->tok;
|
|
||||||
label.type.t = VT_VOID | VT_STATIC;
|
|
||||||
}
|
|
||||||
label.c = 0; /* force new local ELF symbol */
|
|
||||||
put_extern_sym(&label, cur_text_section, ind, 0);
|
put_extern_sym(&label, cur_text_section, ind, 0);
|
||||||
rr = is_ireg(r) ? ireg(r) : 5;
|
rr = is_ireg(r) ? ireg(r) : 5;
|
||||||
o(0x17 | (rr << 7)); // auipc RR, 0 %pcrel_hi(sym)+addend
|
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 void gen_bounds_epilog(void)
|
||||||
{
|
{
|
||||||
static Sym label;
|
|
||||||
addr_t saved_ind;
|
addr_t saved_ind;
|
||||||
addr_t *bounds_ptr;
|
addr_t *bounds_ptr;
|
||||||
Sym *sym_data;
|
Sym *sym_data;
|
||||||
|
Sym label = {0};
|
||||||
|
|
||||||
int offset_modified = func_bound_offset != lbounds_section->data_offset;
|
int offset_modified = func_bound_offset != lbounds_section->data_offset;
|
||||||
|
|
||||||
if (!offset_modified && !func_bound_add_epilog)
|
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,
|
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
||||||
func_bound_offset, lbounds_section->data_offset);
|
func_bound_offset, lbounds_section->data_offset);
|
||||||
|
|
||||||
if (!label.v) {
|
label.type.t = VT_VOID | VT_STATIC;
|
||||||
label.v = tok_alloc(".LB0 ", 5)->tok;
|
|
||||||
label.type.t = VT_VOID | VT_STATIC;
|
|
||||||
}
|
|
||||||
/* generate bound local allocation */
|
/* generate bound local allocation */
|
||||||
if (offset_modified) {
|
if (offset_modified) {
|
||||||
saved_ind = ind;
|
saved_ind = ind;
|
||||||
ind = func_bound_ind;
|
ind = func_bound_ind;
|
||||||
label.c = 0; /* force new local ELF symbol */
|
|
||||||
put_extern_sym(&label, cur_text_section, ind, 0);
|
put_extern_sym(&label, cur_text_section, ind, 0);
|
||||||
greloca(cur_text_section, sym_data, ind, R_RISCV_GOT_HI20, 0);
|
greloca(cur_text_section, sym_data, ind, R_RISCV_GOT_HI20, 0);
|
||||||
o(0x17 | (10 << 7)); // auipc a0, 0 %pcrel_hi(sym)+addend
|
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)
|
EI(0x03, 3, 10, 10, 0); // ld a0, 0(a0)
|
||||||
gen_bounds_call(TOK___bound_local_new);
|
gen_bounds_call(TOK___bound_local_new);
|
||||||
ind = saved_ind;
|
ind = saved_ind;
|
||||||
|
label.c = 0; /* force new local ELF symbol */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate bound check local freeing */
|
/* generate bound check local freeing */
|
||||||
o(0xe02a1101); /* addi sp,sp,-32 sd a0,0(sp) */
|
o(0xe02a1101); /* addi sp,sp,-32 sd a0,0(sp) */
|
||||||
o(0xa82ae42e); /* sd a1,8(sp) fsd fa0,16(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);
|
put_extern_sym(&label, cur_text_section, ind, 0);
|
||||||
greloca(cur_text_section, sym_data, ind, R_RISCV_GOT_HI20, 0);
|
greloca(cur_text_section, sym_data, ind, R_RISCV_GOT_HI20, 0);
|
||||||
o(0x17 | (10 << 7)); // auipc a0, 0 %pcrel_hi(sym)+addend
|
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)
|
ST_FUNC void gen_increment_tcov (SValue *sv)
|
||||||
{
|
{
|
||||||
int r1, r2;
|
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);
|
vpushv(sv);
|
||||||
vtop->r = r1 = get_reg(RC_INT);
|
vtop->r = r1 = get_reg(RC_INT);
|
||||||
r2 = get_reg(RC_INT);
|
r2 = get_reg(RC_INT);
|
||||||
r1 = ireg(r1);
|
r1 = ireg(r1);
|
||||||
r2 = ireg(r2);
|
r2 = ireg(r2);
|
||||||
greloca(cur_text_section, sv->sym, ind, R_RISCV_PCREL_HI20, 0);
|
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);
|
put_extern_sym(&label, cur_text_section, ind, 0);
|
||||||
o(0x17 | (r1 << 7)); // auipc RR, 0 %pcrel_hi(sym)
|
o(0x17 | (r1 << 7)); // auipc RR, 0 %pcrel_hi(sym)
|
||||||
greloca(cur_text_section, &label, ind, R_RISCV_PCREL_LO12_I, 0);
|
greloca(cur_text_section, &label, ind, R_RISCV_PCREL_LO12_I, 0);
|
||||||
|
|
8
tcc.h
8
tcc.h
|
@ -764,7 +764,6 @@ struct TCCState {
|
||||||
unsigned char leading_underscore;
|
unsigned char leading_underscore;
|
||||||
unsigned char ms_extensions; /* allow nested named struct w/o identifier behave like unnamed */
|
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 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 */
|
unsigned char ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */
|
||||||
|
|
||||||
/* warning switches */
|
/* warning switches */
|
||||||
|
@ -782,6 +781,8 @@ struct TCCState {
|
||||||
/* compile with built-in memory and bounds checker */
|
/* compile with built-in memory and bounds checker */
|
||||||
unsigned char do_bounds_check;
|
unsigned char do_bounds_check;
|
||||||
#endif
|
#endif
|
||||||
|
unsigned char test_coverage; /* generate test coverage code */
|
||||||
|
|
||||||
#ifdef TCC_TARGET_ARM
|
#ifdef TCC_TARGET_ARM
|
||||||
enum float_abi float_abi; /* float ABI of the generated code*/
|
enum float_abi float_abi; /* float ABI of the generated code*/
|
||||||
#endif
|
#endif
|
||||||
|
@ -1447,6 +1448,7 @@ ST_DATA Sym *define_stack;
|
||||||
ST_DATA CType int_type, func_old_type, char_pointer_type;
|
ST_DATA CType int_type, func_old_type, char_pointer_type;
|
||||||
ST_DATA SValue *vtop;
|
ST_DATA SValue *vtop;
|
||||||
ST_DATA int rsym, anon_sym, ind, loc;
|
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 const_wanted; /* true if constant wanted */
|
||||||
ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */
|
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_bincl(TCCState *s1);
|
||||||
ST_FUNC void tcc_debug_eincl(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_putfile(TCCState *s1, const char *filename);
|
||||||
ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym);
|
ST_FUNC void tcc_add_tcov(TCCState *s1);
|
||||||
ST_FUNC void tcc_debug_funcend(TCCState *s1, int size);
|
|
||||||
ST_FUNC void tcc_debug_line(TCCState *s1);
|
|
||||||
|
|
||||||
ST_FUNC void tccgen_init(TCCState *s1);
|
ST_FUNC void tccgen_init(TCCState *s1);
|
||||||
ST_FUNC int tccgen_compile(TCCState *s1);
|
ST_FUNC int tccgen_compile(TCCState *s1);
|
||||||
|
|
4
tccelf.c
4
tccelf.c
|
@ -1419,7 +1419,7 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
|
||||||
cstr_printf(&cstr, "__bt_init_dll(0);");
|
cstr_printf(&cstr, "__bt_init_dll(0);");
|
||||||
#endif
|
#endif
|
||||||
#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);
|
s1->output_type == TCC_OUTPUT_DLL ? 0 : s1->rt_num_callers + 1);
|
||||||
tcc_compile_string(s1, cstr.data);
|
tcc_compile_string(s1, cstr.data);
|
||||||
cstr_free(&cstr);
|
cstr_free(&cstr);
|
||||||
|
@ -1450,7 +1450,7 @@ static void tcc_tcov_add_file(TCCState *s1, const char *filename)
|
||||||
cstr_free (&cstr);
|
cstr_free (&cstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcc_add_tcov(TCCState *s1)
|
ST_FUNC void tcc_add_tcov(TCCState *s1)
|
||||||
{
|
{
|
||||||
CString cstr;
|
CString cstr;
|
||||||
|
|
||||||
|
|
433
tccgen.c
433
tccgen.c
|
@ -46,15 +46,12 @@ static int local_scope;
|
||||||
static int in_sizeof;
|
static int in_sizeof;
|
||||||
static int in_generic;
|
static int in_generic;
|
||||||
static int section_sym;
|
static int section_sym;
|
||||||
|
ST_DATA char debug_modes;
|
||||||
|
|
||||||
ST_DATA SValue *vtop;
|
ST_DATA SValue *vtop;
|
||||||
static SValue _vstack[1 + VSTACK_SIZE];
|
static SValue _vstack[1 + VSTACK_SIZE];
|
||||||
#define vstack (_vstack + 1)
|
#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 const_wanted; /* true if constant wanted */
|
||||||
ST_DATA int nocode_wanted; /* no code generation wanted */
|
ST_DATA int nocode_wanted; /* no code generation wanted */
|
||||||
#define unevalmask 0xffff /* unevaluated subexpression */
|
#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_OFF() (nocode_wanted |= 0x20000000)
|
||||||
#define CODE_ON() (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 */
|
/* Clear 'nocode_wanted' at label if it was used */
|
||||||
ST_FUNC void gsym(int t) { if (t) { gsym_addr(t, ind); CODE_ON(); }}
|
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 */
|
/* Set 'nocode_wanted' after unconditional jumps */
|
||||||
static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); }
|
static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); }
|
||||||
|
@ -214,7 +213,6 @@ static struct {
|
||||||
unsigned long last_func_name;
|
unsigned long last_func_name;
|
||||||
int ind;
|
int ind;
|
||||||
int line;
|
int line;
|
||||||
Sym label;
|
|
||||||
} tcov_data;
|
} tcov_data;
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
|
@ -460,6 +458,74 @@ ST_FUNC void tcc_debug_start(TCCState *s1)
|
||||||
SHN_ABS, file->filename);
|
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,
|
static void tcc_debug_stabs (TCCState *s1, const char *str, int type, unsigned long value,
|
||||||
Section *sec, int sym_index)
|
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);
|
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) {
|
if (type == N_LBRAC) {
|
||||||
struct debug_info *info =
|
struct debug_info *info =
|
||||||
(struct debug_info *) tcc_mallocz(sizeof (*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)
|
static void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e)
|
||||||
{
|
{
|
||||||
CString debug_str;
|
CString debug_str;
|
||||||
|
if (!s1->do_debug)
|
||||||
|
return;
|
||||||
cstr_new (&debug_str);
|
cstr_new (&debug_str);
|
||||||
for (; s != e; s = s->prev) {
|
for (; s != e; s = s->prev) {
|
||||||
if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL)
|
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);
|
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;
|
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_new (&str);
|
||||||
cstr_printf (&str, "%s:%c",
|
cstr_printf (&str, "%s:%c",
|
||||||
get_tok_str(sym->v, NULL),
|
get_tok_str(sym->v, NULL),
|
||||||
|
@ -695,6 +802,8 @@ static void tcc_debug_typedef(TCCState *s1, Sym *sym)
|
||||||
{
|
{
|
||||||
CString str;
|
CString str;
|
||||||
|
|
||||||
|
if (!s1->do_debug)
|
||||||
|
return;
|
||||||
cstr_new (&str);
|
cstr_new (&str);
|
||||||
cstr_printf (&str, "%s:t",
|
cstr_printf (&str, "%s:t",
|
||||||
(sym->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
|
(sym->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
|
||||||
|
@ -704,17 +813,11 @@ static void tcc_debug_typedef(TCCState *s1, Sym *sym)
|
||||||
cstr_free (&str);
|
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 */
|
/* for section layout see lib/tcov.c */
|
||||||
|
|
||||||
|
static void tcc_tcov_block_end(int line);
|
||||||
|
|
||||||
static void tcc_tcov_block_begin(void)
|
static void tcc_tcov_block_begin(void)
|
||||||
{
|
{
|
||||||
SValue sv;
|
SValue sv;
|
||||||
|
@ -764,21 +867,19 @@ static void tcc_tcov_block_begin(void)
|
||||||
if (ind == tcov_data.ind && tcov_data.line == file->line_num)
|
if (ind == tcov_data.ind && tcov_data.line == file->line_num)
|
||||||
tcov_data.offset = tcov_data.last_offset;
|
tcov_data.offset = tcov_data.last_offset;
|
||||||
else {
|
else {
|
||||||
if (!tcov_data.label.v) {
|
Sym label = {0};
|
||||||
tcov_data.label.v = tok_alloc(".TCOV ", 6)->tok;
|
label.type.t = VT_LLONG | VT_STATIC;
|
||||||
tcov_data.label.type.t = VT_LLONG | VT_STATIC;
|
|
||||||
}
|
|
||||||
tcov_data.label.c = 0; /* force new local ELF symbol */
|
|
||||||
ptr = section_ptr_add(tcov_section, 16);
|
ptr = section_ptr_add(tcov_section, 16);
|
||||||
tcov_data.line = file->line_num;
|
tcov_data.line = file->line_num;
|
||||||
write64le (ptr, (tcov_data.line << 8) | 0xff);
|
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);
|
((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.r = VT_SYM | VT_LVAL | VT_CONST;
|
||||||
sv.r2 = VT_CONST;
|
sv.r2 = VT_CONST;
|
||||||
sv.c.i = 0;
|
sv.c.i = 0;
|
||||||
sv.sym = &tcov_data.label;
|
sv.sym = &label;
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || \
|
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || \
|
||||||
defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 || \
|
defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 || \
|
||||||
defined TCC_TARGET_RISCV64
|
defined TCC_TARGET_RISCV64
|
||||||
|
@ -844,94 +945,6 @@ static void tcc_tcov_end(void)
|
||||||
section_ptr_add(tcov_section, 1);
|
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 */
|
/* initialize vstack and types. This must be done also for tcc -E */
|
||||||
ST_FUNC void tccgen_init(TCCState *s1)
|
ST_FUNC void tccgen_init(TCCState *s1)
|
||||||
|
@ -967,6 +980,7 @@ ST_FUNC int tccgen_compile(TCCState *s1)
|
||||||
const_wanted = 0;
|
const_wanted = 0;
|
||||||
nocode_wanted = 0x80000000;
|
nocode_wanted = 0x80000000;
|
||||||
local_scope = 0;
|
local_scope = 0;
|
||||||
|
debug_modes = s1->do_debug | s1->test_coverage << 1;
|
||||||
|
|
||||||
tcc_debug_start(s1);
|
tcc_debug_start(s1);
|
||||||
tcc_tcov_start ();
|
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);
|
info = ELFW(ST_INFO)(sym_bind, sym_type);
|
||||||
sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name);
|
sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name);
|
||||||
|
|
||||||
if (tcc_state->do_debug
|
if (debug_modes)
|
||||||
&& sym_type != STT_FUNC
|
tcc_debug_extern_sym(tcc_state, sym, sh_num, sym_bind, sym_type);
|
||||||
&& sym->v < SYM_FIRST_ANOM)
|
|
||||||
tcc_debug_extern_sym(tcc_state, sym, sh_num, sym_bind);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
esym = elfsym(sym);
|
esym = elfsym(sym);
|
||||||
|
@ -2188,15 +2200,15 @@ static void add_local_bounds(Sym *s, Sym *e)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Wrapper around sym_pop, that potentially also registers local bounds. */
|
/* 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
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (tcc_state->do_bounds_check && !ellipsis && !keep)
|
if (tcc_state->do_bounds_check && !keep && (local_scope || !func_var))
|
||||||
add_local_bounds(*ptop, b);
|
add_local_bounds(local_stack, b);
|
||||||
#endif
|
#endif
|
||||||
if (tcc_state->do_debug)
|
if (debug_modes)
|
||||||
tcc_add_debug_info (tcc_state, !local_scope, *ptop, b);
|
tcc_add_debug_info (tcc_state, !local_scope, local_stack, b);
|
||||||
sym_pop(ptop, b, keep);
|
sym_pop(&local_stack, b, keep);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void incr_bf_adr(int o)
|
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)
|
static void store_packed_bf(int bit_pos, int bit_size)
|
||||||
{
|
{
|
||||||
int bits, n, o, m, c;
|
int bits, n, o, m, c;
|
||||||
|
|
||||||
c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
|
c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
|
||||||
vswap(); // X B
|
vswap(); // X B
|
||||||
save_reg_upstack(vtop->r, 1);
|
save_reg_upstack(vtop->r, 1);
|
||||||
|
@ -4727,10 +4738,12 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
||||||
continue;
|
continue;
|
||||||
bit_pos = BIT_POS(f->type.t);
|
bit_pos = BIT_POS(f->type.t);
|
||||||
size = type_size(&f->type, &align);
|
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
|
||||||
if (bit_pos + bit_size <= size * 8 && f->c + size <= c &&
|
#ifdef TCC_TARGET_ARM
|
||||||
(f->c & (align - 1)) == 0)
|
&& !(f->c & (align - 1))
|
||||||
|
#endif
|
||||||
|
)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* try to access the field using a different type */
|
/* try to access the field using a different type */
|
||||||
|
@ -4756,7 +4769,11 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
||||||
c0 = cx;
|
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 */
|
/* update offset and bit position */
|
||||||
f->c = cx;
|
f->c = cx;
|
||||||
bit_pos = px;
|
bit_pos = px;
|
||||||
|
@ -4771,7 +4788,6 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
||||||
cx, s, align, px, bit_size);
|
cx, s, align, px, bit_size);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
single_byte:
|
|
||||||
/* fall back to load/store single-byte wise */
|
/* fall back to load/store single-byte wise */
|
||||||
f->auxtype = VT_STRUCT;
|
f->auxtype = VT_STRUCT;
|
||||||
#ifdef BF_DEBUG
|
#ifdef BF_DEBUG
|
||||||
|
@ -5696,9 +5712,8 @@ ST_FUNC void unary(void)
|
||||||
AttributeDef ad;
|
AttributeDef ad;
|
||||||
|
|
||||||
/* generate line number info */
|
/* generate line number info */
|
||||||
if (tcc_state->do_debug)
|
if (debug_modes)
|
||||||
tcc_debug_line(tcc_state);
|
tcc_debug_line(tcc_state), tcc_tcov_check_line (1);
|
||||||
tcc_tcov_check_line (1);
|
|
||||||
|
|
||||||
sizeof_caller = in_sizeof;
|
sizeof_caller = in_sizeof;
|
||||||
in_sizeof = 0;
|
in_sizeof = 0;
|
||||||
|
@ -6419,7 +6434,8 @@ special_math_val:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s->f.func_noreturn) {
|
if (s->f.func_noreturn) {
|
||||||
tcc_tcov_block_end (tcov_data.line);
|
if (debug_modes)
|
||||||
|
tcc_tcov_block_end (tcov_data.line);
|
||||||
CODE_OFF();
|
CODE_OFF();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -6678,13 +6694,6 @@ static void expr_cond(void)
|
||||||
if (!g)
|
if (!g)
|
||||||
gexpr();
|
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)
|
if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
|
||||||
mk_pointer(&vtop->type);
|
mk_pointer(&vtop->type);
|
||||||
sv = *vtop; /* save value to handle it later */
|
sv = *vtop; /* save value to handle it later */
|
||||||
|
@ -6705,15 +6714,14 @@ static void expr_cond(void)
|
||||||
expr_cond();
|
expr_cond();
|
||||||
|
|
||||||
if (c < 0 && is_cond_bool(vtop) && is_cond_bool(&sv)) {
|
if (c < 0 && is_cond_bool(vtop) && is_cond_bool(&sv)) {
|
||||||
if (sv.r == VT_CMP) {
|
/* optimize "if (f ? a > b : c || d) ..." for example, where normally
|
||||||
t1 = sv.jtrue;
|
"a < b" and "c || d" would be forced to "(int)0/1" first, whereas
|
||||||
t2 = u;
|
this code jumps directly to the if's then/else branches. */
|
||||||
} else {
|
t1 = gvtst(0, 0);
|
||||||
t1 = gvtst(0, 0);
|
t2 = gjmp(0);
|
||||||
t2 = gjmp(0);
|
gsym(u);
|
||||||
gsym(u);
|
vpushv(&sv);
|
||||||
vpushv(&sv);
|
/* combine jump targets of 2nd op with VT_CMP of 1st op */
|
||||||
}
|
|
||||||
gvtst_set(0, t1);
|
gvtst_set(0, t1);
|
||||||
gvtst_set(1, t2);
|
gvtst_set(1, t2);
|
||||||
nocode_wanted = ncw_prev;
|
nocode_wanted = ncw_prev;
|
||||||
|
@ -7099,11 +7107,10 @@ void new_scope(struct scope *o)
|
||||||
/* record local declaration stack position */
|
/* record local declaration stack position */
|
||||||
o->lstk = local_stack;
|
o->lstk = local_stack;
|
||||||
o->llstk = local_label_stack;
|
o->llstk = local_label_stack;
|
||||||
|
|
||||||
++local_scope;
|
++local_scope;
|
||||||
|
|
||||||
if (tcc_state->do_debug)
|
if (debug_modes)
|
||||||
tcc_debug_stabn(N_LBRAC, ind - func_ind);
|
tcc_debug_stabn(tcc_state, N_LBRAC, ind - func_ind);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prev_scope(struct scope *o, int is_expr)
|
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. */
|
tables, though. sym_pop will do that. */
|
||||||
|
|
||||||
/* pop locally defined symbols */
|
/* 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;
|
cur_scope = o->prev;
|
||||||
--local_scope;
|
--local_scope;
|
||||||
|
|
||||||
if (tcc_state->do_debug)
|
if (debug_modes)
|
||||||
tcc_debug_stabn(N_RBRAC, ind - func_ind);
|
tcc_debug_stabn(tcc_state, N_RBRAC, ind - func_ind);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* leave a scope via break/continue(/goto) */
|
/* leave a scope via break/continue(/goto) */
|
||||||
|
@ -7182,8 +7189,9 @@ again:
|
||||||
goto expr;
|
goto expr;
|
||||||
next();
|
next();
|
||||||
|
|
||||||
tcc_tcov_check_line (0);
|
if (debug_modes)
|
||||||
tcc_tcov_block_begin ();
|
tcc_tcov_check_line (0), tcc_tcov_block_begin ();
|
||||||
|
|
||||||
if (t == TOK_IF) {
|
if (t == TOK_IF) {
|
||||||
skip('(');
|
skip('(');
|
||||||
gexpr();
|
gexpr();
|
||||||
|
@ -7264,7 +7272,8 @@ again:
|
||||||
/* jump unless last stmt in top-level block */
|
/* jump unless last stmt in top-level block */
|
||||||
if (tok != '}' || local_scope != 1)
|
if (tok != '}' || local_scope != 1)
|
||||||
rsym = gjmp(rsym);
|
rsym = gjmp(rsym);
|
||||||
tcc_tcov_block_end (tcov_data.line);
|
if (debug_modes)
|
||||||
|
tcc_tcov_block_end (tcov_data.line);
|
||||||
CODE_OFF();
|
CODE_OFF();
|
||||||
|
|
||||||
} else if (t == TOK_BREAK) {
|
} 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 ()
|
/* 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;
|
CType dtype;
|
||||||
int size, align;
|
int size, align;
|
||||||
Section *sec = p->sec;
|
Section *sec = p->sec;
|
||||||
|
uint64_t val;
|
||||||
|
|
||||||
dtype = *type;
|
dtype = *type;
|
||||||
dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
|
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)
|
if ((vtop->r & VT_SYM)
|
||||||
&& bt != VT_PTR
|
&& bt != VT_PTR
|
||||||
&& bt != VT_FUNC
|
|
||||||
&& (bt != (PTR_SIZE == 8 ? VT_LLONG : VT_INT)
|
&& (bt != (PTR_SIZE == 8 ? VT_LLONG : VT_INT)
|
||||||
|| (type->t & VT_BITFIELD))
|
|| (type->t & VT_BITFIELD))
|
||||||
&& !((vtop->r & VT_CONST) && vtop->sym->v >= SYM_FIRST_ANOM)
|
&& !((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;
|
ptr = sec->data + c;
|
||||||
|
val = vtop->c.i;
|
||||||
|
|
||||||
/* XXX: make code faster ? */
|
/* XXX: make code faster ? */
|
||||||
if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) &&
|
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;
|
n = 8 - bit_pos;
|
||||||
if (n > bit_size)
|
if (n > bit_size)
|
||||||
n = bit_size;
|
n = bit_size;
|
||||||
v = vtop->c.i >> bits << bit_pos;
|
v = val >> bits << bit_pos;
|
||||||
m = ((1 << n) - 1) << bit_pos;
|
m = ((1 << n) - 1) << bit_pos;
|
||||||
*p = (*p & ~m) | (v & m);
|
*p = (*p & ~m) | (v & m);
|
||||||
bits += n, bit_size -= n, bit_pos = 0, ++p;
|
bits += n, bit_size -= n, bit_pos = 0, ++p;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
switch(bt) {
|
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:
|
case VT_BOOL:
|
||||||
vtop->c.i = vtop->c.i != 0;
|
*(char *)ptr = val != 0;
|
||||||
|
break;
|
||||||
case VT_BYTE:
|
case VT_BYTE:
|
||||||
*(char *)ptr = vtop->c.i;
|
*(char *)ptr = val;
|
||||||
break;
|
break;
|
||||||
case VT_SHORT:
|
case VT_SHORT:
|
||||||
*(short *)ptr = vtop->c.i;
|
write16le(ptr, val);
|
||||||
break;
|
break;
|
||||||
case VT_FLOAT:
|
case VT_FLOAT:
|
||||||
*(float*)ptr = vtop->c.f;
|
write32le(ptr, val);
|
||||||
break;
|
break;
|
||||||
case VT_DOUBLE:
|
case VT_DOUBLE:
|
||||||
*(double *)ptr = vtop->c.d;
|
write64le(ptr, val);
|
||||||
break;
|
break;
|
||||||
case VT_LDOUBLE:
|
case VT_LDOUBLE:
|
||||||
#if defined TCC_IS_NATIVE_387
|
#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);
|
memcpy(ptr, &vtop->c.ld, 10);
|
||||||
#ifdef __TINYC__
|
#ifdef __TINYC__
|
||||||
else if (sizeof (long double) == sizeof (double))
|
else if (sizeof (long double) == sizeof (double))
|
||||||
|
@ -7904,52 +7920,44 @@ static void init_putv(init_params *p, CType *type, unsigned long c)
|
||||||
;
|
;
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
/* For other platforms it should work natively, but may not work
|
||||||
|
for cross compilers */
|
||||||
if (sizeof(long double) == LDOUBLE_SIZE)
|
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)
|
else if (sizeof(double) == LDOUBLE_SIZE)
|
||||||
*(double *)ptr = (double)vtop->c.ld;
|
memcpy(ptr, &vtop->c.ld, LDOUBLE_SIZE);
|
||||||
#ifndef TCC_CROSS_TEST
|
#ifndef TCC_CROSS_TEST
|
||||||
else
|
else
|
||||||
tcc_error("can't cross compile long double constants");
|
tcc_error("can't cross compile long double constants");
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
#if PTR_SIZE != 8
|
|
||||||
|
#if PTR_SIZE == 8
|
||||||
|
/* intptr_t may need a reloc too, see tcctest.c:relocation_test() */
|
||||||
case VT_LLONG:
|
case VT_LLONG:
|
||||||
*(long long *)ptr = vtop->c.i;
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
case VT_LLONG:
|
|
||||||
#endif
|
|
||||||
case VT_PTR:
|
case VT_PTR:
|
||||||
{
|
if (vtop->r & VT_SYM)
|
||||||
addr_t val = vtop->c.i;
|
greloca(sec, vtop->sym, c, R_DATA_PTR, val);
|
||||||
#if PTR_SIZE == 8
|
else
|
||||||
if (vtop->r & VT_SYM)
|
write64le(ptr, val);
|
||||||
greloca(sec, vtop->sym, c, R_DATA_PTR, val);
|
break;
|
||||||
else
|
case VT_INT:
|
||||||
*(addr_t *)ptr = val;
|
write32le(ptr, val);
|
||||||
|
break;
|
||||||
#else
|
#else
|
||||||
if (vtop->r & VT_SYM)
|
case VT_LLONG:
|
||||||
greloc(sec, vtop->sym, c, R_DATA_PTR);
|
write64le(ptr, val);
|
||||||
*(addr_t *)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
|
#endif
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
{
|
//tcc_internal_error("unexpected type");
|
||||||
int val = vtop->c.i;
|
break;
|
||||||
#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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vtop--;
|
vtop--;
|
||||||
|
@ -7975,9 +7983,8 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f
|
||||||
CType *t1;
|
CType *t1;
|
||||||
|
|
||||||
/* generate line number info */
|
/* generate line number info */
|
||||||
if (!p->sec && tcc_state->do_debug)
|
if (debug_modes && !p->sec)
|
||||||
tcc_debug_line(tcc_state);
|
tcc_debug_line(tcc_state), tcc_tcov_check_line (1);
|
||||||
tcc_tcov_check_line (1);
|
|
||||||
|
|
||||||
if (!(flags & DIF_HAVE_ELEM) && tok != '{' &&
|
if (!(flags & DIF_HAVE_ELEM) && tok != '{' &&
|
||||||
/* In case of strings we have special handling for arrays, so
|
/* In case of strings we have special handling for arrays, so
|
||||||
|
@ -8453,7 +8460,7 @@ static void gen_function(Sym *sym)
|
||||||
gsym(rsym);
|
gsym(rsym);
|
||||||
nocode_wanted = 0;
|
nocode_wanted = 0;
|
||||||
/* reset local stack */
|
/* reset local stack */
|
||||||
pop_local_syms(&local_stack, NULL, 0, func_var);
|
pop_local_syms(NULL, 0);
|
||||||
gfunc_epilog();
|
gfunc_epilog();
|
||||||
cur_text_section->data_offset = ind;
|
cur_text_section->data_offset = ind;
|
||||||
local_scope = 0;
|
local_scope = 0;
|
||||||
|
@ -8737,7 +8744,7 @@ found:
|
||||||
}
|
}
|
||||||
sym->a = ad.a;
|
sym->a = ad.a;
|
||||||
sym->f = ad.f;
|
sym->f = ad.f;
|
||||||
if (tcc_state->do_debug)
|
if (debug_modes)
|
||||||
tcc_debug_typedef (tcc_state, sym);
|
tcc_debug_typedef (tcc_state, sym);
|
||||||
} else if ((type.t & VT_BTYPE) == VT_VOID
|
} else if ((type.t & VT_BTYPE) == VT_VOID
|
||||||
&& !(type.t & VT_EXTERN)) {
|
&& !(type.t & VT_EXTERN)) {
|
||||||
|
|
42
tccpp.c
42
tccpp.c
|
@ -358,18 +358,11 @@ char *unicode_to_utf8 (char *b, uint32_t Uc)
|
||||||
/* add a unicode character expanded into utf8 */
|
/* add a unicode character expanded into utf8 */
|
||||||
void cstr_u8cat(CString *cstr, int ch)
|
void cstr_u8cat(CString *cstr, int ch)
|
||||||
{
|
{
|
||||||
unsigned char buf[4];
|
char buf[4], *e;
|
||||||
int size;
|
e = unicode_to_utf8(buf, (uint32_t)ch);
|
||||||
int add = (int)((unsigned char*)unicode_to_utf8((char *)&buf[0],(uint32_t)ch) - &buf[0]);
|
cstr_cat(cstr, buf, e - buf);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ST_FUNC void cstr_cat(CString *cstr, const char *str, int len)
|
ST_FUNC void cstr_cat(CString *cstr, const char *str, int len)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
|
@ -617,6 +610,7 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv)
|
||||||
}
|
}
|
||||||
addv:
|
addv:
|
||||||
*p++ = v;
|
*p++ = v;
|
||||||
|
case 0: /* nameless anonymous symbol */
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
} else if (v < tok_ident) {
|
} else if (v < tok_ident) {
|
||||||
return table_ident[v - TOK_IDENT]->str;
|
return table_ident[v - TOK_IDENT]->str;
|
||||||
|
@ -2095,7 +2089,7 @@ include_done:
|
||||||
/* evaluate escape codes in a string. */
|
/* evaluate escape codes in a string. */
|
||||||
static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
|
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;
|
const uint8_t *p;
|
||||||
|
|
||||||
p = buf;
|
p = buf;
|
||||||
|
@ -2125,13 +2119,13 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long
|
||||||
}
|
}
|
||||||
c = n;
|
c = n;
|
||||||
goto add_char_nonext;
|
goto add_char_nonext;
|
||||||
case 'x': { unsigned int i; unsigned ucn_chars_nr = -1u; goto parse_hex_or_ucn;
|
case 'x': i = 0; goto parse_hex_or_ucn;
|
||||||
case 'u': ucn_chars_nr = 4; goto parse_hex_or_ucn;
|
case 'u': i = 4; goto parse_hex_or_ucn;
|
||||||
case 'U': ucn_chars_nr = 8; goto parse_hex_or_ucn;
|
case 'U': i = 8; goto parse_hex_or_ucn;
|
||||||
parse_hex_or_ucn:;
|
parse_hex_or_ucn:
|
||||||
p++;
|
p++;
|
||||||
n = 0;
|
n = 0;
|
||||||
for(i=1;i<=ucn_chars_nr;i++) {
|
do {
|
||||||
c = *p;
|
c = *p;
|
||||||
if (c >= 'a' && c <= 'f')
|
if (c >= 'a' && c <= 'f')
|
||||||
c = c - 'a' + 10;
|
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;
|
c = c - 'A' + 10;
|
||||||
else if (isnum(c))
|
else if (isnum(c))
|
||||||
c = c - '0';
|
c = c - '0';
|
||||||
else{
|
else if (i > 0)
|
||||||
if (ucn_chars_nr!=-1)
|
expect("more hex digits in universal-character-name");
|
||||||
tcc_error("%u hex digits expected in universal-character-name\n", ucn_chars_nr);
|
else {
|
||||||
break;
|
c = n;
|
||||||
|
goto add_char_nonext;
|
||||||
}
|
}
|
||||||
n = n * 16 + c;
|
n = n * 16 + c;
|
||||||
p++;
|
p++;
|
||||||
}
|
} while (--i);
|
||||||
c = n;
|
cstr_u8cat(outstr, n);
|
||||||
if(ucn_chars_nr==-1) goto add_char_nonext;
|
|
||||||
cstr_u8cat(outstr, c);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
case 'a':
|
case 'a':
|
||||||
c = '\a';
|
c = '\a';
|
||||||
break;
|
break;
|
||||||
|
|
2
tccrun.c
2
tccrun.c
|
@ -183,7 +183,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (s1->do_bounds_check) {
|
if (s1->do_bounds_check) {
|
||||||
if ((p = tcc_get_symbol(s1, "__bound_init")))
|
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
|
#endif
|
||||||
set_exception_handler();
|
set_exception_handler();
|
||||||
|
|
6
tcctok.h
6
tcctok.h
|
@ -100,8 +100,10 @@
|
||||||
DEF(TOK___NAN__, "__nan__")
|
DEF(TOK___NAN__, "__nan__")
|
||||||
DEF(TOK___SNAN__, "__snan__")
|
DEF(TOK___SNAN__, "__snan__")
|
||||||
DEF(TOK___INF__, "__inf__")
|
DEF(TOK___INF__, "__inf__")
|
||||||
DEF(TOK___mzerosf, "__mzerosf")
|
#if defined TCC_TARGET_X86_64
|
||||||
DEF(TOK___mzerodf, "__mzerodf")
|
DEF(TOK___mzerosf, "__mzerosf") /* -0.0 */
|
||||||
|
DEF(TOK___mzerodf, "__mzerodf") /* -0.0 */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* attribute identifiers */
|
/* attribute identifiers */
|
||||||
/* XXX: handle all tokens generically since speed is not critical */
|
/* XXX: handle all tokens generically since speed is not critical */
|
||||||
|
|
|
@ -2830,9 +2830,6 @@ int reltab[3] = { 1, 2, 3 };
|
||||||
int *rel1 = &reltab[1];
|
int *rel1 = &reltab[1];
|
||||||
int *rel2 = &reltab[2];
|
int *rel2 = &reltab[2];
|
||||||
|
|
||||||
#ifdef _WIN64
|
|
||||||
void relocation_test(void) {}
|
|
||||||
#else
|
|
||||||
void getmyaddress(void)
|
void getmyaddress(void)
|
||||||
{
|
{
|
||||||
printf("in getmyaddress\n");
|
printf("in getmyaddress\n");
|
||||||
|
@ -2850,7 +2847,7 @@ long __pa_symbol(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned long theaddress = (unsigned long)getmyaddress;
|
uintptr_t theaddress = (uintptr_t)getmyaddress;
|
||||||
void relocation_test(void)
|
void relocation_test(void)
|
||||||
{
|
{
|
||||||
void (*fptr)(void) = (void (*)(void))theaddress;
|
void (*fptr)(void) = (void (*)(void))theaddress;
|
||||||
|
@ -2861,7 +2858,6 @@ void relocation_test(void)
|
||||||
printf("pa_symbol=0x%lx\n", __pa_symbol() >> 63);
|
printf("pa_symbol=0x%lx\n", __pa_symbol() >> 63);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void old_style_f(a,b,c)
|
void old_style_f(a,b,c)
|
||||||
int a, b;
|
int a, b;
|
||||||
|
|
Loading…
Reference in a new issue