mirror of https://repo.or.cz/tinycc.git
review recent commits
tccpp.c: - revert "Preprocessor fix + new testcase" Fix was not a fix and nobody could understand the test. This reverts6379f2ee76
- better fix and add new test (pp/18.c) tccgen.c: - remove global variables 'in_sizeof', 'constant_p' - rework comma expression (gexpr()) - merge func/data 'alias_target' codes (See08c777053c
) - move call to do_Static_assert() - better error: "expression expected before '%s'" - fix "statement after label" - remove unnecessary second parameter to block() - remove unnecessary call to decl() - revert changes to old C89 test file See7f0a28f6ca
tccelf.c: - rework "...make undefined global symbol STT_NOTYPE" (Seef44060f8fc
) - move tccelf_add_crtbegin() from libtcc.c tcctest: - unfix K&R fix (keep old look of K&R functions) tccrun.c: - exit(0) returns 0 libtcc.c: - move #defines for -dumpmachine - more explicit error "file not found" (as opposed to error while loading file) tccpe.c, x86_64-gen.c, i386-asm.c, tccasm.c: - use R_X86_64_PLT32 for functions on x86_64-win32 tccdefs.h - empty #defines for _Nonnull, __has_builtin(), etc. configure: - Simpler "macOS .dylib ... VERSION letters." (See6b967b1285
) Makefile: - macOS version also - add cross searchpaths for packages build.yml: - disable codesign on macos-11 (doesn't seem to work)
This commit is contained in:
parent
6426cc3384
commit
da0d43903b
|
@ -1,4 +1,4 @@
|
||||||
name: build and run tests
|
name: build and test
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
@ -17,7 +17,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: make & test tcc
|
- name: make & test tcc
|
||||||
run: ./configure && make && make test -k
|
run: ./configure --config-codesign=no && make && make test -k
|
||||||
|
|
||||||
test-x86_64-win32:
|
test-x86_64-win32:
|
||||||
runs-on: windows-2019
|
runs-on: windows-2019
|
||||||
|
|
10
Makefile
10
Makefile
|
@ -55,6 +55,8 @@ else
|
||||||
# `make test' when libtcc.dylib is used (configure --disable-static), so
|
# `make test' when libtcc.dylib is used (configure --disable-static), so
|
||||||
# we bake a relative path into the binary. $libdir is used after install.
|
# we bake a relative path into the binary. $libdir is used after install.
|
||||||
LINK_LIBTCC += -Wl,-rpath,"@executable_path/$(TOP)" -Wl,-rpath,"$(libdir)"
|
LINK_LIBTCC += -Wl,-rpath,"@executable_path/$(TOP)" -Wl,-rpath,"$(libdir)"
|
||||||
|
# -current/compatibility_version must not contain letters.
|
||||||
|
MACOS_DYLIB_VERSION := $(firstword $(subst rc, ,$(VERSION)))
|
||||||
DYLIBVER += -current_version $(MACOS_DYLIB_VERSION)
|
DYLIBVER += -current_version $(MACOS_DYLIB_VERSION)
|
||||||
DYLIBVER += -compatibility_version $(MACOS_DYLIB_VERSION)
|
DYLIBVER += -compatibility_version $(MACOS_DYLIB_VERSION)
|
||||||
endif
|
endif
|
||||||
|
@ -193,7 +195,6 @@ endif
|
||||||
# include custom configuration (see make help)
|
# include custom configuration (see make help)
|
||||||
-include config-extra.mak
|
-include config-extra.mak
|
||||||
|
|
||||||
ifneq ($(X),)
|
|
||||||
ifneq ($(T),$(NATIVE_TARGET))
|
ifneq ($(T),$(NATIVE_TARGET))
|
||||||
# assume support files for cross-targets in "/usr/<triplet>" by default
|
# assume support files for cross-targets in "/usr/<triplet>" by default
|
||||||
TRIPLET-i386 ?= i686-linux-gnu
|
TRIPLET-i386 ?= i686-linux-gnu
|
||||||
|
@ -201,11 +202,12 @@ TRIPLET-x86_64 ?= x86_64-linux-gnu
|
||||||
TRIPLET-arm ?= arm-linux-gnueabi
|
TRIPLET-arm ?= arm-linux-gnueabi
|
||||||
TRIPLET-arm64 ?= aarch64-linux-gnu
|
TRIPLET-arm64 ?= aarch64-linux-gnu
|
||||||
TRIPLET-riscv64 ?= riscv64-linux-gnu
|
TRIPLET-riscv64 ?= riscv64-linux-gnu
|
||||||
|
MARCH-i386 ?= i386-linux-gnu
|
||||||
|
MARCH-$T ?= $(TRIPLET-$T)
|
||||||
TR = $(if $(TRIPLET-$T),$T,ignored)
|
TR = $(if $(TRIPLET-$T),$T,ignored)
|
||||||
CRT-$(TR) ?= /usr/$(TRIPLET-$T)/lib
|
CRT-$(TR) ?= /usr/$(TRIPLET-$T)/lib
|
||||||
LIB-$(TR) ?= {B}:/usr/$(TRIPLET-$T)/lib
|
LIB-$(TR) ?= {B}:/usr/$(TRIPLET-$T)/lib:/usr/lib/$(MARCH-$T)
|
||||||
INC-$(TR) ?= {B}/include:/usr/$(TRIPLET-$T)/include
|
INC-$(TR) ?= {B}/include:/usr/$(TRIPLET-$T)/include:/usr/include
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccdbg.c tccelf.c tccasm.c tccrun.c
|
CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccdbg.c tccelf.c tccasm.c tccrun.c
|
||||||
|
|
|
@ -603,12 +603,6 @@ echo "VERSION = $version" >> config.mak
|
||||||
echo "#define TCC_VERSION \"$version\"" >> $TMPH
|
echo "#define TCC_VERSION \"$version\"" >> $TMPH
|
||||||
echo "@set VERSION $version" > config.texi
|
echo "@set VERSION $version" > config.texi
|
||||||
|
|
||||||
if test "$targetos" = "Darwin"; then
|
|
||||||
# On macOS, -current_version and -compatibility_version must not contain letters.
|
|
||||||
macos_dylib_version=`echo $version | sed 's/[^0-9.]//g'`
|
|
||||||
echo "MACOS_DYLIB_VERSION = $macos_dylib_version" >> config.mak
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$source_path_used" = "yes" ; then
|
if test "$source_path_used" = "yes" ; then
|
||||||
case $source_path in
|
case $source_path in
|
||||||
/*) echo "TOPSRC=$source_path";;
|
/*) echo "TOPSRC=$source_path";;
|
||||||
|
|
|
@ -515,7 +515,13 @@ static void gen_disp32(ExprValue *pe)
|
||||||
sym->type.t = VT_FUNC;
|
sym->type.t = VT_FUNC;
|
||||||
sym->type.ref = NULL;
|
sym->type.ref = NULL;
|
||||||
}
|
}
|
||||||
|
#ifdef TCC_TARGET_X86_64
|
||||||
|
greloca(cur_text_section, sym, ind, R_X86_64_PLT32, pe->v - 4);
|
||||||
|
gen_le32(0);
|
||||||
|
#else
|
||||||
gen_addrpc32(VT_SYM, sym, pe->v);
|
gen_addrpc32(VT_SYM, sym, pe->v);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,20 +124,16 @@
|
||||||
/* avoids usage of GCC/clang specific builtins in libc-headerfiles: */
|
/* avoids usage of GCC/clang specific builtins in libc-headerfiles: */
|
||||||
#define __FINITE_MATH_ONLY__ 1
|
#define __FINITE_MATH_ONLY__ 1
|
||||||
#define _FORTIFY_SOURCE 0
|
#define _FORTIFY_SOURCE 0
|
||||||
#define __has_builtin(x) 0
|
//#define __has_builtin(x) 0
|
||||||
|
|
||||||
#elif defined __ANDROID__
|
#elif defined __ANDROID__
|
||||||
#define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD
|
#define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD
|
||||||
#define __PRETTY_FUNCTION__ __FUNCTION__
|
|
||||||
#define __has_builtin(x) 0
|
|
||||||
#define __has_feature(x) 0
|
|
||||||
#define _Nonnull
|
|
||||||
#define _Nullable
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* Linux */
|
/* Linux */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Some derived integer types needed to get stdint.h to compile correctly on some platforms */
|
/* Some derived integer types needed to get stdint.h to compile correctly on some platforms */
|
||||||
#ifndef __NetBSD__
|
#ifndef __NetBSD__
|
||||||
#define __UINTPTR_TYPE__ unsigned __PTRDIFF_TYPE__
|
#define __UINTPTR_TYPE__ unsigned __PTRDIFF_TYPE__
|
||||||
|
@ -152,6 +148,16 @@
|
||||||
#define __REDIRECT_NTHNL(name, proto, alias) name proto __asm__ (#alias) __THROWNL
|
#define __REDIRECT_NTHNL(name, proto, alias) name proto __asm__ (#alias) __THROWNL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* not implemented */
|
||||||
|
#define __PRETTY_FUNCTION__ __FUNCTION__
|
||||||
|
#define __has_builtin(x) 0
|
||||||
|
#define __has_feature(x) 0
|
||||||
|
/* C23 Keywords */
|
||||||
|
#define _Nonnull
|
||||||
|
#define _Nullable
|
||||||
|
#define _Nullable_result
|
||||||
|
#define _Null_unspecified
|
||||||
|
|
||||||
/* skip __builtin... with -E */
|
/* skip __builtin... with -E */
|
||||||
#ifndef __TCC_PP__
|
#ifndef __TCC_PP__
|
||||||
|
|
||||||
|
|
166
libtcc.c
166
libtcc.c
|
@ -620,9 +620,9 @@ static void error1(int mode, const char *fmt, va_list ap)
|
||||||
f->filename, f->line_num - !!(tok_flags & TOK_FLAG_BOL));
|
f->filename, f->line_num - !!(tok_flags & TOK_FLAG_BOL));
|
||||||
} else if (s1->current_filename) {
|
} else if (s1->current_filename) {
|
||||||
cstr_printf(&cs, "%s: ", s1->current_filename);
|
cstr_printf(&cs, "%s: ", s1->current_filename);
|
||||||
}
|
} else {
|
||||||
if (0 == cs.size)
|
|
||||||
cstr_printf(&cs, "tcc: ");
|
cstr_printf(&cs, "tcc: ");
|
||||||
|
}
|
||||||
cstr_printf(&cs, mode == ERROR_WARN ? "warning: " : "error: ");
|
cstr_printf(&cs, mode == ERROR_WARN ? "warning: " : "error: ");
|
||||||
cstr_vprintf(&cs, fmt, ap);
|
cstr_vprintf(&cs, fmt, ap);
|
||||||
if (!s1 || !s1->error_func) {
|
if (!s1 || !s1->error_func) {
|
||||||
|
@ -930,17 +930,8 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* add sections */
|
||||||
tccelf_new(s);
|
tccelf_new(s);
|
||||||
if (s->do_debug) {
|
|
||||||
/* add debug sections */
|
|
||||||
tcc_debug_new(s);
|
|
||||||
}
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (s->do_bounds_check) {
|
|
||||||
/* if bound checking, then add corresponding sections */
|
|
||||||
tccelf_bounds_new(s);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (output_type == TCC_OUTPUT_OBJ) {
|
if (output_type == TCC_OUTPUT_OBJ) {
|
||||||
/* always elf for objects */
|
/* always elf for objects */
|
||||||
|
@ -951,66 +942,21 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
||||||
tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
|
tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
# ifdef _WIN32
|
# ifdef TCC_IS_NATIVE
|
||||||
/* allow linking with system dll's directly */
|
/* allow linking with system dll's directly */
|
||||||
tcc_add_systemdir(s);
|
tcc_add_systemdir(s);
|
||||||
# endif
|
# endif
|
||||||
/* target PE has its own startup code in libtcc1.a */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#elif defined TCC_TARGET_MACHO
|
#elif defined TCC_TARGET_MACHO
|
||||||
# ifdef TCC_IS_NATIVE
|
# ifdef TCC_IS_NATIVE
|
||||||
tcc_add_macos_sdkpath(s);
|
tcc_add_macos_sdkpath(s);
|
||||||
# endif
|
# endif
|
||||||
/* Mach-O with LC_MAIN doesn't need any crt startup code. */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* paths for crt objects */
|
/* paths for crt objects */
|
||||||
tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
|
tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
|
||||||
|
if (output_type != TCC_OUTPUT_MEMORY && !s->nostdlib)
|
||||||
/* add libc crt1/crti objects */
|
tccelf_add_crtbegin(s);
|
||||||
if (output_type != TCC_OUTPUT_MEMORY && !s->nostdlib) {
|
|
||||||
#if TARGETOS_OpenBSD
|
|
||||||
if (output_type != TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s, "crt0.o");
|
|
||||||
if (output_type == TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s, "crtbeginS.o");
|
|
||||||
else
|
|
||||||
tcc_add_crt(s, "crtbegin.o");
|
|
||||||
#elif TARGETOS_FreeBSD
|
|
||||||
if (output_type != TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s, "crt1.o");
|
|
||||||
tcc_add_crt(s, "crti.o");
|
|
||||||
if (s->static_link)
|
|
||||||
tcc_add_crt(s, "crtbeginT.o");
|
|
||||||
else if (output_type & TCC_OUTPUT_DYN)
|
|
||||||
tcc_add_crt(s, "crtbeginS.o");
|
|
||||||
else
|
|
||||||
tcc_add_crt(s, "crtbegin.o");
|
|
||||||
#elif TARGETOS_NetBSD
|
|
||||||
if (output_type != TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s, "crt0.o");
|
|
||||||
tcc_add_crt(s, "crti.o");
|
|
||||||
if (s->static_link)
|
|
||||||
tcc_add_crt(s, "crtbeginT.o");
|
|
||||||
else if (output_type & TCC_OUTPUT_DYN)
|
|
||||||
tcc_add_crt(s, "crtbeginS.o");
|
|
||||||
else
|
|
||||||
tcc_add_crt(s, "crtbegin.o");
|
|
||||||
#elif defined TARGETOS_ANDROID
|
|
||||||
if (output_type != TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s, "crtbegin_dynamic.o");
|
|
||||||
else
|
|
||||||
tcc_add_crt(s, "crtbegin_so.o");
|
|
||||||
#else
|
|
||||||
if (output_type != TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s, "crt1.o");
|
|
||||||
tcc_add_crt(s, "crti.o");
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
|
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
|
||||||
|
@ -1096,7 +1042,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
if (flags & AFF_PRINT_ERROR)
|
if (flags & AFF_PRINT_ERROR)
|
||||||
tcc_error_noabort("file '%s' not found", filename);
|
tcc_error_noabort("file '%s' not found", filename);
|
||||||
return ret;
|
return FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
s1->current_filename = filename;
|
s1->current_filename = filename;
|
||||||
|
@ -1226,18 +1172,21 @@ LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tcc_add_library_internal(TCCState *s, const char *fmt,
|
static int tcc_add_library_internal(TCCState *s1, const char *fmt,
|
||||||
const char *filename, int flags, char **paths, int nb_paths)
|
const char *filename, int flags, char **paths, int nb_paths)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int i;
|
int i, ret;
|
||||||
|
|
||||||
for(i = 0; i < nb_paths; i++) {
|
for(i = 0; i < nb_paths; i++) {
|
||||||
snprintf(buf, sizeof(buf), fmt, paths[i], filename);
|
snprintf(buf, sizeof(buf), fmt, paths[i], filename);
|
||||||
if (tcc_add_file_internal(s, buf, flags | AFF_TYPE_BIN) == 0)
|
ret = tcc_add_file_internal(s1, buf, (flags & ~AFF_PRINT_ERROR) | AFF_TYPE_BIN);
|
||||||
return 0;
|
if (ret != FILE_NOT_FOUND)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
return -1;
|
if (flags & AFF_PRINT_ERROR)
|
||||||
|
tcc_error_noabort("file '%s' not found", filename);
|
||||||
|
return FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find and load a dll. Return non zero if not found */
|
/* find and load a dll. Return non zero if not found */
|
||||||
|
@ -1253,17 +1202,14 @@ ST_FUNC void tcc_add_support(TCCState *s1, const char *filename)
|
||||||
char buf[100];
|
char buf[100];
|
||||||
if (CONFIG_TCC_CROSSPREFIX[0])
|
if (CONFIG_TCC_CROSSPREFIX[0])
|
||||||
filename = strcat(strcpy(buf, CONFIG_TCC_CROSSPREFIX), filename);
|
filename = strcat(strcpy(buf, CONFIG_TCC_CROSSPREFIX), filename);
|
||||||
if (tcc_add_dll(s1, filename, 0) < 0)
|
tcc_add_dll(s1, filename, AFF_PRINT_ERROR);
|
||||||
tcc_error_noabort("%s not found", filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO
|
#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO
|
||||||
ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
|
ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
|
||||||
{
|
{
|
||||||
if (-1 == tcc_add_library_internal(s1, "%s/%s",
|
return tcc_add_library_internal(s1, "%s/%s",
|
||||||
filename, 0, s1->crt_paths, s1->nb_crt_paths))
|
filename, AFF_PRINT_ERROR, s1->crt_paths, s1->nb_crt_paths);
|
||||||
return tcc_error_noabort("file '%s' not found", filename);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1285,18 +1231,19 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
|
||||||
#endif
|
#endif
|
||||||
int flags = s->filetype & AFF_WHOLE_ARCHIVE;
|
int flags = s->filetype & AFF_WHOLE_ARCHIVE;
|
||||||
while (*pp) {
|
while (*pp) {
|
||||||
if (0 == tcc_add_library_internal(s, *pp,
|
int ret = tcc_add_library_internal(s, *pp,
|
||||||
libraryname, flags, s->library_paths, s->nb_library_paths))
|
libraryname, flags, s->library_paths, s->nb_library_paths);
|
||||||
return 0;
|
if (ret != FILE_NOT_FOUND)
|
||||||
|
return ret;
|
||||||
++pp;
|
++pp;
|
||||||
}
|
}
|
||||||
return -1;
|
return FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUB_FUNC int tcc_add_library_err(TCCState *s1, const char *libname)
|
PUB_FUNC int tcc_add_library_err(TCCState *s1, const char *libname)
|
||||||
{
|
{
|
||||||
int ret = tcc_add_library(s1, libname);
|
int ret = tcc_add_library(s1, libname);
|
||||||
if (ret < 0)
|
if (ret == FILE_NOT_FOUND)
|
||||||
tcc_error_noabort("library '%s' not found", libname);
|
tcc_error_noabort("library '%s' not found", libname);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1790,6 +1737,37 @@ static int set_flag(TCCState *s, const FlagDef *flags, const char *name)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char dumpmachine_str[] =
|
||||||
|
/* this is a best guess, please refine as necessary */
|
||||||
|
#ifdef TCC_TARGET_I386
|
||||||
|
"i386-pc"
|
||||||
|
#elif defined TCC_TARGET_X86_64
|
||||||
|
"x86_64-pc"
|
||||||
|
#elif defined TCC_TARGET_C67
|
||||||
|
"c67"
|
||||||
|
#elif defined TCC_TARGET_ARM
|
||||||
|
"arm"
|
||||||
|
#elif defined TCC_TARGET_ARM64
|
||||||
|
"aarch64"
|
||||||
|
#elif defined TCC_TARGET_RISCV64
|
||||||
|
"riscv64"
|
||||||
|
#endif
|
||||||
|
"-"
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
"mingw32"
|
||||||
|
#elif defined(TCC_TARGET_MACHO)
|
||||||
|
"apple-darwin"
|
||||||
|
#elif TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
|
||||||
|
"freebsd"
|
||||||
|
#elif TARGETOS_OpenBSD
|
||||||
|
"openbsd"
|
||||||
|
#elif TARGETOS_NetBSD
|
||||||
|
"netbsd"
|
||||||
|
#else
|
||||||
|
"linux-gnu"
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
static int args_parser_make_argv(const char *r, int *argc, char ***argv)
|
static int args_parser_make_argv(const char *r, int *argc, char ***argv)
|
||||||
{
|
{
|
||||||
int ret = 0, q, c;
|
int ret = 0, q, c;
|
||||||
|
@ -2140,43 +2118,11 @@ dorun:
|
||||||
s->gen_phony_deps = 1;
|
s->gen_phony_deps = 1;
|
||||||
break;
|
break;
|
||||||
case TCC_OPTION_dumpmachine:
|
case TCC_OPTION_dumpmachine:
|
||||||
/* this is a best guess, please refine as necessary */
|
printf("%s\n", dumpmachine_str);
|
||||||
printf("%s",
|
|
||||||
#ifdef TCC_TARGET_I386
|
|
||||||
"i386-pc"
|
|
||||||
#elif defined TCC_TARGET_X86_64
|
|
||||||
"x86_64-pc"
|
|
||||||
#elif defined TCC_TARGET_C67
|
|
||||||
"c67"
|
|
||||||
#elif defined TCC_TARGET_ARM
|
|
||||||
"arm"
|
|
||||||
#elif defined TCC_TARGET_ARM64
|
|
||||||
"aarch64"
|
|
||||||
#elif defined TCC_TARGET_RISCV64
|
|
||||||
"riscv64"
|
|
||||||
#endif
|
|
||||||
"-"
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
"mingw32"
|
|
||||||
#elif defined(TCC_TARGET_MACHO)
|
|
||||||
"apple-darwin"
|
|
||||||
#elif TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
|
|
||||||
"freebsd"
|
|
||||||
#elif TARGETOS_OpenBSD
|
|
||||||
"openbsd"
|
|
||||||
#elif TARGETOS_NetBSD
|
|
||||||
"netbsd"
|
|
||||||
#else
|
|
||||||
"linux-gnu"
|
|
||||||
#endif
|
|
||||||
"\n"
|
|
||||||
);
|
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
|
||||||
case TCC_OPTION_dumpversion:
|
case TCC_OPTION_dumpversion:
|
||||||
printf ("%s\n", TCC_VERSION);
|
printf ("%s\n", TCC_VERSION);
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
|
||||||
case TCC_OPTION_x:
|
case TCC_OPTION_x:
|
||||||
x = 0;
|
x = 0;
|
||||||
if (*optarg == 'c')
|
if (*optarg == 'c')
|
||||||
|
|
9
tcc.h
9
tcc.h
|
@ -1155,6 +1155,7 @@ struct filespec {
|
||||||
#define TOK_PLCHLDR 0xa4 /* placeholder token as defined in C99 */
|
#define TOK_PLCHLDR 0xa4 /* placeholder token as defined in C99 */
|
||||||
#define TOK_NOSUBST 0xa5 /* means following token has already been pp'd */
|
#define TOK_NOSUBST 0xa5 /* means following token has already been pp'd */
|
||||||
#define TOK_PPJOIN 0xa6 /* A '##' in the right position to mean pasting */
|
#define TOK_PPJOIN 0xa6 /* A '##' in the right position to mean pasting */
|
||||||
|
#define TOK_SOTYPE 0xa7 /* alias of '(' for parsing sizeof (type) */
|
||||||
|
|
||||||
/* assignment operators */
|
/* assignment operators */
|
||||||
#define TOK_A_ADD 0xb0
|
#define TOK_A_ADD 0xb0
|
||||||
|
@ -1291,6 +1292,9 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||||
#define AFF_BINTYPE_AR 3
|
#define AFF_BINTYPE_AR 3
|
||||||
#define AFF_BINTYPE_C67 4
|
#define AFF_BINTYPE_C67 4
|
||||||
|
|
||||||
|
/* return value of tcc_add_file_internal(): 0, -1, or FILE_NOT_FOUND */
|
||||||
|
#define FILE_NOT_FOUND -2
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
#ifndef ELF_OBJ_ONLY
|
||||||
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
|
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1532,9 +1536,6 @@ ST_FUNC void tccelf_new(TCCState *s);
|
||||||
ST_FUNC void tccelf_delete(TCCState *s);
|
ST_FUNC void tccelf_delete(TCCState *s);
|
||||||
ST_FUNC void tccelf_begin_file(TCCState *s1);
|
ST_FUNC void tccelf_begin_file(TCCState *s1);
|
||||||
ST_FUNC void tccelf_end_file(TCCState *s1);
|
ST_FUNC void tccelf_end_file(TCCState *s1);
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
ST_FUNC void tccelf_bounds_new(TCCState *s);
|
|
||||||
#endif
|
|
||||||
ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
|
ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
|
||||||
ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
|
ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
|
||||||
ST_FUNC size_t section_add(Section *sec, addr_t size, int align);
|
ST_FUNC size_t section_add(Section *sec, addr_t size, int align);
|
||||||
|
@ -1575,6 +1576,8 @@ ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t
|
||||||
#ifndef ELF_OBJ_ONLY
|
#ifndef ELF_OBJ_ONLY
|
||||||
ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level);
|
ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level);
|
||||||
ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd);
|
ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd);
|
||||||
|
ST_FUNC void tccelf_add_crtbegin(TCCState *s1);
|
||||||
|
ST_FUNC void tccelf_add_crtend(TCCState *s1);
|
||||||
#endif
|
#endif
|
||||||
#ifndef TCC_TARGET_PE
|
#ifndef TCC_TARGET_PE
|
||||||
ST_FUNC void tcc_add_runtime(TCCState *s1);
|
ST_FUNC void tcc_add_runtime(TCCState *s1);
|
||||||
|
|
4
tccasm.c
4
tccasm.c
|
@ -834,6 +834,10 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||||
|
|
||||||
if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
|
if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
|
||||||
sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC;
|
sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC;
|
||||||
|
if (sym->c) {
|
||||||
|
ElfSym *esym = elfsym(sym);
|
||||||
|
esym->st_info = ELFW(ST_INFO)(ELFW(ST_BIND)(esym->st_info), STT_FUNC);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
tcc_warning_c(warn_unsupported)("change type of '%s' from 0x%x to '%s' ignored",
|
tcc_warning_c(warn_unsupported)("change type of '%s' from 0x%x to '%s' ignored",
|
||||||
get_tok_str(sym->v, NULL), sym->type.t, newtype);
|
get_tok_str(sym->v, NULL), sym->type.t, newtype);
|
||||||
|
|
134
tccelf.c
134
tccelf.c
|
@ -83,17 +83,21 @@ ST_FUNC void tccelf_new(TCCState *s)
|
||||||
".dynstrtab",
|
".dynstrtab",
|
||||||
".dynhashtab", SHF_PRIVATE);
|
".dynhashtab", SHF_PRIVATE);
|
||||||
get_sym_attr(s, 0, 1);
|
get_sym_attr(s, 0, 1);
|
||||||
}
|
|
||||||
|
if (s->do_debug) {
|
||||||
|
/* add debug sections */
|
||||||
|
tcc_debug_new(s);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
ST_FUNC void tccelf_bounds_new(TCCState *s)
|
if (s->do_bounds_check) {
|
||||||
{
|
/* if bound checking, then add corresponding sections */
|
||||||
TCCState *s1 = s;
|
/* (make ro after relocation done with GNU_RELRO) */
|
||||||
/* create bounds sections (make ro after relocation done with GNU_RELRO) */
|
bounds_section = new_section(s, ".bounds", SHT_PROGBITS, shf_RELRO);
|
||||||
bounds_section = new_section(s, ".bounds", SHT_PROGBITS, shf_RELRO);
|
lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, shf_RELRO);
|
||||||
lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, shf_RELRO);
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void free_section(Section *s)
|
static void free_section(Section *s)
|
||||||
{
|
{
|
||||||
|
@ -173,16 +177,22 @@ ST_FUNC void tccelf_end_file(TCCState *s1)
|
||||||
|
|
||||||
for (i = 0; i < nb_syms; ++i) {
|
for (i = 0; i < nb_syms; ++i) {
|
||||||
ElfSym *sym = (ElfSym*)s->data + first_sym + i;
|
ElfSym *sym = (ElfSym*)s->data + first_sym + i;
|
||||||
if (sym->st_shndx == SHN_UNDEF
|
|
||||||
&& ELFW(ST_BIND)(sym->st_info) == STB_LOCAL)
|
if (sym->st_shndx == SHN_UNDEF) {
|
||||||
sym->st_info = ELFW(ST_INFO)(STB_GLOBAL, ELFW(ST_TYPE)(sym->st_info));
|
int sym_bind = ELFW(ST_BIND)(sym->st_info);
|
||||||
|
int sym_type = ELFW(ST_TYPE)(sym->st_info);
|
||||||
|
if (sym_bind == STB_LOCAL)
|
||||||
|
sym_bind = STB_GLOBAL;
|
||||||
#ifndef TCC_TARGET_PE
|
#ifndef TCC_TARGET_PE
|
||||||
/* An ELF relocatable file should have the types of its undefined global symbol set
|
if (sym_bind == STB_GLOBAL && s1->output_type == TCC_OUTPUT_OBJ) {
|
||||||
to STT_NOTYPE or it will confuse binutils bfd */
|
/* undefined symbols with STT_FUNC are confusing gnu ld when
|
||||||
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF && s1->output_type == TCC_OUTPUT_OBJ)
|
linking statically to STT_GNU_IFUNC */
|
||||||
if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL)
|
sym_type = STT_NOTYPE;
|
||||||
sym->st_info = ELFW(ST_INFO)(STB_GLOBAL, ELFW(ST_TYPE)(STT_NOTYPE));
|
}
|
||||||
#endif
|
#endif
|
||||||
|
sym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
|
||||||
|
}
|
||||||
|
|
||||||
tr[i] = set_elf_sym(s, sym->st_value, sym->st_size, sym->st_info,
|
tr[i] = set_elf_sym(s, sym->st_value, sym->st_size, sym->st_info,
|
||||||
sym->st_other, sym->st_shndx, (char*)s->link->data + sym->st_name);
|
sym->st_other, sym->st_shndx, (char*)s->link->data + sym->st_name);
|
||||||
}
|
}
|
||||||
|
@ -1666,6 +1676,67 @@ static void tcc_tcov_add_file(TCCState *s1, const char *filename)
|
||||||
set_local_sym(s1, &"___tcov_data"[!s1->leading_underscore], tcov_section, 0);
|
set_local_sym(s1, &"___tcov_data"[!s1->leading_underscore], tcov_section, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO
|
||||||
|
/* add libc crt1/crti objects */
|
||||||
|
ST_FUNC void tccelf_add_crtbegin(TCCState *s1)
|
||||||
|
{
|
||||||
|
#if TARGETOS_OpenBSD
|
||||||
|
if (s1->output_type != TCC_OUTPUT_DLL)
|
||||||
|
tcc_add_crt(s1, "crt0.o");
|
||||||
|
if (s1->output_type == TCC_OUTPUT_DLL)
|
||||||
|
tcc_add_crt(s1, "crtbeginS.o");
|
||||||
|
else
|
||||||
|
tcc_add_crt(s1, "crtbegin.o");
|
||||||
|
#elif TARGETOS_FreeBSD || TARGETOS_NetBSD
|
||||||
|
if (s1->output_type != TCC_OUTPUT_DLL)
|
||||||
|
#if TARGETOS_FreeBSD
|
||||||
|
tcc_add_crt(s1, "crt1.o");
|
||||||
|
#else
|
||||||
|
tcc_add_crt(s1, "crt0.o");
|
||||||
|
#endif
|
||||||
|
tcc_add_crt(s1, "crti.o");
|
||||||
|
if (s1->static_link)
|
||||||
|
tcc_add_crt(s1, "crtbeginT.o");
|
||||||
|
else if (s1->output_type == TCC_OUTPUT_DLL)
|
||||||
|
tcc_add_crt(s1, "crtbeginS.o");
|
||||||
|
else
|
||||||
|
tcc_add_crt(s1, "crtbegin.o");
|
||||||
|
#elif TARGETOS_ANDROID
|
||||||
|
if (s1->output_type == TCC_OUTPUT_DLL)
|
||||||
|
tcc_add_crt(s1, "crtbegin_so.o");
|
||||||
|
else
|
||||||
|
tcc_add_crt(s1, "crtbegin_dynamic.o");
|
||||||
|
#else
|
||||||
|
if (s1->output_type != TCC_OUTPUT_DLL)
|
||||||
|
tcc_add_crt(s1, "crt1.o");
|
||||||
|
tcc_add_crt(s1, "crti.o");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC void tccelf_add_crtend(TCCState *s1)
|
||||||
|
{
|
||||||
|
#if TARGETOS_OpenBSD
|
||||||
|
if (s1->output_type == TCC_OUTPUT_DLL)
|
||||||
|
tcc_add_crt(s1, "crtendS.o");
|
||||||
|
else
|
||||||
|
tcc_add_crt(s1, "crtend.o");
|
||||||
|
#elif TARGETOS_FreeBSD || TARGETOS_NetBSD
|
||||||
|
if (s1->output_type == TCC_OUTPUT_DLL)
|
||||||
|
tcc_add_crt(s1, "crtendS.o");
|
||||||
|
else
|
||||||
|
tcc_add_crt(s1, "crtend.o");
|
||||||
|
tcc_add_crt(s1, "crtn.o");
|
||||||
|
#elif TARGETOS_ANDROID
|
||||||
|
if (s1->output_type == TCC_OUTPUT_DLL)
|
||||||
|
tcc_add_crt(s1, "crtend_so.o");
|
||||||
|
else
|
||||||
|
tcc_add_crt(s1, "crtend_android.o");
|
||||||
|
#else
|
||||||
|
tcc_add_crt(s1, "crtn.o");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif /* !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO */
|
||||||
|
|
||||||
#ifndef TCC_TARGET_PE
|
#ifndef TCC_TARGET_PE
|
||||||
/* add tcc runtime libraries */
|
/* add tcc runtime libraries */
|
||||||
ST_FUNC void tcc_add_runtime(TCCState *s1)
|
ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||||
|
@ -1708,7 +1779,7 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||||
if (TCC_LIBGCC[0] == '/')
|
if (TCC_LIBGCC[0] == '/')
|
||||||
tcc_add_file(s1, TCC_LIBGCC);
|
tcc_add_file(s1, TCC_LIBGCC);
|
||||||
else
|
else
|
||||||
tcc_add_dll(s1, TCC_LIBGCC, 0);
|
tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined TCC_TARGET_ARM && TARGETOS_FreeBSD
|
#if defined TCC_TARGET_ARM && TARGETOS_FreeBSD
|
||||||
|
@ -1716,31 +1787,10 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||||
#endif
|
#endif
|
||||||
if (TCC_LIBTCC1[0])
|
if (TCC_LIBTCC1[0])
|
||||||
tcc_add_support(s1, TCC_LIBTCC1);
|
tcc_add_support(s1, TCC_LIBTCC1);
|
||||||
|
#ifndef TCC_TARGET_MACHO
|
||||||
/* add crt end if not memory output */
|
if (s1->output_type != TCC_OUTPUT_MEMORY)
|
||||||
if (s1->output_type != TCC_OUTPUT_MEMORY) {
|
tccelf_add_crtend(s1);
|
||||||
#if defined TCC_TARGET_MACHO
|
|
||||||
/* nothing to do */
|
|
||||||
#elif TARGETOS_FreeBSD || TARGETOS_NetBSD
|
|
||||||
if (s1->output_type & TCC_OUTPUT_DYN)
|
|
||||||
tcc_add_crt(s1, "crtendS.o");
|
|
||||||
else
|
|
||||||
tcc_add_crt(s1, "crtend.o");
|
|
||||||
tcc_add_crt(s1, "crtn.o");
|
|
||||||
#elif TARGETOS_OpenBSD
|
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s1, "crtendS.o");
|
|
||||||
else
|
|
||||||
tcc_add_crt(s1, "crtend.o");
|
|
||||||
#elif TARGETOS_ANDROID
|
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s1, "crtend_so.o");
|
|
||||||
else
|
|
||||||
tcc_add_crt(s1, "crtend_android.o");
|
|
||||||
#else
|
|
||||||
tcc_add_crt(s1, "crtn.o");
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* ndef TCC_TARGET_PE */
|
#endif /* ndef TCC_TARGET_PE */
|
||||||
|
@ -3834,7 +3884,7 @@ static int ld_add_file(TCCState *s1, const char filename[])
|
||||||
return 0;
|
return 0;
|
||||||
filename = tcc_basename(filename);
|
filename = tcc_basename(filename);
|
||||||
}
|
}
|
||||||
return tcc_add_dll(s1, filename, 0);
|
return tcc_add_dll(s1, filename, AFF_PRINT_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
|
static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
|
||||||
|
|
168
tccgen.c
168
tccgen.c
|
@ -43,8 +43,6 @@ static int nb_sym_pools;
|
||||||
|
|
||||||
static Sym *all_cleanups, *pending_gotos;
|
static Sym *all_cleanups, *pending_gotos;
|
||||||
static int local_scope;
|
static int local_scope;
|
||||||
static int in_sizeof;
|
|
||||||
static int constant_p;
|
|
||||||
ST_DATA char debug_modes;
|
ST_DATA char debug_modes;
|
||||||
|
|
||||||
ST_DATA SValue *vtop;
|
ST_DATA SValue *vtop;
|
||||||
|
@ -130,6 +128,10 @@ typedef struct {
|
||||||
static void init_prec(void);
|
static void init_prec(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void block(int flags);
|
||||||
|
#define STMT_EXPR 1
|
||||||
|
#define STMT_COMPOUND 2
|
||||||
|
|
||||||
static void gen_cast(CType *type);
|
static void gen_cast(CType *type);
|
||||||
static void gen_cast_s(int t);
|
static void gen_cast_s(int t);
|
||||||
static inline CType *pointed_type(CType *type);
|
static inline CType *pointed_type(CType *type);
|
||||||
|
@ -139,7 +141,6 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
|
||||||
static void parse_expr_type(CType *type);
|
static void parse_expr_type(CType *type);
|
||||||
static void init_putv(init_params *p, CType *type, unsigned long c);
|
static void init_putv(init_params *p, CType *type, unsigned long c);
|
||||||
static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags);
|
static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags);
|
||||||
static void block(int is_expr, int allow_decl);
|
|
||||||
static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope);
|
static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope);
|
||||||
static int decl(int l);
|
static int decl(int l);
|
||||||
static void expr_eq(void);
|
static void expr_eq(void);
|
||||||
|
@ -3466,11 +3467,7 @@ static void vpush_type_size(CType *type, int *a)
|
||||||
int size = type_size(type, a);
|
int size = type_size(type, a);
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
tcc_error("unknown type size");
|
tcc_error("unknown type size");
|
||||||
#if PTR_SIZE == 8
|
vpushs(size);
|
||||||
vpushll(size);
|
|
||||||
#else
|
|
||||||
vpushi(size);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4433,11 +4430,11 @@ do_decl:
|
||||||
c = 0;
|
c = 0;
|
||||||
flexible = 0;
|
flexible = 0;
|
||||||
while (tok != '}') {
|
while (tok != '}') {
|
||||||
if (tok == TOK_STATIC_ASSERT) {
|
|
||||||
do_Static_assert();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!parse_btype(&btype, &ad1, 0)) {
|
if (!parse_btype(&btype, &ad1, 0)) {
|
||||||
|
if (tok == TOK_STATIC_ASSERT) {
|
||||||
|
do_Static_assert();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
skip(';');
|
skip(';');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -4844,7 +4841,7 @@ static inline void convert_parameter_type(CType *pt)
|
||||||
to indicate a const function parameter */
|
to indicate a const function parameter */
|
||||||
pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
|
pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
|
||||||
/* array must be transformed to pointer according to ANSI C */
|
/* array must be transformed to pointer according to ANSI C */
|
||||||
pt->t &= ~VT_ARRAY;
|
pt->t &= ~(VT_ARRAY | VT_VLA);
|
||||||
if ((pt->t & VT_BTYPE) == VT_FUNC) {
|
if ((pt->t & VT_BTYPE) == VT_FUNC) {
|
||||||
mk_pointer(pt);
|
mk_pointer(pt);
|
||||||
}
|
}
|
||||||
|
@ -5069,7 +5066,8 @@ check:
|
||||||
type->ref = s;
|
type->ref = s;
|
||||||
|
|
||||||
if (vla_array_str) {
|
if (vla_array_str) {
|
||||||
if (t1 & VT_VLA)
|
/* for function args, the top dimension is converted to pointer */
|
||||||
|
if ((t1 & VT_VLA) && (td & TYPE_NEST))
|
||||||
s->vla_array_str = vla_array_str;
|
s->vla_array_str = vla_array_str;
|
||||||
else
|
else
|
||||||
tok_str_free_str(vla_array_str);
|
tok_str_free_str(vla_array_str);
|
||||||
|
@ -5435,7 +5433,7 @@ static void parse_atomic(int atok)
|
||||||
|
|
||||||
ST_FUNC void unary(void)
|
ST_FUNC void unary(void)
|
||||||
{
|
{
|
||||||
int n, t, align, size, r, sizeof_caller;
|
int n, t, align, size, r;
|
||||||
CType type;
|
CType type;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
AttributeDef ad;
|
AttributeDef ad;
|
||||||
|
@ -5444,8 +5442,6 @@ ST_FUNC void unary(void)
|
||||||
if (debug_modes)
|
if (debug_modes)
|
||||||
tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1);
|
tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1);
|
||||||
|
|
||||||
sizeof_caller = in_sizeof;
|
|
||||||
in_sizeof = 0;
|
|
||||||
type.ref = NULL;
|
type.ref = NULL;
|
||||||
/* XXX: GCC 2.95.3 does not generate a table although it should be
|
/* XXX: GCC 2.95.3 does not generate a table although it should be
|
||||||
better here */
|
better here */
|
||||||
|
@ -5527,7 +5523,9 @@ ST_FUNC void unary(void)
|
||||||
ad.section = rodata_section;
|
ad.section = rodata_section;
|
||||||
decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
|
decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
|
||||||
break;
|
break;
|
||||||
|
case TOK_SOTYPE:
|
||||||
case '(':
|
case '(':
|
||||||
|
t = tok;
|
||||||
next();
|
next();
|
||||||
/* cast ? */
|
/* cast ? */
|
||||||
if (parse_btype(&type, &ad, 0)) {
|
if (parse_btype(&type, &ad, 0)) {
|
||||||
|
@ -5545,11 +5543,10 @@ ST_FUNC void unary(void)
|
||||||
r |= VT_LVAL;
|
r |= VT_LVAL;
|
||||||
memset(&ad, 0, sizeof(AttributeDef));
|
memset(&ad, 0, sizeof(AttributeDef));
|
||||||
decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
|
decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
|
||||||
|
} else if (t == TOK_SOTYPE) { /* from sizeof/alignof (...) */
|
||||||
|
vpush(&type);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (sizeof_caller) {
|
|
||||||
vpush(&type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
unary();
|
unary();
|
||||||
gen_cast(&type);
|
gen_cast(&type);
|
||||||
}
|
}
|
||||||
|
@ -5566,7 +5563,7 @@ ST_FUNC void unary(void)
|
||||||
as statement expressions can't ever be entered from the
|
as statement expressions can't ever be entered from the
|
||||||
outside, so any reactivation of code emission (from labels
|
outside, so any reactivation of code emission (from labels
|
||||||
or loop heads) can be disabled again after the end of it. */
|
or loop heads) can be disabled again after the end of it. */
|
||||||
block(1, 0);
|
block(STMT_EXPR);
|
||||||
/* If the statement expr can be entered, then we retain the current
|
/* If the statement expr can be entered, then we retain the current
|
||||||
nocode_wanted state (from e.g. a 'return 0;' in the stmt-expr).
|
nocode_wanted state (from e.g. a 'return 0;' in the stmt-expr).
|
||||||
If it can't be entered then the state is that from before the
|
If it can't be entered then the state is that from before the
|
||||||
|
@ -5630,8 +5627,9 @@ ST_FUNC void unary(void)
|
||||||
case TOK_ALIGNOF3:
|
case TOK_ALIGNOF3:
|
||||||
t = tok;
|
t = tok;
|
||||||
next();
|
next();
|
||||||
in_sizeof++;
|
if (tok == '(')
|
||||||
expr_type(&type, unary); /* Perform a in_sizeof = 0; */
|
tok = TOK_SOTYPE;
|
||||||
|
expr_type(&type, unary);
|
||||||
if (t == TOK_SIZEOF) {
|
if (t == TOK_SIZEOF) {
|
||||||
vpush_type_size(&type, &align);
|
vpush_type_size(&type, &align);
|
||||||
gen_cast_s(VT_SIZE_T);
|
gen_cast_s(VT_SIZE_T);
|
||||||
|
@ -5687,11 +5685,12 @@ ST_FUNC void unary(void)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TOK_builtin_constant_p:
|
case TOK_builtin_constant_p:
|
||||||
constant_p = 1;
|
|
||||||
parse_builtin_params(1, "e");
|
parse_builtin_params(1, "e");
|
||||||
n = constant_p &&
|
n = 1;
|
||||||
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
|
if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST
|
||||||
!((vtop->r & VT_SYM) && vtop->sym->a.addrtaken);
|
|| ((vtop->r & VT_SYM) && vtop->sym->a.addrtaken)
|
||||||
|
)
|
||||||
|
n = 0;
|
||||||
vtop--;
|
vtop--;
|
||||||
vpushi(n);
|
vpushi(n);
|
||||||
break;
|
break;
|
||||||
|
@ -5947,10 +5946,10 @@ special_math_val:
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tok_identifier:
|
tok_identifier:
|
||||||
|
if (tok < TOK_UIDENT)
|
||||||
|
tcc_error("expression expected before '%s'", get_tok_str(tok, &tokc));
|
||||||
t = tok;
|
t = tok;
|
||||||
next();
|
next();
|
||||||
if (t < TOK_UIDENT)
|
|
||||||
expect("identifier");
|
|
||||||
s = sym_find(t);
|
s = sym_find(t);
|
||||||
if (!s || IS_ASM_SYM(s)) {
|
if (!s || IS_ASM_SYM(s)) {
|
||||||
const char *name = get_tok_str(t, NULL);
|
const char *name = get_tok_str(t, NULL);
|
||||||
|
@ -6546,13 +6545,19 @@ static void expr_eq(void)
|
||||||
ST_FUNC void gexpr(void)
|
ST_FUNC void gexpr(void)
|
||||||
{
|
{
|
||||||
expr_eq();
|
expr_eq();
|
||||||
while (tok == ',') {
|
if (tok == ',') {
|
||||||
constant_p &= (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
|
do {
|
||||||
!((vtop->r & VT_SYM) && vtop->sym->a.addrtaken);
|
vpop();
|
||||||
vpop();
|
next();
|
||||||
next();
|
expr_eq();
|
||||||
expr_eq();
|
} while (tok == ',');
|
||||||
convert_parameter_type (&vtop->type);
|
|
||||||
|
/* convert array & function to pointer */
|
||||||
|
convert_parameter_type(&vtop->type);
|
||||||
|
|
||||||
|
/* make builtin_constant_p((1,2)) return 0 (like on gcc) */
|
||||||
|
if ((vtop->r & VT_VALMASK) == VT_CONST && nocode_wanted && !CONST_WANTED)
|
||||||
|
gv(RC_TYPE(vtop->type.t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6908,7 +6913,7 @@ static void lblock(int *bsym, int *csym)
|
||||||
loop_scope = co;
|
loop_scope = co;
|
||||||
}
|
}
|
||||||
co->bsym = bsym;
|
co->bsym = bsym;
|
||||||
block(0, 0);
|
block(0);
|
||||||
co->bsym = b;
|
co->bsym = b;
|
||||||
if (csym) {
|
if (csym) {
|
||||||
co->csym = c;
|
co->csym = c;
|
||||||
|
@ -6916,13 +6921,13 @@ static void lblock(int *bsym, int *csym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void block(int is_expr, int allow_decl)
|
static void block(int flags)
|
||||||
{
|
{
|
||||||
int a, b, c, d, e, t;
|
int a, b, c, d, e, t;
|
||||||
struct scope o;
|
struct scope o;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
|
||||||
if (is_expr) {
|
if (flags & STMT_EXPR) {
|
||||||
/* default return value is (void) */
|
/* default return value is (void) */
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
vtop->type.t = VT_VOID;
|
vtop->type.t = VT_VOID;
|
||||||
|
@ -6945,12 +6950,12 @@ again:
|
||||||
gexpr();
|
gexpr();
|
||||||
skip(')');
|
skip(')');
|
||||||
a = gvtst(1, 0);
|
a = gvtst(1, 0);
|
||||||
block(0, 0);
|
block(0);
|
||||||
if (tok == TOK_ELSE) {
|
if (tok == TOK_ELSE) {
|
||||||
d = gjmp(0);
|
d = gjmp(0);
|
||||||
gsym(a);
|
gsym(a);
|
||||||
next();
|
next();
|
||||||
block(0, 0);
|
block(0);
|
||||||
gsym(d); /* patch else jmp */
|
gsym(d); /* patch else jmp */
|
||||||
} else {
|
} else {
|
||||||
gsym(a);
|
gsym(a);
|
||||||
|
@ -6991,13 +6996,13 @@ again:
|
||||||
while (tok != '}') {
|
while (tok != '}') {
|
||||||
decl(VT_LOCAL);
|
decl(VT_LOCAL);
|
||||||
if (tok != '}') {
|
if (tok != '}') {
|
||||||
if (is_expr)
|
if (flags & STMT_EXPR)
|
||||||
vpop();
|
vpop();
|
||||||
block(is_expr, 1);
|
block(flags | STMT_COMPOUND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_scope(&o, is_expr);
|
prev_scope(&o, flags & STMT_EXPR);
|
||||||
if (debug_modes)
|
if (debug_modes)
|
||||||
tcc_debug_stabn(tcc_state, N_RBRAC, ind - func_ind);
|
tcc_debug_stabn(tcc_state, N_RBRAC, ind - func_ind);
|
||||||
if (local_scope)
|
if (local_scope)
|
||||||
|
@ -7168,7 +7173,6 @@ again:
|
||||||
cr->sym = gind();
|
cr->sym = gind();
|
||||||
dynarray_add(&cur_switch->p, &cur_switch->n, cr);
|
dynarray_add(&cur_switch->p, &cur_switch->n, cr);
|
||||||
skip(':');
|
skip(':');
|
||||||
is_expr = 0;
|
|
||||||
goto block_after_label;
|
goto block_after_label;
|
||||||
|
|
||||||
} else if (t == TOK_DEFAULT) {
|
} else if (t == TOK_DEFAULT) {
|
||||||
|
@ -7178,7 +7182,6 @@ again:
|
||||||
tcc_error("too many 'default'");
|
tcc_error("too many 'default'");
|
||||||
cur_switch->def_sym = cur_switch->nocode_wanted ? 1 : gind();
|
cur_switch->def_sym = cur_switch->nocode_wanted ? 1 : gind();
|
||||||
skip(':');
|
skip(':');
|
||||||
is_expr = 0;
|
|
||||||
goto block_after_label;
|
goto block_after_label;
|
||||||
|
|
||||||
} else if (t == TOK_GOTO) {
|
} else if (t == TOK_GOTO) {
|
||||||
|
@ -7253,20 +7256,21 @@ again:
|
||||||
if (debug_modes)
|
if (debug_modes)
|
||||||
tcc_tcov_reset_ind(tcc_state);
|
tcc_tcov_reset_ind(tcc_state);
|
||||||
vla_restore(cur_scope->vla.loc);
|
vla_restore(cur_scope->vla.loc);
|
||||||
/* c23 declaration after label */
|
|
||||||
if (allow_decl && tok != ';')
|
|
||||||
decl(VT_LOCAL);
|
|
||||||
if (tok != '}')
|
|
||||||
goto again;
|
|
||||||
/* we accept this, but it is a mistake */
|
|
||||||
tcc_warning_c(warn_all)("deprecated use of label at end of compound statement");
|
|
||||||
|
|
||||||
|
if (tok != '}') {
|
||||||
|
if (0 == (flags & STMT_COMPOUND))
|
||||||
|
goto again;
|
||||||
|
/* C23: insert implicit null-statement whithin compound statement */
|
||||||
|
} else {
|
||||||
|
/* we accept this, but it is a mistake */
|
||||||
|
tcc_warning_c(warn_all)("deprecated use of label at end of compound statement");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* expression case */
|
/* expression case */
|
||||||
if (t != ';') {
|
if (t != ';') {
|
||||||
unget_tok(t);
|
unget_tok(t);
|
||||||
expr:
|
expr:
|
||||||
if (is_expr) {
|
if (flags & STMT_EXPR) {
|
||||||
vpop();
|
vpop();
|
||||||
gexpr();
|
gexpr();
|
||||||
} else {
|
} else {
|
||||||
|
@ -8271,8 +8275,8 @@ static void func_vla_arg(Sym *sym)
|
||||||
Sym *arg;
|
Sym *arg;
|
||||||
|
|
||||||
for (arg = sym->type.ref->next; arg; arg = arg->next)
|
for (arg = sym->type.ref->next; arg; arg = arg->next)
|
||||||
if (arg->type.t & VT_VLA)
|
if ((arg->type.t & VT_BTYPE) == VT_PTR && (arg->type.ref->type.t & VT_VLA))
|
||||||
func_vla_arg_code(arg);
|
func_vla_arg_code(arg->type.ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse a function defined by symbol 'sym' and generate its code in
|
/* parse a function defined by symbol 'sym' and generate its code in
|
||||||
|
@ -8316,7 +8320,7 @@ static void gen_function(Sym *sym)
|
||||||
rsym = 0;
|
rsym = 0;
|
||||||
clear_temp_local_var_list();
|
clear_temp_local_var_list();
|
||||||
func_vla_arg(sym);
|
func_vla_arg(sym);
|
||||||
block(0, 0);
|
block(0);
|
||||||
gsym(rsym);
|
gsym(rsym);
|
||||||
|
|
||||||
nocode_wanted = 0;
|
nocode_wanted = 0;
|
||||||
|
@ -8424,11 +8428,6 @@ static int decl(int l)
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
if (tok == TOK_STATIC_ASSERT) {
|
|
||||||
do_Static_assert();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
oldint = 0;
|
oldint = 0;
|
||||||
if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) {
|
if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) {
|
||||||
if (l == VT_JMP)
|
if (l == VT_JMP)
|
||||||
|
@ -8438,6 +8437,10 @@ static int decl(int l)
|
||||||
next();
|
next();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (tok == TOK_STATIC_ASSERT) {
|
||||||
|
do_Static_assert();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (l != VT_CONST)
|
if (l != VT_CONST)
|
||||||
break;
|
break;
|
||||||
if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
|
if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
|
||||||
|
@ -8633,6 +8636,7 @@ static int decl(int l)
|
||||||
has_init = (tok == '=');
|
has_init = (tok == '=');
|
||||||
if (has_init && (type.t & VT_VLA))
|
if (has_init && (type.t & VT_VLA))
|
||||||
tcc_error("variable length array cannot be initialized");
|
tcc_error("variable length array cannot be initialized");
|
||||||
|
|
||||||
if (((type.t & VT_EXTERN) && (!has_init || l != VT_CONST))
|
if (((type.t & VT_EXTERN) && (!has_init || l != VT_CONST))
|
||||||
|| (type.t & VT_BTYPE) == VT_FUNC
|
|| (type.t & VT_BTYPE) == VT_FUNC
|
||||||
/* as with GCC, uninitialized global arrays with no size
|
/* as with GCC, uninitialized global arrays with no size
|
||||||
|
@ -8643,20 +8647,6 @@ static int decl(int l)
|
||||||
/* external variable or function */
|
/* external variable or function */
|
||||||
type.t |= VT_EXTERN;
|
type.t |= VT_EXTERN;
|
||||||
sym = external_sym(v, &type, r, &ad);
|
sym = external_sym(v, &type, r, &ad);
|
||||||
if (ad.alias_target) {
|
|
||||||
/* Aliases need to be emitted when their target
|
|
||||||
symbol is emitted, even if perhaps unreferenced.
|
|
||||||
We only support the case where the base is
|
|
||||||
already defined, otherwise we would need
|
|
||||||
deferring to emit the aliases until the end of
|
|
||||||
the compile unit. */
|
|
||||||
Sym *alias_target = sym_find(ad.alias_target);
|
|
||||||
ElfSym *esym = elfsym(alias_target);
|
|
||||||
if (!esym)
|
|
||||||
tcc_error("unsupported forward __alias__ attribute");
|
|
||||||
put_extern_sym2(sym, esym->st_shndx,
|
|
||||||
esym->st_value, esym->st_size, 1);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (l == VT_CONST || (type.t & VT_STATIC))
|
if (l == VT_CONST || (type.t & VT_STATIC))
|
||||||
r |= VT_CONST;
|
r |= VT_CONST;
|
||||||
|
@ -8667,18 +8657,22 @@ static int decl(int l)
|
||||||
else if (l == VT_CONST)
|
else if (l == VT_CONST)
|
||||||
/* uninitialized global variables may be overridden */
|
/* uninitialized global variables may be overridden */
|
||||||
type.t |= VT_EXTERN;
|
type.t |= VT_EXTERN;
|
||||||
|
|
||||||
if (ad.alias_target && 1) {
|
|
||||||
Sym *alias_target = sym_find(ad.alias_target);
|
|
||||||
ElfSym *esym = elfsym(alias_target);
|
|
||||||
if (!esym) tcc_error("unsupported forward __alias__ attribute");
|
|
||||||
sym = external_sym(v, &type, r, &ad);
|
|
||||||
put_extern_sym2(sym, esym->st_shndx,
|
|
||||||
esym->st_value, esym->st_size, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
decl_initializer_alloc(&type, &ad, r, has_init, v, l == VT_CONST);
|
decl_initializer_alloc(&type, &ad, r, has_init, v, l == VT_CONST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ad.alias_target && l == VT_CONST) {
|
||||||
|
/* Aliases need to be emitted when their target symbol
|
||||||
|
is emitted, even if perhaps unreferenced.
|
||||||
|
We only support the case where the base is already
|
||||||
|
defined, otherwise we would need deferring to emit
|
||||||
|
the aliases until the end of the compile unit. */
|
||||||
|
Sym *alias_target = sym_find(ad.alias_target);
|
||||||
|
ElfSym *esym = elfsym(alias_target);
|
||||||
|
if (!esym)
|
||||||
|
tcc_error("unsupported forward __alias__ attribute");
|
||||||
|
put_extern_sym2(sym_find(v), esym->st_shndx,
|
||||||
|
esym->st_value, esym->st_size, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (tok != ',') {
|
if (tok != ',') {
|
||||||
if (l == VT_JMP)
|
if (l == VT_JMP)
|
||||||
|
|
2
tccpe.c
2
tccpe.c
|
@ -35,7 +35,7 @@
|
||||||
# define REL_TYPE_DIRECT R_X86_64_64
|
# define REL_TYPE_DIRECT R_X86_64_64
|
||||||
# define R_XXX_THUNKFIX R_X86_64_PC32
|
# define R_XXX_THUNKFIX R_X86_64_PC32
|
||||||
# define R_XXX_RELATIVE R_X86_64_RELATIVE
|
# define R_XXX_RELATIVE R_X86_64_RELATIVE
|
||||||
# define R_XXX_FUNCCALL R_X86_64_PC32
|
# define R_XXX_FUNCCALL R_X86_64_PLT32
|
||||||
# define IMAGE_FILE_MACHINE 0x8664
|
# define IMAGE_FILE_MACHINE 0x8664
|
||||||
# define RSRC_RELTYPE 3
|
# define RSRC_RELTYPE 3
|
||||||
|
|
||||||
|
|
24
tccpp.c
24
tccpp.c
|
@ -2960,8 +2960,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
||||||
spc = 0;
|
spc = 0;
|
||||||
while (*st >= 0) {
|
while (*st >= 0) {
|
||||||
TOK_GET(&t, &st, &cval);
|
TOK_GET(&t, &st, &cval);
|
||||||
if (t != TOK_PLCHLDR
|
if (t != TOK_NOSUBST
|
||||||
&& t != TOK_NOSUBST
|
|
||||||
&& 0 == check_space(t, &spc)) {
|
&& 0 == check_space(t, &spc)) {
|
||||||
const char *s = get_tok_str(t, &cval);
|
const char *s = get_tok_str(t, &cval);
|
||||||
while (*s) {
|
while (*s) {
|
||||||
|
@ -3004,6 +3003,9 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
||||||
str.len--;
|
str.len--;
|
||||||
goto add_var;
|
goto add_var;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (*st <= 0) /* expanded to empty string */
|
||||||
|
tok_str_add(&str, TOK_PLCHLDR);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
add_var:
|
add_var:
|
||||||
|
@ -3021,11 +3023,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
||||||
}
|
}
|
||||||
st = s->next->d;
|
st = s->next->d;
|
||||||
}
|
}
|
||||||
if (*st <= 0) {
|
for (;;) {
|
||||||
/* expanded to empty string */
|
|
||||||
if (str.len)
|
|
||||||
tok_str_add(&str, TOK_PLCHLDR);
|
|
||||||
} else for (;;) {
|
|
||||||
int t2;
|
int t2;
|
||||||
TOK_GET(&t2, &st, &cval);
|
TOK_GET(&t2, &st, &cval);
|
||||||
if (t2 <= 0)
|
if (t2 <= 0)
|
||||||
|
@ -3135,7 +3133,8 @@ static inline int *macro_twosharps(const int *ptr0)
|
||||||
} else {
|
} else {
|
||||||
start_of_nosubsts = -1;
|
start_of_nosubsts = -1;
|
||||||
}
|
}
|
||||||
tok_str_add2(¯o_str1, t, &cval);
|
if (t != TOK_PLCHLDR)
|
||||||
|
tok_str_add2(¯o_str1, t, &cval);
|
||||||
}
|
}
|
||||||
tok_str_add(¯o_str1, 0);
|
tok_str_add(¯o_str1, 0);
|
||||||
//tok_print(" ###", macro_str1.str);
|
//tok_print(" ###", macro_str1.str);
|
||||||
|
@ -3154,7 +3153,7 @@ static int next_argstream(Sym **nested_list, TokenString *ws_str)
|
||||||
if (macro_ptr) {
|
if (macro_ptr) {
|
||||||
p = macro_ptr, t = *p;
|
p = macro_ptr, t = *p;
|
||||||
if (ws_str) {
|
if (ws_str) {
|
||||||
while (is_space(t) || TOK_LINEFEED == t || TOK_PLCHLDR == t)
|
while (is_space(t) || TOK_LINEFEED == t)
|
||||||
tok_str_add(ws_str, t), t = *++p;
|
tok_str_add(ws_str, t), t = *++p;
|
||||||
}
|
}
|
||||||
if (t == 0) {
|
if (t == 0) {
|
||||||
|
@ -3289,7 +3288,7 @@ static int macro_subst_tok(
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
next_nomacro(); /* eat '(' */
|
next_nomacro(); /* eat '(' */
|
||||||
} while (tok == TOK_PLCHLDR || is_space(tok));
|
} while (is_space(tok));
|
||||||
|
|
||||||
/* argument macro */
|
/* argument macro */
|
||||||
args = NULL;
|
args = NULL;
|
||||||
|
@ -3298,8 +3297,7 @@ static int macro_subst_tok(
|
||||||
for(;;) {
|
for(;;) {
|
||||||
do {
|
do {
|
||||||
next_argstream(nested_list, NULL);
|
next_argstream(nested_list, NULL);
|
||||||
} while (tok == TOK_PLCHLDR || is_space(tok) ||
|
} while (is_space(tok) || TOK_LINEFEED == tok);
|
||||||
TOK_LINEFEED == tok);
|
|
||||||
empty_arg:
|
empty_arg:
|
||||||
/* handle '()' case */
|
/* handle '()' case */
|
||||||
if (!args && !sa && tok == ')')
|
if (!args && !sa && tok == ')')
|
||||||
|
@ -3488,7 +3486,7 @@ ST_FUNC void next(void)
|
||||||
t = tok;
|
t = tok;
|
||||||
if (macro_ptr) {
|
if (macro_ptr) {
|
||||||
if (!TOK_HAS_VALUE(t)) {
|
if (!TOK_HAS_VALUE(t)) {
|
||||||
if (t == TOK_NOSUBST || t == TOK_PLCHLDR) {
|
if (t == TOK_NOSUBST) {
|
||||||
/* discard preprocessor markers */
|
/* discard preprocessor markers */
|
||||||
goto redo;
|
goto redo;
|
||||||
} else if (t == 0) {
|
} else if (t == 0) {
|
||||||
|
|
5
tccrun.c
5
tccrun.c
|
@ -263,8 +263,11 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||||
|
|
||||||
/* These aren't C symbols, so don't need leading underscore handling. */
|
/* These aren't C symbols, so don't need leading underscore handling. */
|
||||||
run_cdtors(s1, "__init_array_start", "__init_array_end", argc, argv, envp);
|
run_cdtors(s1, "__init_array_start", "__init_array_end", argc, argv, envp);
|
||||||
if (!(ret = setjmp(rc->jb)))
|
ret = setjmp(rc->jb);
|
||||||
|
if (0 == ret)
|
||||||
ret = prog_main(argc, argv, envp);
|
ret = prog_main(argc, argv, envp);
|
||||||
|
else if (256 == ret)
|
||||||
|
ret = 0;
|
||||||
run_cdtors(s1, "__fini_array_start", "__fini_array_end", 0, NULL, NULL);
|
run_cdtors(s1, "__fini_array_start", "__fini_array_end", 0, NULL, NULL);
|
||||||
run_on_exit(ret);
|
run_on_exit(ret);
|
||||||
if (s1->dflag & 16 && ret) /* tcc -dt -run ... */
|
if (s1->dflag & 16 && ret) /* tcc -dt -run ... */
|
||||||
|
|
|
@ -13,3 +13,18 @@
|
||||||
X181 M_EMPTYI_P_C1()
|
X181 M_EMPTYI_P_C1()
|
||||||
X182 M_EMPTYI_P_C1(x)
|
X182 M_EMPTYI_P_C1(x)
|
||||||
X183 usefnlike()
|
X183 usefnlike()
|
||||||
|
|
||||||
|
#define ABC(x) ABC : x
|
||||||
|
#define A(a,b,c) a ## b ## c
|
||||||
|
#define B(a,b,c) A(a,b,c)
|
||||||
|
#define C(a,b,c) a b c
|
||||||
|
B(
|
||||||
|
C(A,C(,,),),
|
||||||
|
C(B(,,),B,B(,,)),
|
||||||
|
C(B(,,),B(,,),C)
|
||||||
|
)/* */(a b c)
|
||||||
|
|
||||||
|
#define TEST(x) TEST : x
|
||||||
|
#define K(a,b) a ## b
|
||||||
|
#define L(a,b) K( TE a , b ST )
|
||||||
|
L(,)(t e s t)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
X181 1
|
X181 1
|
||||||
X182 0
|
X182 0
|
||||||
X183 yeah
|
X183 yeah
|
||||||
|
ABC : a b c
|
||||||
|
TEST : t e s t
|
||||||
|
|
117
tests/pp/23.c
117
tests/pp/23.c
|
@ -1,117 +0,0 @@
|
||||||
#define M_DEFERRED_COMMA ,
|
|
||||||
|
|
||||||
#define M_EAT(...)
|
|
||||||
#define M_APPLY(a, ...) a (__VA_ARGS__)
|
|
||||||
#define M_ID(...) __VA_ARGS__
|
|
||||||
|
|
||||||
#define M_C2I(a, ...) a ## __VA_ARGS__
|
|
||||||
#define M_C(a, ...) M_C2I(a, __VA_ARGS__)
|
|
||||||
#define M_C3I(a, b, ...) a ## b ## __VA_ARGS__
|
|
||||||
#define M_C3(a, b, ...) M_C3I(a ,b, __VA_ARGS__)
|
|
||||||
#define M_C4I(a, b, c, ...) a ## b ## c ## __VA_ARGS__
|
|
||||||
#define M_C4(a, b, c, ...) M_C4I(a ,b, c, __VA_ARGS__)
|
|
||||||
|
|
||||||
#define M_INVI_0 1
|
|
||||||
#define M_INVI_1 0
|
|
||||||
#define M_INV(x) M_C(M_INVI_, x)
|
|
||||||
|
|
||||||
#define M_ANDI_00 0
|
|
||||||
#define M_ANDI_01 0
|
|
||||||
#define M_ANDI_10 0
|
|
||||||
#define M_ANDI_11 1
|
|
||||||
#define M_AND(x,y) M_C3(M_ANDI_, x, y)
|
|
||||||
|
|
||||||
#define M_ANDI_000 0
|
|
||||||
#define M_ANDI_001 0
|
|
||||||
#define M_ANDI_010 0
|
|
||||||
#define M_ANDI_011 0
|
|
||||||
#define M_ANDI_100 0
|
|
||||||
#define M_ANDI_101 0
|
|
||||||
#define M_ANDI_110 0
|
|
||||||
#define M_ANDI_111 1
|
|
||||||
#define M_AND3(x,y,z) M_C4(M_ANDI_, x, y, z)
|
|
||||||
|
|
||||||
#define M_ORI_00 0
|
|
||||||
#define M_ORI_01 1
|
|
||||||
#define M_ORI_10 1
|
|
||||||
#define M_ORI_11 1
|
|
||||||
#define M_OR(x,y) M_C3(M_ORI_, x, y)
|
|
||||||
|
|
||||||
#define M_ORI_000 0
|
|
||||||
#define M_ORI_001 1
|
|
||||||
#define M_ORI_010 1
|
|
||||||
#define M_ORI_011 1
|
|
||||||
#define M_ORI_100 1
|
|
||||||
#define M_ORI_101 1
|
|
||||||
#define M_ORI_110 1
|
|
||||||
#define M_ORI_111 1
|
|
||||||
#define M_OR3(x,y,z) M_C4(M_ORI_, x, y, z)
|
|
||||||
|
|
||||||
#define M_RETI_ARG2(_1, _2, ...) _2
|
|
||||||
#define M_RET_ARG2(...) M_RETI_ARG2(__VA_ARGS__,)
|
|
||||||
|
|
||||||
#define M_RETI_ARG4(_1, _2, _3, _4, ...) _4
|
|
||||||
#define M_RET_ARG4(...) M_RETI_ARG4(__VA_ARGS__,)
|
|
||||||
|
|
||||||
#define M_TOBOOLI_0 1, 0,
|
|
||||||
#define M_BOOL(x) M_RET_ARG2(M_C(M_TOBOOLI_, x), 1, useless)
|
|
||||||
|
|
||||||
#define M_IFI_0(true_c, ...) __VA_ARGS__
|
|
||||||
#define M_IFI_1(true_c, ...) true_c
|
|
||||||
#define M_IF(c) M_C(M_IFI_, M_BOOL(c))
|
|
||||||
|
|
||||||
#define M_NARGS(...) M_RET_ARG4(__VA_ARGS__, 3, 2, 1, useless)
|
|
||||||
|
|
||||||
#define M_MAP(...) M_MAP_0(__VA_ARGS__)
|
|
||||||
#define M_MAP_0(f, ...) M_C(M_MAP_, M_NARGS(__VA_ARGS__))(f, __VA_ARGS__)
|
|
||||||
#define M_MAP_1(f, _1) f(_1)
|
|
||||||
#define M_MAP_2(f, _1, _2) f(_1) f(_2)
|
|
||||||
#define M_MAP_3(f, _1, _2, _3) f(_1) f(_2) f(_3)
|
|
||||||
|
|
||||||
#define M_MAP2(...) M_MAP2I_0(__VA_ARGS__)
|
|
||||||
#define M_MAP2I_0(f, d, ...) M_C(M_MAP2I_, M_NARGS(__VA_ARGS__))(f, d, __VA_ARGS__)
|
|
||||||
#define M_MAP2I_1(f, d, _1) f(d, _1)
|
|
||||||
#define M_MAP2I_2(f, d, _1, _2) f(d, _1) f(d, _2)
|
|
||||||
#define M_MAP2I_3(f, d, _1, _2, _3) f(d, _1) f(d, _2) f(d, _3)
|
|
||||||
|
|
||||||
#define M_CROSS_MAP(f, alist, blist) M_CROSSI_MAP1(f, alist, blist)
|
|
||||||
#define M_CROSSI_MAP1(f, alist, blist) M_C(M_CROSSI_MAP1_, M_NARGS alist)(f, blist, M_ID alist)
|
|
||||||
#define M_CROSSI_MAP1_1(...) M_CROSSI_MAP1_1b(__VA_ARGS__)
|
|
||||||
#define M_CROSSI_MAP1_1b(f, blist, a1) M_MAP2(f, a1, M_ID blist)
|
|
||||||
#define M_CROSSI_MAP1_2(...) M_CROSSI_MAP1_2b(__VA_ARGS__)
|
|
||||||
#define M_CROSSI_MAP1_2b(f, blist, a1, a2) M_MAP2(f, a1, M_ID blist) M_MAP2(f, a2, M_ID blist)
|
|
||||||
#define M_CROSSI_MAP1_3(...) M_CROSSI_MAP1_3b(__VA_ARGS__)
|
|
||||||
#define M_CROSSI_MAP1_3b(f, blist, a1, a2, a3) M_MAP2(f, a1, M_ID blist) M_MAP2(f, a2, M_ID blist) M_MAP2(f, a3, M_ID blist)
|
|
||||||
|
|
||||||
#define M_COMMA_P(...) M_RETI_ARG4(__VA_ARGS__, 1, 1, 0, useless)
|
|
||||||
|
|
||||||
#define M_PARENTHESISI_DETECT1(...) ,
|
|
||||||
#define M_PARENTHESIS_P(...) \
|
|
||||||
M_AND3(M_COMMA_P(M_PARENTHESISI_DETECT1 __VA_ARGS__), \
|
|
||||||
M_INV(M_COMMA_P(__VA_ARGS__)), \
|
|
||||||
M_EMPTY_P(M_EAT __VA_ARGS__))
|
|
||||||
|
|
||||||
#define M_EMPTYI_DETECT(...) ,
|
|
||||||
#define M_EMPTYI_P_C1(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__ () )
|
|
||||||
#define M_EMPTYI_P_C2(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__)
|
|
||||||
#define M_EMPTYI_P_C3(...) M_COMMA_P(__VA_ARGS__ () )
|
|
||||||
#define M_EMPTY_P(...) M_AND(M_EMPTYI_P_C1(__VA_ARGS__), M_INV(M_OR3(M_EMPTYI_P_C2(__VA_ARGS__), M_COMMA_P(__VA_ARGS__),M_EMPTYI_P_C3(__VA_ARGS__))))
|
|
||||||
|
|
||||||
#define M_G3N_IS_PRESENT(num) \
|
|
||||||
M_IF(M_PARENTHESIS_P(M_C(M_GENERIC_ORG_, num)() ))(M_DEFERRED_COMMA M_ID M_C(M_GENERIC_ORG_, num)(), )
|
|
||||||
|
|
||||||
#define M_G3N_IS_PRESENT2(el1, num) \
|
|
||||||
M_IF(M_PARENTHESIS_P(M_C4(M_GENERIC_ORG_, el1, _COMP_, num)()))(M_DEFERRED_COMMA M_APPLY(M_C3, el1, _COMP_, M_ID M_C4(M_GENERIC_ORG_, el1, _COMP_, num)()), )
|
|
||||||
|
|
||||||
#define FLT1 (GENTYPE(float), TYPE(float) )
|
|
||||||
|
|
||||||
#define M_GENERIC_ORG_2() (USER)
|
|
||||||
#define M_GENERIC_ORG_USER_COMP_1() (CORE)
|
|
||||||
#define M_GENERIC_ORG_USER_COMP_CORE_OPLIST_6() FLT1
|
|
||||||
|
|
||||||
// Shall expand to ", USER"
|
|
||||||
M_MAP(M_G3N_IS_PRESENT, 1, 2, 3)
|
|
||||||
// Shall expand to ", USER_COMP_CORE"
|
|
||||||
M_CROSS_MAP(M_G3N_IS_PRESENT2, (MLIB , USER), ( 1, 2, 3 ) )
|
|
||||||
// Shall expand to ", USER_COMP_CORE" (composition of both) [fail]
|
|
||||||
M_CROSS_MAP(M_G3N_IS_PRESENT2, (MLIB M_MAP(M_G3N_IS_PRESENT, 1, 2, 3)), ( 1, 2, 3 ) )
|
|
|
@ -1,3 +0,0 @@
|
||||||
, USER
|
|
||||||
, USER_COMP_CORE
|
|
||||||
, USER_COMP_CORE
|
|
|
@ -140,11 +140,6 @@ static int onetwothree = 123;
|
||||||
#define B3 4
|
#define B3 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __TINYC__
|
|
||||||
/* We try to handle this syntax. Make at least sure it doesn't segfault. */
|
|
||||||
char invalid_function_def()[] {return 0;}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define __INT64_C(c) c ## LL
|
#define __INT64_C(c) c ## LL
|
||||||
#define INT64_MIN (-__INT64_C(9223372036854775807)-1)
|
#define INT64_MIN (-__INT64_C(9223372036854775807)-1)
|
||||||
|
|
||||||
|
@ -341,18 +336,13 @@ static struct recursive_macro { int rm_field; } G;
|
||||||
WRAP((printf("rm_field = %d %d\n", rm_field, WRAP(rm_field))));
|
WRAP((printf("rm_field = %d %d\n", rm_field, WRAP(rm_field))));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(__TINYC__) && (__GNUC__ >= 14 || __clang_major__ >= 15)
|
#if __TINYC__
|
||||||
#define IMPLICIT_INT int
|
int op(a, b)
|
||||||
#else
|
|
||||||
#define IMPLICIT_INT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int op(IMPLICIT_INT a, IMPLICIT_INT b)
|
|
||||||
{
|
{
|
||||||
return a / b;
|
return a / b;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret(IMPLICIT_INT a)
|
int ret(a)
|
||||||
{
|
{
|
||||||
if (a == 2)
|
if (a == 2)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -360,6 +350,7 @@ int ret(IMPLICIT_INT a)
|
||||||
return 2;
|
return 2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(__TINYC__) && (__GNUC__ >= 8)
|
#if !defined(__TINYC__) && (__GNUC__ >= 8)
|
||||||
/* Old GCCs don't regard "foo"[1] as constant, even in GNU dialect. */
|
/* Old GCCs don't regard "foo"[1] as constant, even in GNU dialect. */
|
||||||
|
@ -716,7 +707,7 @@ int tab2[3][2];
|
||||||
|
|
||||||
int g;
|
int g;
|
||||||
|
|
||||||
void f1(IMPLICIT_INT g)
|
void f1(int g)
|
||||||
{
|
{
|
||||||
printf("g1=%d\n", g);
|
printf("g1=%d\n", g);
|
||||||
}
|
}
|
||||||
|
@ -1511,25 +1502,35 @@ void compound_literal_test(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if __TINYC__
|
||||||
|
|
||||||
/* K & R protos */
|
/* K & R protos */
|
||||||
|
|
||||||
IMPLICIT_INT kr_func1(IMPLICIT_INT a, IMPLICIT_INT b)
|
kr_func1(a, b)
|
||||||
{
|
{
|
||||||
return a + b;
|
return a + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kr_func2(IMPLICIT_INT a, IMPLICIT_INT b)
|
int kr_func2(a, b)
|
||||||
{
|
{
|
||||||
return a + b;
|
return a + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPLICIT_INT kr_test()
|
kr_test()
|
||||||
{
|
{
|
||||||
printf("func1=%d\n", kr_func1(3, 4));
|
printf("func1=%d\n", kr_func1(3, 4));
|
||||||
printf("func2=%d\n", kr_func2(3, 4));
|
printf("func2=%d\n", kr_func2(3, 4));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We try to handle this syntax. Make at least sure it doesn't segfault. */
|
||||||
|
char invalid_function_def()[] {return 0;}
|
||||||
|
|
||||||
|
#else
|
||||||
|
# define kr_test() printf("func1=7\nfunc2=7\n")
|
||||||
|
#endif
|
||||||
|
|
||||||
void num(int n)
|
void num(int n)
|
||||||
{
|
{
|
||||||
char *tab, *p;
|
char *tab, *p;
|
||||||
|
@ -2058,7 +2059,7 @@ void c99_bool_test(void)
|
||||||
printf("b = %d\n", b);
|
printf("b = %d\n", b);
|
||||||
b2 = 0;
|
b2 = 0;
|
||||||
printf("sizeof(x ? _Bool : _Bool) = %d (should be sizeof int)\n",
|
printf("sizeof(x ? _Bool : _Bool) = %d (should be sizeof int)\n",
|
||||||
sizeof((volatile IMPLICIT_INT)a ? b : b2));
|
sizeof ((volatile int)a ? b : b2));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3062,7 +3063,7 @@ void c99_vla_test_3d(int s, int arr[2][3][s])
|
||||||
|
|
||||||
void c99_vla_test_3e(int s, int arr[][3][--s])
|
void c99_vla_test_3e(int s, int arr[][3][--s])
|
||||||
{
|
{
|
||||||
printf ("%d %d\n", s, arr[1][2][3]);
|
printf ("%d %d %d\n", sizeof arr, s, arr[1][2][3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void c99_vla_test_3(void)
|
void c99_vla_test_3(void)
|
||||||
|
@ -3145,6 +3146,10 @@ void sizeof_test(void)
|
||||||
printf("sizeof(1 && 1) = %d\n", sizeof(1 && 1));
|
printf("sizeof(1 && 1) = %d\n", sizeof(1 && 1));
|
||||||
printf("sizeof(t || 1) = %d\n", sizeof(t || 1));
|
printf("sizeof(t || 1) = %d\n", sizeof(t || 1));
|
||||||
printf("sizeof(0 || 0) = %d\n", sizeof(0 || 0));
|
printf("sizeof(0 || 0) = %d\n", sizeof(0 || 0));
|
||||||
|
|
||||||
|
int arr[4], fn();
|
||||||
|
printf("sizeof(0, arr) = %d\n", sizeof(0, arr));
|
||||||
|
printf("sizeof(0, fn) = %d\n", sizeof(0, fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
void typeof_test(void)
|
void typeof_test(void)
|
||||||
|
@ -3915,30 +3920,29 @@ void builtin_test(void)
|
||||||
COMPAT_TYPE(char *, unsigned char *);
|
COMPAT_TYPE(char *, unsigned char *);
|
||||||
COMPAT_TYPE(char *, signed char *);
|
COMPAT_TYPE(char *, signed char *);
|
||||||
COMPAT_TYPE(char *, char *);
|
COMPAT_TYPE(char *, char *);
|
||||||
/* space is needed because tcc preprocessor introduces a space between each token */
|
COMPAT_TYPE(char **, void *);
|
||||||
COMPAT_TYPE(char * *, void *);
|
|
||||||
#endif
|
#endif
|
||||||
printf("res1 = %d\n", __builtin_constant_p(1));
|
printf("res1 = %d\n", __builtin_constant_p(1));
|
||||||
printf("res2 = %d\n", __builtin_constant_p(1 + 2));
|
printf("res2 = %d\n", __builtin_constant_p(1 + 2));
|
||||||
printf("res3 = %d\n", __builtin_constant_p(&constant_p_var));
|
printf("res3 = %d\n", __builtin_constant_p(&constant_p_var));
|
||||||
printf("res4 = %d\n", __builtin_constant_p(constant_p_var));
|
printf("res4 = %d\n", __builtin_constant_p(constant_p_var));
|
||||||
printf("res5 = %d\n", __builtin_constant_p(100000 / constant_p_var));
|
printf("res5 = %d\n", __builtin_constant_p(100000 / constant_p_var));
|
||||||
#ifdef __clang__
|
printf("res6 = %d\n", __builtin_constant_p(i && 1));
|
||||||
/* clang doesn't regard this as constant expression */
|
printf("res7 = %d\n", __builtin_constant_p("hi"));
|
||||||
printf("res6 = 1\n");
|
printf("res8 = %d\n", __builtin_constant_p(func()));
|
||||||
|
#ifndef __clang__
|
||||||
|
printf("res10 = %d\n", __builtin_constant_p(i && 0));
|
||||||
|
printf("res11 = %d\n", __builtin_constant_p(i * 0));
|
||||||
|
printf("res12 = %d\n", __builtin_constant_p(i && 0 ? i : 34));
|
||||||
|
printf("res13 = %d\n", __builtin_constant_p((1,7)));
|
||||||
#else
|
#else
|
||||||
printf("res6 = %d\n", __builtin_constant_p(i && 0));
|
/* clang doesn't regard these as constant expression */
|
||||||
|
printf("res10 = 1\n");
|
||||||
|
printf("res11 = 1\n");
|
||||||
|
printf("res12 = 1\n");
|
||||||
|
printf("res13 = 0\n");
|
||||||
#endif
|
#endif
|
||||||
printf("res7 = %d\n", __builtin_constant_p(i && 1));
|
|
||||||
#ifdef __clang__
|
|
||||||
/* clang doesn't regard this as constant expression */
|
|
||||||
printf("res8 = 1\n");
|
|
||||||
#else
|
|
||||||
printf("res8 = %d\n", __builtin_constant_p(i && 0 ? i : 34));
|
|
||||||
#endif
|
|
||||||
printf("res9 = %d\n", __builtin_constant_p("hi"));
|
|
||||||
printf("res10 = %d\n", __builtin_constant_p(func()));
|
|
||||||
printf("res11 = %d\n", __builtin_constant_p((i++, 7)));
|
|
||||||
s = 1;
|
s = 1;
|
||||||
ll = 2;
|
ll = 2;
|
||||||
i = __builtin_choose_expr (1 != 0, ll, s);
|
i = __builtin_choose_expr (1 != 0, ll, s);
|
||||||
|
|
|
@ -14,8 +14,7 @@ int main()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
int a = 2;
|
printf("%d\n", 2);
|
||||||
printf("%d\n", a);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -2,14 +2,17 @@ extern int printf (const char *, ...);
|
||||||
extern void target(void);
|
extern void target(void);
|
||||||
extern void alias_for_target(void);
|
extern void alias_for_target(void);
|
||||||
extern void asm_for_target(void);
|
extern void asm_for_target(void);
|
||||||
|
extern int g_int, alias_int;
|
||||||
|
|
||||||
void inunit2(void);
|
void inunit2(void);
|
||||||
|
|
||||||
void inunit2(void)
|
void inunit2(void)
|
||||||
{
|
{
|
||||||
|
printf("in unit2:\n");
|
||||||
target();
|
target();
|
||||||
alias_for_target();
|
alias_for_target();
|
||||||
/* This symbol is not supposed to be available in this unit:
|
/* This symbol is not supposed to be available in this unit:
|
||||||
asm_for_target();
|
asm_for_target();
|
||||||
*/
|
*/
|
||||||
|
printf("g_int = %d\nalias_int = %d\n", g_int, alias_int);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,24 @@
|
||||||
/* Check semantics of various constructs to generate renamed symbols. */
|
/* Check semantics of various constructs to generate renamed symbols. */
|
||||||
|
|
||||||
extern int printf (const char *, ...);
|
extern int printf (const char *, ...);
|
||||||
void target(void);
|
void target(void);
|
||||||
void target(void) {
|
void target(void) {
|
||||||
printf("in target function\n");
|
printf("in target function\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void alias_for_target(void) __attribute__((alias("target")));
|
void alias_for_target(void) __attribute__((alias("target")));
|
||||||
|
|
||||||
|
int g_int = 34;
|
||||||
|
int alias_int __attribute__((alias("g_int")));
|
||||||
|
|
||||||
#ifdef __leading_underscore
|
#ifdef __leading_underscore
|
||||||
void asm_for_target(void) __asm__("_target");
|
# define _ "_"
|
||||||
#else
|
#else
|
||||||
void asm_for_target(void) __asm__("target");
|
# define _
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void asm_for_target(void) __asm__(_"target");
|
||||||
|
int asm_int __asm__(_"g_int");
|
||||||
|
|
||||||
/* This is not supposed to compile, alias targets must be defined in the
|
/* This is not supposed to compile, alias targets must be defined in the
|
||||||
same unit. In TCC they even must be defined before the reference
|
same unit. In TCC they even must be defined before the reference
|
||||||
void alias_for_undef(void) __attribute__((alias("undefined")));
|
void alias_for_undef(void) __attribute__((alias("undefined")));
|
||||||
|
@ -24,6 +31,7 @@ int main(void)
|
||||||
target();
|
target();
|
||||||
alias_for_target();
|
alias_for_target();
|
||||||
asm_for_target();
|
asm_for_target();
|
||||||
|
printf("g_int = %d\nalias_int = %d\nasm_int = %d\n", g_int, alias_int, asm_int);
|
||||||
inunit2();
|
inunit2();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
in target function
|
in target function
|
||||||
in target function
|
in target function
|
||||||
in target function
|
in target function
|
||||||
|
g_int = 34
|
||||||
|
alias_int = 34
|
||||||
|
asm_int = 34
|
||||||
|
in unit2:
|
||||||
in target function
|
in target function
|
||||||
in target function
|
in target function
|
||||||
|
g_int = 34
|
||||||
|
alias_int = 34
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
60_errors_and_warnings.c:148: error: identifier expected
|
60_errors_and_warnings.c:148: error: identifier expected
|
||||||
|
|
||||||
[test_invalid_1]
|
[test_invalid_1]
|
||||||
60_errors_and_warnings.c:153: error: identifier expected
|
60_errors_and_warnings.c:153: error: expression expected before ','
|
||||||
|
|
||||||
[test_invalid_2]
|
[test_invalid_2]
|
||||||
60_errors_and_warnings.c:156: error: ';' expected (got "{")
|
60_errors_and_warnings.c:156: error: ';' expected (got "{")
|
||||||
|
|
10
x86_64-gen.c
10
x86_64-gen.c
|
@ -646,11 +646,7 @@ static void gcall_or_jmp(int is_jmp)
|
||||||
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
|
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
|
||||||
((vtop->r & VT_SYM) && (vtop->c.i-4) == (int)(vtop->c.i-4))) {
|
((vtop->r & VT_SYM) && (vtop->c.i-4) == (int)(vtop->c.i-4))) {
|
||||||
/* constant symbolic case -> simple relocation */
|
/* constant symbolic case -> simple relocation */
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32, (int)(vtop->c.i-4));
|
|
||||||
#else
|
|
||||||
greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4));
|
greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4));
|
||||||
#endif
|
|
||||||
oad(0xe8 + is_jmp, 0); /* call/jmp im */
|
oad(0xe8 + is_jmp, 0); /* call/jmp im */
|
||||||
} else {
|
} else {
|
||||||
/* otherwise, indirect call */
|
/* otherwise, indirect call */
|
||||||
|
@ -668,11 +664,7 @@ static void gen_bounds_call(int v)
|
||||||
{
|
{
|
||||||
Sym *sym = external_helper_sym(v);
|
Sym *sym = external_helper_sym(v);
|
||||||
oad(0xe8, 0);
|
oad(0xe8, 0);
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4);
|
|
||||||
#else
|
|
||||||
greloca(cur_text_section, sym, ind-4, R_X86_64_PLT32, -4);
|
greloca(cur_text_section, sym, ind-4, R_X86_64_PLT32, -4);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
|
@ -1046,7 +1038,7 @@ void gfunc_epilog(void)
|
||||||
Sym *sym = external_helper_sym(TOK___chkstk);
|
Sym *sym = external_helper_sym(TOK___chkstk);
|
||||||
oad(0xb8, v); /* mov stacksize, %eax */
|
oad(0xb8, v); /* mov stacksize, %eax */
|
||||||
oad(0xe8, 0); /* call __chkstk, (does the stackframe too) */
|
oad(0xe8, 0); /* call __chkstk, (does the stackframe too) */
|
||||||
greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4);
|
greloca(cur_text_section, sym, ind-4, R_X86_64_PLT32, -4);
|
||||||
o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */
|
o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */
|
||||||
} else {
|
} else {
|
||||||
o(0xe5894855); /* push %rbp, mov %rsp, %rbp */
|
o(0xe5894855); /* push %rbp, mov %rsp, %rbp */
|
||||||
|
|
Loading…
Reference in New Issue