mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-24 03:40:09 +08:00
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
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: build and run tests
|
||||
name: build and test
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -17,7 +17,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: make & test tcc
|
||||
run: ./configure && make && make test -k
|
||||
run: ./configure --config-codesign=no && make && make test -k
|
||||
|
||||
test-x86_64-win32:
|
||||
runs-on: windows-2019
|
||||
|
10
Makefile
10
Makefile
@ -55,6 +55,8 @@ else
|
||||
# `make test' when libtcc.dylib is used (configure --disable-static), so
|
||||
# we bake a relative path into the binary. $libdir is used after install.
|
||||
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 += -compatibility_version $(MACOS_DYLIB_VERSION)
|
||||
endif
|
||||
@ -193,7 +195,6 @@ endif
|
||||
# include custom configuration (see make help)
|
||||
-include config-extra.mak
|
||||
|
||||
ifneq ($(X),)
|
||||
ifneq ($(T),$(NATIVE_TARGET))
|
||||
# assume support files for cross-targets in "/usr/<triplet>" by default
|
||||
TRIPLET-i386 ?= i686-linux-gnu
|
||||
@ -201,11 +202,12 @@ TRIPLET-x86_64 ?= x86_64-linux-gnu
|
||||
TRIPLET-arm ?= arm-linux-gnueabi
|
||||
TRIPLET-arm64 ?= aarch64-linux-gnu
|
||||
TRIPLET-riscv64 ?= riscv64-linux-gnu
|
||||
MARCH-i386 ?= i386-linux-gnu
|
||||
MARCH-$T ?= $(TRIPLET-$T)
|
||||
TR = $(if $(TRIPLET-$T),$T,ignored)
|
||||
CRT-$(TR) ?= /usr/$(TRIPLET-$T)/lib
|
||||
LIB-$(TR) ?= {B}:/usr/$(TRIPLET-$T)/lib
|
||||
INC-$(TR) ?= {B}/include:/usr/$(TRIPLET-$T)/include
|
||||
endif
|
||||
LIB-$(TR) ?= {B}:/usr/$(TRIPLET-$T)/lib:/usr/lib/$(MARCH-$T)
|
||||
INC-$(TR) ?= {B}/include:/usr/$(TRIPLET-$T)/include:/usr/include
|
||||
endif
|
||||
|
||||
CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccdbg.c tccelf.c tccasm.c tccrun.c
|
||||
|
6
configure
vendored
6
configure
vendored
@ -603,12 +603,6 @@ echo "VERSION = $version" >> config.mak
|
||||
echo "#define TCC_VERSION \"$version\"" >> $TMPH
|
||||
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
|
||||
case $source_path in
|
||||
/*) echo "TOPSRC=$source_path";;
|
||||
|
@ -515,7 +515,13 @@ static void gen_disp32(ExprValue *pe)
|
||||
sym->type.t = VT_FUNC;
|
||||
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);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,20 +124,16 @@
|
||||
/* avoids usage of GCC/clang specific builtins in libc-headerfiles: */
|
||||
#define __FINITE_MATH_ONLY__ 1
|
||||
#define _FORTIFY_SOURCE 0
|
||||
#define __has_builtin(x) 0
|
||||
//#define __has_builtin(x) 0
|
||||
|
||||
#elif defined __ANDROID__
|
||||
#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
|
||||
/* Linux */
|
||||
|
||||
#endif
|
||||
|
||||
/* Some derived integer types needed to get stdint.h to compile correctly on some platforms */
|
||||
#ifndef __NetBSD__
|
||||
#define __UINTPTR_TYPE__ unsigned __PTRDIFF_TYPE__
|
||||
@ -152,6 +148,16 @@
|
||||
#define __REDIRECT_NTHNL(name, proto, alias) name proto __asm__ (#alias) __THROWNL
|
||||
#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 */
|
||||
#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));
|
||||
} else if (s1->current_filename) {
|
||||
cstr_printf(&cs, "%s: ", s1->current_filename);
|
||||
}
|
||||
if (0 == cs.size)
|
||||
} else {
|
||||
cstr_printf(&cs, "tcc: ");
|
||||
}
|
||||
cstr_printf(&cs, mode == ERROR_WARN ? "warning: " : "error: ");
|
||||
cstr_vprintf(&cs, fmt, ap);
|
||||
if (!s1 || !s1->error_func) {
|
||||
@ -930,17 +930,8 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* add sections */
|
||||
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) {
|
||||
/* 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);
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
# ifdef _WIN32
|
||||
# ifdef TCC_IS_NATIVE
|
||||
/* allow linking with system dll's directly */
|
||||
tcc_add_systemdir(s);
|
||||
# endif
|
||||
/* target PE has its own startup code in libtcc1.a */
|
||||
return 0;
|
||||
|
||||
#elif defined TCC_TARGET_MACHO
|
||||
# ifdef TCC_IS_NATIVE
|
||||
tcc_add_macos_sdkpath(s);
|
||||
# endif
|
||||
/* Mach-O with LC_MAIN doesn't need any crt startup code. */
|
||||
return 0;
|
||||
|
||||
#else
|
||||
/* paths for crt objects */
|
||||
tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
|
||||
|
||||
/* add libc crt1/crti objects */
|
||||
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");
|
||||
if (output_type != TCC_OUTPUT_MEMORY && !s->nostdlib)
|
||||
tccelf_add_crtbegin(s);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
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 (flags & AFF_PRINT_ERROR)
|
||||
tcc_error_noabort("file '%s' not found", filename);
|
||||
return ret;
|
||||
return FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
s1->current_filename = filename;
|
||||
@ -1226,18 +1172,21 @@ LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
|
||||
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)
|
||||
{
|
||||
char buf[1024];
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
for(i = 0; i < nb_paths; i++) {
|
||||
snprintf(buf, sizeof(buf), fmt, paths[i], filename);
|
||||
if (tcc_add_file_internal(s, buf, flags | AFF_TYPE_BIN) == 0)
|
||||
return 0;
|
||||
ret = tcc_add_file_internal(s1, buf, (flags & ~AFF_PRINT_ERROR) | AFF_TYPE_BIN);
|
||||
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 */
|
||||
@ -1253,17 +1202,14 @@ ST_FUNC void tcc_add_support(TCCState *s1, const char *filename)
|
||||
char buf[100];
|
||||
if (CONFIG_TCC_CROSSPREFIX[0])
|
||||
filename = strcat(strcpy(buf, CONFIG_TCC_CROSSPREFIX), filename);
|
||||
if (tcc_add_dll(s1, filename, 0) < 0)
|
||||
tcc_error_noabort("%s not found", filename);
|
||||
tcc_add_dll(s1, filename, AFF_PRINT_ERROR);
|
||||
}
|
||||
|
||||
#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO
|
||||
ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
|
||||
{
|
||||
if (-1 == tcc_add_library_internal(s1, "%s/%s",
|
||||
filename, 0, s1->crt_paths, s1->nb_crt_paths))
|
||||
return tcc_error_noabort("file '%s' not found", filename);
|
||||
return 0;
|
||||
return tcc_add_library_internal(s1, "%s/%s",
|
||||
filename, AFF_PRINT_ERROR, s1->crt_paths, s1->nb_crt_paths);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1285,18 +1231,19 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
|
||||
#endif
|
||||
int flags = s->filetype & AFF_WHOLE_ARCHIVE;
|
||||
while (*pp) {
|
||||
if (0 == tcc_add_library_internal(s, *pp,
|
||||
libraryname, flags, s->library_paths, s->nb_library_paths))
|
||||
return 0;
|
||||
int ret = tcc_add_library_internal(s, *pp,
|
||||
libraryname, flags, s->library_paths, s->nb_library_paths);
|
||||
if (ret != FILE_NOT_FOUND)
|
||||
return ret;
|
||||
++pp;
|
||||
}
|
||||
return -1;
|
||||
return FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
PUB_FUNC int tcc_add_library_err(TCCState *s1, const char *libname)
|
||||
{
|
||||
int ret = tcc_add_library(s1, libname);
|
||||
if (ret < 0)
|
||||
if (ret == FILE_NOT_FOUND)
|
||||
tcc_error_noabort("library '%s' not found", libname);
|
||||
return ret;
|
||||
}
|
||||
@ -1790,6 +1737,37 @@ static int set_flag(TCCState *s, const FlagDef *flags, const char *name)
|
||||
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)
|
||||
{
|
||||
int ret = 0, q, c;
|
||||
@ -2140,43 +2118,11 @@ dorun:
|
||||
s->gen_phony_deps = 1;
|
||||
break;
|
||||
case TCC_OPTION_dumpmachine:
|
||||
/* this is a best guess, please refine as necessary */
|
||||
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"
|
||||
);
|
||||
printf("%s\n", dumpmachine_str);
|
||||
exit(0);
|
||||
break;
|
||||
case TCC_OPTION_dumpversion:
|
||||
printf ("%s\n", TCC_VERSION);
|
||||
exit(0);
|
||||
break;
|
||||
case TCC_OPTION_x:
|
||||
x = 0;
|
||||
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_NOSUBST 0xa5 /* means following token has already been pp'd */
|
||||
#define TOK_PPJOIN 0xa6 /* A '##' in the right position to mean pasting */
|
||||
#define TOK_SOTYPE 0xa7 /* alias of '(' for parsing sizeof (type) */
|
||||
|
||||
/* assignment operators */
|
||||
#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_C67 4
|
||||
|
||||
/* return value of tcc_add_file_internal(): 0, -1, or FILE_NOT_FOUND */
|
||||
#define FILE_NOT_FOUND -2
|
||||
|
||||
#ifndef ELF_OBJ_ONLY
|
||||
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
|
||||
#endif
|
||||
@ -1532,9 +1536,6 @@ ST_FUNC void tccelf_new(TCCState *s);
|
||||
ST_FUNC void tccelf_delete(TCCState *s);
|
||||
ST_FUNC void tccelf_begin_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 void section_realloc(Section *sec, unsigned long new_size);
|
||||
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
|
||||
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 void tccelf_add_crtbegin(TCCState *s1);
|
||||
ST_FUNC void tccelf_add_crtend(TCCState *s1);
|
||||
#endif
|
||||
#ifndef TCC_TARGET_PE
|
||||
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")) {
|
||||
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
|
||||
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);
|
||||
|
134
tccelf.c
134
tccelf.c
@ -83,17 +83,21 @@ ST_FUNC void tccelf_new(TCCState *s)
|
||||
".dynstrtab",
|
||||
".dynhashtab", SHF_PRIVATE);
|
||||
get_sym_attr(s, 0, 1);
|
||||
}
|
||||
|
||||
if (s->do_debug) {
|
||||
/* add debug sections */
|
||||
tcc_debug_new(s);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
ST_FUNC void tccelf_bounds_new(TCCState *s)
|
||||
{
|
||||
TCCState *s1 = s;
|
||||
/* create bounds sections (make ro after relocation done with GNU_RELRO) */
|
||||
bounds_section = new_section(s, ".bounds", SHT_PROGBITS, shf_RELRO);
|
||||
lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, shf_RELRO);
|
||||
}
|
||||
if (s->do_bounds_check) {
|
||||
/* if bound checking, then add corresponding sections */
|
||||
/* (make ro after relocation done with GNU_RELRO) */
|
||||
bounds_section = new_section(s, ".bounds", SHT_PROGBITS, shf_RELRO);
|
||||
lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, shf_RELRO);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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) {
|
||||
ElfSym *sym = (ElfSym*)s->data + first_sym + i;
|
||||
if (sym->st_shndx == SHN_UNDEF
|
||||
&& ELFW(ST_BIND)(sym->st_info) == STB_LOCAL)
|
||||
sym->st_info = ELFW(ST_INFO)(STB_GLOBAL, ELFW(ST_TYPE)(sym->st_info));
|
||||
|
||||
if (sym->st_shndx == SHN_UNDEF) {
|
||||
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
|
||||
/* An ELF relocatable file should have the types of its undefined global symbol set
|
||||
to STT_NOTYPE or it will confuse binutils bfd */
|
||||
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF && s1->output_type == TCC_OUTPUT_OBJ)
|
||||
if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL)
|
||||
sym->st_info = ELFW(ST_INFO)(STB_GLOBAL, ELFW(ST_TYPE)(STT_NOTYPE));
|
||||
if (sym_bind == STB_GLOBAL && s1->output_type == TCC_OUTPUT_OBJ) {
|
||||
/* undefined symbols with STT_FUNC are confusing gnu ld when
|
||||
linking statically to STT_GNU_IFUNC */
|
||||
sym_type = STT_NOTYPE;
|
||||
}
|
||||
#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,
|
||||
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);
|
||||
}
|
||||
|
||||
#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
|
||||
/* add tcc runtime libraries */
|
||||
ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||
@ -1708,7 +1779,7 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||
if (TCC_LIBGCC[0] == '/')
|
||||
tcc_add_file(s1, TCC_LIBGCC);
|
||||
else
|
||||
tcc_add_dll(s1, TCC_LIBGCC, 0);
|
||||
tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR);
|
||||
}
|
||||
#endif
|
||||
#if defined TCC_TARGET_ARM && TARGETOS_FreeBSD
|
||||
@ -1716,31 +1787,10 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||
#endif
|
||||
if (TCC_LIBTCC1[0])
|
||||
tcc_add_support(s1, TCC_LIBTCC1);
|
||||
|
||||
/* add crt end if not memory output */
|
||||
if (s1->output_type != TCC_OUTPUT_MEMORY) {
|
||||
#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");
|
||||
#ifndef TCC_TARGET_MACHO
|
||||
if (s1->output_type != TCC_OUTPUT_MEMORY)
|
||||
tccelf_add_crtend(s1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ndef TCC_TARGET_PE */
|
||||
@ -3834,7 +3884,7 @@ static int ld_add_file(TCCState *s1, const char filename[])
|
||||
return 0;
|
||||
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)
|
||||
|
168
tccgen.c
168
tccgen.c
@ -43,8 +43,6 @@ static int nb_sym_pools;
|
||||
|
||||
static Sym *all_cleanups, *pending_gotos;
|
||||
static int local_scope;
|
||||
static int in_sizeof;
|
||||
static int constant_p;
|
||||
ST_DATA char debug_modes;
|
||||
|
||||
ST_DATA SValue *vtop;
|
||||
@ -130,6 +128,10 @@ typedef struct {
|
||||
static void init_prec(void);
|
||||
#endif
|
||||
|
||||
static void block(int flags);
|
||||
#define STMT_EXPR 1
|
||||
#define STMT_COMPOUND 2
|
||||
|
||||
static void gen_cast(CType *type);
|
||||
static void gen_cast_s(int t);
|
||||
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 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 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 int decl(int l);
|
||||
static void expr_eq(void);
|
||||
@ -3466,11 +3467,7 @@ static void vpush_type_size(CType *type, int *a)
|
||||
int size = type_size(type, a);
|
||||
if (size < 0)
|
||||
tcc_error("unknown type size");
|
||||
#if PTR_SIZE == 8
|
||||
vpushll(size);
|
||||
#else
|
||||
vpushi(size);
|
||||
#endif
|
||||
vpushs(size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4433,11 +4430,11 @@ do_decl:
|
||||
c = 0;
|
||||
flexible = 0;
|
||||
while (tok != '}') {
|
||||
if (tok == TOK_STATIC_ASSERT) {
|
||||
do_Static_assert();
|
||||
continue;
|
||||
}
|
||||
if (!parse_btype(&btype, &ad1, 0)) {
|
||||
if (tok == TOK_STATIC_ASSERT) {
|
||||
do_Static_assert();
|
||||
continue;
|
||||
}
|
||||
skip(';');
|
||||
continue;
|
||||
}
|
||||
@ -4844,7 +4841,7 @@ static inline void convert_parameter_type(CType *pt)
|
||||
to indicate a const function parameter */
|
||||
pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
|
||||
/* 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) {
|
||||
mk_pointer(pt);
|
||||
}
|
||||
@ -5069,7 +5066,8 @@ check:
|
||||
type->ref = s;
|
||||
|
||||
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;
|
||||
else
|
||||
tok_str_free_str(vla_array_str);
|
||||
@ -5435,7 +5433,7 @@ static void parse_atomic(int atok)
|
||||
|
||||
ST_FUNC void unary(void)
|
||||
{
|
||||
int n, t, align, size, r, sizeof_caller;
|
||||
int n, t, align, size, r;
|
||||
CType type;
|
||||
Sym *s;
|
||||
AttributeDef ad;
|
||||
@ -5444,8 +5442,6 @@ ST_FUNC void unary(void)
|
||||
if (debug_modes)
|
||||
tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1);
|
||||
|
||||
sizeof_caller = in_sizeof;
|
||||
in_sizeof = 0;
|
||||
type.ref = NULL;
|
||||
/* XXX: GCC 2.95.3 does not generate a table although it should be
|
||||
better here */
|
||||
@ -5527,7 +5523,9 @@ ST_FUNC void unary(void)
|
||||
ad.section = rodata_section;
|
||||
decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
|
||||
break;
|
||||
case TOK_SOTYPE:
|
||||
case '(':
|
||||
t = tok;
|
||||
next();
|
||||
/* cast ? */
|
||||
if (parse_btype(&type, &ad, 0)) {
|
||||
@ -5545,11 +5543,10 @@ ST_FUNC void unary(void)
|
||||
r |= VT_LVAL;
|
||||
memset(&ad, 0, sizeof(AttributeDef));
|
||||
decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
|
||||
} else if (t == TOK_SOTYPE) { /* from sizeof/alignof (...) */
|
||||
vpush(&type);
|
||||
return;
|
||||
} else {
|
||||
if (sizeof_caller) {
|
||||
vpush(&type);
|
||||
return;
|
||||
}
|
||||
unary();
|
||||
gen_cast(&type);
|
||||
}
|
||||
@ -5566,7 +5563,7 @@ ST_FUNC void unary(void)
|
||||
as statement expressions can't ever be entered from the
|
||||
outside, so any reactivation of code emission (from labels
|
||||
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
|
||||
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
|
||||
@ -5630,8 +5627,9 @@ ST_FUNC void unary(void)
|
||||
case TOK_ALIGNOF3:
|
||||
t = tok;
|
||||
next();
|
||||
in_sizeof++;
|
||||
expr_type(&type, unary); /* Perform a in_sizeof = 0; */
|
||||
if (tok == '(')
|
||||
tok = TOK_SOTYPE;
|
||||
expr_type(&type, unary);
|
||||
if (t == TOK_SIZEOF) {
|
||||
vpush_type_size(&type, &align);
|
||||
gen_cast_s(VT_SIZE_T);
|
||||
@ -5687,11 +5685,12 @@ ST_FUNC void unary(void)
|
||||
}
|
||||
break;
|
||||
case TOK_builtin_constant_p:
|
||||
constant_p = 1;
|
||||
parse_builtin_params(1, "e");
|
||||
n = constant_p &&
|
||||
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
|
||||
!((vtop->r & VT_SYM) && vtop->sym->a.addrtaken);
|
||||
n = 1;
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST
|
||||
|| ((vtop->r & VT_SYM) && vtop->sym->a.addrtaken)
|
||||
)
|
||||
n = 0;
|
||||
vtop--;
|
||||
vpushi(n);
|
||||
break;
|
||||
@ -5947,10 +5946,10 @@ special_math_val:
|
||||
|
||||
default:
|
||||
tok_identifier:
|
||||
if (tok < TOK_UIDENT)
|
||||
tcc_error("expression expected before '%s'", get_tok_str(tok, &tokc));
|
||||
t = tok;
|
||||
next();
|
||||
if (t < TOK_UIDENT)
|
||||
expect("identifier");
|
||||
s = sym_find(t);
|
||||
if (!s || IS_ASM_SYM(s)) {
|
||||
const char *name = get_tok_str(t, NULL);
|
||||
@ -6546,13 +6545,19 @@ static void expr_eq(void)
|
||||
ST_FUNC void gexpr(void)
|
||||
{
|
||||
expr_eq();
|
||||
while (tok == ',') {
|
||||
constant_p &= (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
|
||||
!((vtop->r & VT_SYM) && vtop->sym->a.addrtaken);
|
||||
vpop();
|
||||
next();
|
||||
expr_eq();
|
||||
convert_parameter_type (&vtop->type);
|
||||
if (tok == ',') {
|
||||
do {
|
||||
vpop();
|
||||
next();
|
||||
expr_eq();
|
||||
} while (tok == ',');
|
||||
|
||||
/* 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;
|
||||
}
|
||||
co->bsym = bsym;
|
||||
block(0, 0);
|
||||
block(0);
|
||||
co->bsym = b;
|
||||
if (csym) {
|
||||
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;
|
||||
struct scope o;
|
||||
Sym *s;
|
||||
|
||||
if (is_expr) {
|
||||
if (flags & STMT_EXPR) {
|
||||
/* default return value is (void) */
|
||||
vpushi(0);
|
||||
vtop->type.t = VT_VOID;
|
||||
@ -6945,12 +6950,12 @@ again:
|
||||
gexpr();
|
||||
skip(')');
|
||||
a = gvtst(1, 0);
|
||||
block(0, 0);
|
||||
block(0);
|
||||
if (tok == TOK_ELSE) {
|
||||
d = gjmp(0);
|
||||
gsym(a);
|
||||
next();
|
||||
block(0, 0);
|
||||
block(0);
|
||||
gsym(d); /* patch else jmp */
|
||||
} else {
|
||||
gsym(a);
|
||||
@ -6991,13 +6996,13 @@ again:
|
||||
while (tok != '}') {
|
||||
decl(VT_LOCAL);
|
||||
if (tok != '}') {
|
||||
if (is_expr)
|
||||
if (flags & STMT_EXPR)
|
||||
vpop();
|
||||
block(is_expr, 1);
|
||||
block(flags | STMT_COMPOUND);
|
||||
}
|
||||
}
|
||||
|
||||
prev_scope(&o, is_expr);
|
||||
prev_scope(&o, flags & STMT_EXPR);
|
||||
if (debug_modes)
|
||||
tcc_debug_stabn(tcc_state, N_RBRAC, ind - func_ind);
|
||||
if (local_scope)
|
||||
@ -7168,7 +7173,6 @@ again:
|
||||
cr->sym = gind();
|
||||
dynarray_add(&cur_switch->p, &cur_switch->n, cr);
|
||||
skip(':');
|
||||
is_expr = 0;
|
||||
goto block_after_label;
|
||||
|
||||
} else if (t == TOK_DEFAULT) {
|
||||
@ -7178,7 +7182,6 @@ again:
|
||||
tcc_error("too many 'default'");
|
||||
cur_switch->def_sym = cur_switch->nocode_wanted ? 1 : gind();
|
||||
skip(':');
|
||||
is_expr = 0;
|
||||
goto block_after_label;
|
||||
|
||||
} else if (t == TOK_GOTO) {
|
||||
@ -7253,20 +7256,21 @@ again:
|
||||
if (debug_modes)
|
||||
tcc_tcov_reset_ind(tcc_state);
|
||||
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 {
|
||||
/* expression case */
|
||||
if (t != ';') {
|
||||
unget_tok(t);
|
||||
expr:
|
||||
if (is_expr) {
|
||||
if (flags & STMT_EXPR) {
|
||||
vpop();
|
||||
gexpr();
|
||||
} else {
|
||||
@ -8271,8 +8275,8 @@ static void func_vla_arg(Sym *sym)
|
||||
Sym *arg;
|
||||
|
||||
for (arg = sym->type.ref->next; arg; arg = arg->next)
|
||||
if (arg->type.t & VT_VLA)
|
||||
func_vla_arg_code(arg);
|
||||
if ((arg->type.t & VT_BTYPE) == VT_PTR && (arg->type.ref->type.t & VT_VLA))
|
||||
func_vla_arg_code(arg->type.ref);
|
||||
}
|
||||
|
||||
/* parse a function defined by symbol 'sym' and generate its code in
|
||||
@ -8316,7 +8320,7 @@ static void gen_function(Sym *sym)
|
||||
rsym = 0;
|
||||
clear_temp_local_var_list();
|
||||
func_vla_arg(sym);
|
||||
block(0, 0);
|
||||
block(0);
|
||||
gsym(rsym);
|
||||
|
||||
nocode_wanted = 0;
|
||||
@ -8424,11 +8428,6 @@ static int decl(int l)
|
||||
|
||||
while (1) {
|
||||
|
||||
if (tok == TOK_STATIC_ASSERT) {
|
||||
do_Static_assert();
|
||||
continue;
|
||||
}
|
||||
|
||||
oldint = 0;
|
||||
if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) {
|
||||
if (l == VT_JMP)
|
||||
@ -8438,6 +8437,10 @@ static int decl(int l)
|
||||
next();
|
||||
continue;
|
||||
}
|
||||
if (tok == TOK_STATIC_ASSERT) {
|
||||
do_Static_assert();
|
||||
continue;
|
||||
}
|
||||
if (l != VT_CONST)
|
||||
break;
|
||||
if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
|
||||
@ -8633,6 +8636,7 @@ static int decl(int l)
|
||||
has_init = (tok == '=');
|
||||
if (has_init && (type.t & VT_VLA))
|
||||
tcc_error("variable length array cannot be initialized");
|
||||
|
||||
if (((type.t & VT_EXTERN) && (!has_init || l != VT_CONST))
|
||||
|| (type.t & VT_BTYPE) == VT_FUNC
|
||||
/* as with GCC, uninitialized global arrays with no size
|
||||
@ -8643,20 +8647,6 @@ static int decl(int l)
|
||||
/* external variable or function */
|
||||
type.t |= VT_EXTERN;
|
||||
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 {
|
||||
if (l == VT_CONST || (type.t & VT_STATIC))
|
||||
r |= VT_CONST;
|
||||
@ -8667,18 +8657,22 @@ static int decl(int l)
|
||||
else if (l == VT_CONST)
|
||||
/* uninitialized global variables may be overridden */
|
||||
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);
|
||||
}
|
||||
|
||||
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 (l == VT_JMP)
|
||||
|
2
tccpe.c
2
tccpe.c
@ -35,7 +35,7 @@
|
||||
# define REL_TYPE_DIRECT R_X86_64_64
|
||||
# define R_XXX_THUNKFIX R_X86_64_PC32
|
||||
# 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 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;
|
||||
while (*st >= 0) {
|
||||
TOK_GET(&t, &st, &cval);
|
||||
if (t != TOK_PLCHLDR
|
||||
&& t != TOK_NOSUBST
|
||||
if (t != TOK_NOSUBST
|
||||
&& 0 == check_space(t, &spc)) {
|
||||
const char *s = get_tok_str(t, &cval);
|
||||
while (*s) {
|
||||
@ -3004,6 +3003,9 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
||||
str.len--;
|
||||
goto add_var;
|
||||
}
|
||||
} else {
|
||||
if (*st <= 0) /* expanded to empty string */
|
||||
tok_str_add(&str, TOK_PLCHLDR);
|
||||
}
|
||||
} else {
|
||||
add_var:
|
||||
@ -3021,11 +3023,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
||||
}
|
||||
st = s->next->d;
|
||||
}
|
||||
if (*st <= 0) {
|
||||
/* expanded to empty string */
|
||||
if (str.len)
|
||||
tok_str_add(&str, TOK_PLCHLDR);
|
||||
} else for (;;) {
|
||||
for (;;) {
|
||||
int t2;
|
||||
TOK_GET(&t2, &st, &cval);
|
||||
if (t2 <= 0)
|
||||
@ -3135,7 +3133,8 @@ static inline int *macro_twosharps(const int *ptr0)
|
||||
} else {
|
||||
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_print(" ###", macro_str1.str);
|
||||
@ -3154,7 +3153,7 @@ static int next_argstream(Sym **nested_list, TokenString *ws_str)
|
||||
if (macro_ptr) {
|
||||
p = macro_ptr, t = *p;
|
||||
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;
|
||||
}
|
||||
if (t == 0) {
|
||||
@ -3289,7 +3288,7 @@ static int macro_subst_tok(
|
||||
}
|
||||
do {
|
||||
next_nomacro(); /* eat '(' */
|
||||
} while (tok == TOK_PLCHLDR || is_space(tok));
|
||||
} while (is_space(tok));
|
||||
|
||||
/* argument macro */
|
||||
args = NULL;
|
||||
@ -3298,8 +3297,7 @@ static int macro_subst_tok(
|
||||
for(;;) {
|
||||
do {
|
||||
next_argstream(nested_list, NULL);
|
||||
} while (tok == TOK_PLCHLDR || is_space(tok) ||
|
||||
TOK_LINEFEED == tok);
|
||||
} while (is_space(tok) || TOK_LINEFEED == tok);
|
||||
empty_arg:
|
||||
/* handle '()' case */
|
||||
if (!args && !sa && tok == ')')
|
||||
@ -3488,7 +3486,7 @@ ST_FUNC void next(void)
|
||||
t = tok;
|
||||
if (macro_ptr) {
|
||||
if (!TOK_HAS_VALUE(t)) {
|
||||
if (t == TOK_NOSUBST || t == TOK_PLCHLDR) {
|
||||
if (t == TOK_NOSUBST) {
|
||||
/* discard preprocessor markers */
|
||||
goto redo;
|
||||
} 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. */
|
||||
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);
|
||||
else if (256 == ret)
|
||||
ret = 0;
|
||||
run_cdtors(s1, "__fini_array_start", "__fini_array_end", 0, NULL, NULL);
|
||||
run_on_exit(ret);
|
||||
if (s1->dflag & 16 && ret) /* tcc -dt -run ... */
|
||||
|
@ -13,3 +13,18 @@
|
||||
X181 M_EMPTYI_P_C1()
|
||||
X182 M_EMPTYI_P_C1(x)
|
||||
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
|
||||
X182 0
|
||||
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
|
||||
#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_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))));
|
||||
}
|
||||
|
||||
#if !defined(__TINYC__) && (__GNUC__ >= 14 || __clang_major__ >= 15)
|
||||
#define IMPLICIT_INT int
|
||||
#else
|
||||
#define IMPLICIT_INT
|
||||
#endif
|
||||
|
||||
int op(IMPLICIT_INT a, IMPLICIT_INT b)
|
||||
#if __TINYC__
|
||||
int op(a, b)
|
||||
{
|
||||
return a / b;
|
||||
}
|
||||
|
||||
int ret(IMPLICIT_INT a)
|
||||
int ret(a)
|
||||
{
|
||||
if (a == 2)
|
||||
return 1;
|
||||
@ -360,6 +350,7 @@ int ret(IMPLICIT_INT a)
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(__TINYC__) && (__GNUC__ >= 8)
|
||||
/* Old GCCs don't regard "foo"[1] as constant, even in GNU dialect. */
|
||||
@ -716,7 +707,7 @@ int tab2[3][2];
|
||||
|
||||
int g;
|
||||
|
||||
void f1(IMPLICIT_INT g)
|
||||
void f1(int g)
|
||||
{
|
||||
printf("g1=%d\n", g);
|
||||
}
|
||||
@ -1511,25 +1502,35 @@ void compound_literal_test(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if __TINYC__
|
||||
|
||||
/* K & R protos */
|
||||
|
||||
IMPLICIT_INT kr_func1(IMPLICIT_INT a, IMPLICIT_INT b)
|
||||
kr_func1(a, b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int kr_func2(IMPLICIT_INT a, IMPLICIT_INT b)
|
||||
int kr_func2(a, b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
|
||||
IMPLICIT_INT kr_test()
|
||||
kr_test()
|
||||
{
|
||||
printf("func1=%d\n", kr_func1(3, 4));
|
||||
printf("func2=%d\n", kr_func2(3, 4));
|
||||
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)
|
||||
{
|
||||
char *tab, *p;
|
||||
@ -2058,7 +2059,7 @@ void c99_bool_test(void)
|
||||
printf("b = %d\n", b);
|
||||
b2 = 0;
|
||||
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
|
||||
}
|
||||
|
||||
@ -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])
|
||||
{
|
||||
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)
|
||||
@ -3145,6 +3146,10 @@ void sizeof_test(void)
|
||||
printf("sizeof(1 && 1) = %d\n", sizeof(1 && 1));
|
||||
printf("sizeof(t || 1) = %d\n", sizeof(t || 1));
|
||||
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)
|
||||
@ -3915,30 +3920,29 @@ void builtin_test(void)
|
||||
COMPAT_TYPE(char *, unsigned char *);
|
||||
COMPAT_TYPE(char *, signed 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
|
||||
printf("res1 = %d\n", __builtin_constant_p(1));
|
||||
printf("res2 = %d\n", __builtin_constant_p(1 + 2));
|
||||
printf("res3 = %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));
|
||||
#ifdef __clang__
|
||||
/* clang doesn't regard this as constant expression */
|
||||
printf("res6 = 1\n");
|
||||
printf("res6 = %d\n", __builtin_constant_p(i && 1));
|
||||
printf("res7 = %d\n", __builtin_constant_p("hi"));
|
||||
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
|
||||
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
|
||||
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;
|
||||
ll = 2;
|
||||
i = __builtin_choose_expr (1 != 0, ll, s);
|
||||
|
@ -14,8 +14,7 @@ int main()
|
||||
break;
|
||||
|
||||
case 2:
|
||||
int a = 2;
|
||||
printf("%d\n", a);
|
||||
printf("%d\n", 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -2,14 +2,17 @@ extern int printf (const char *, ...);
|
||||
extern void target(void);
|
||||
extern void alias_for_target(void);
|
||||
extern void asm_for_target(void);
|
||||
extern int g_int, alias_int;
|
||||
|
||||
void inunit2(void);
|
||||
|
||||
void inunit2(void)
|
||||
{
|
||||
printf("in unit2:\n");
|
||||
target();
|
||||
alias_for_target();
|
||||
/* This symbol is not supposed to be available in this unit:
|
||||
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. */
|
||||
|
||||
extern int printf (const char *, ...);
|
||||
void target(void);
|
||||
void target(void) {
|
||||
printf("in target function\n");
|
||||
}
|
||||
|
||||
void alias_for_target(void) __attribute__((alias("target")));
|
||||
|
||||
int g_int = 34;
|
||||
int alias_int __attribute__((alias("g_int")));
|
||||
|
||||
#ifdef __leading_underscore
|
||||
void asm_for_target(void) __asm__("_target");
|
||||
# define _ "_"
|
||||
#else
|
||||
void asm_for_target(void) __asm__("target");
|
||||
# define _
|
||||
#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
|
||||
same unit. In TCC they even must be defined before the reference
|
||||
void alias_for_undef(void) __attribute__((alias("undefined")));
|
||||
@ -24,6 +31,7 @@ int main(void)
|
||||
target();
|
||||
alias_for_target();
|
||||
asm_for_target();
|
||||
printf("g_int = %d\nalias_int = %d\nasm_int = %d\n", g_int, alias_int, asm_int);
|
||||
inunit2();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,5 +1,11 @@
|
||||
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
|
||||
g_int = 34
|
||||
alias_int = 34
|
||||
|
@ -68,7 +68,7 @@
|
||||
60_errors_and_warnings.c:148: error: identifier expected
|
||||
|
||||
[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]
|
||||
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 &&
|
||||
((vtop->r & VT_SYM) && (vtop->c.i-4) == (int)(vtop->c.i-4))) {
|
||||
/* 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));
|
||||
#endif
|
||||
oad(0xe8 + is_jmp, 0); /* call/jmp im */
|
||||
} else {
|
||||
/* otherwise, indirect call */
|
||||
@ -668,11 +664,7 @@ static void gen_bounds_call(int v)
|
||||
{
|
||||
Sym *sym = external_helper_sym(v);
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
@ -1046,7 +1038,7 @@ void gfunc_epilog(void)
|
||||
Sym *sym = external_helper_sym(TOK___chkstk);
|
||||
oad(0xb8, v); /* mov stacksize, %eax */
|
||||
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 */
|
||||
} else {
|
||||
o(0xe5894855); /* push %rbp, mov %rsp, %rbp */
|
||||
|
Loading…
Reference in New Issue
Block a user