diff --git a/.gitignore b/.gitignore index c989b6be..9bf6d59e 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ tests/*.gcc tests/*-cc* tests/*-tcc* tests/libtcc_test +tests/libtcc_test_mt tests/asm-c-connect tests/asm-c-connect-sep tests/vla_test diff --git a/Makefile b/Makefile index e69ffe62..6e8774cc 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ ifdef CONFIG_WIN32 CFGWIN = -win NATIVE_TARGET = $(ARCH)-win$(if $(findstring arm,$(ARCH)),ce,32) else - LIBS=-lm + LIBS=-lm -lpthread ifneq ($(CONFIG_ldl),no) LIBS+=-ldl endif diff --git a/arm-asm.c b/arm-asm.c index 3b5ae661..f09f0032 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -16,7 +16,7 @@ ST_FUNC void gen_le32(int c); /*************************************************************/ #else /*************************************************************/ - +#define USING_GLOBALS #include "tcc.h" static void asm_error(void) diff --git a/arm-gen.c b/arm-gen.c index 2b220e7c..d6efb19e 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -132,6 +132,7 @@ enum { /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ +#define USING_GLOBALS #include "tcc.h" enum float_abi float_abi; diff --git a/arm-link.c b/arm-link.c index 737e30b5..f58b8a59 100644 --- a/arm-link.c +++ b/arm-link.c @@ -57,8 +57,6 @@ int code_reloc (int reloc_type) case R_ARM_JUMP_SLOT: return 1; } - - tcc_error ("Unknown relocation type: %d", reloc_type); return -1; } @@ -97,8 +95,6 @@ int gotplt_entry_type (int reloc_type) case R_ARM_GOT32: return ALWAYS_GOTPLT_ENTRY; } - - tcc_error ("Unknown relocation type: %d", reloc_type); return -1; } @@ -252,24 +248,24 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t int index; uint8_t *p; char *name, buf[1024]; - Section *text_section; + Section *text; name = (char *) symtab_section->link->data + sym->st_name; - text_section = s1->sections[sym->st_shndx]; + text = s1->sections[sym->st_shndx]; /* Modify reloc to target a thumb stub to switch to ARM */ snprintf(buf, sizeof(buf), "%s_from_thumb", name); index = put_elf_sym(symtab_section, - text_section->data_offset + 1, + text->data_offset + 1, sym->st_size, sym->st_info, 0, sym->st_shndx, buf); to_thumb = 1; - val = text_section->data_offset + 1; + val = text->data_offset + 1; rel->r_info = ELFW(R_INFO)(index, type); /* Create a thumb stub function to switch to ARM mode */ - put_elf_reloc(symtab_section, text_section, - text_section->data_offset + 4, R_ARM_JUMP24, + put_elf_reloc(symtab_section, text, + text->data_offset + 4, R_ARM_JUMP24, sym_index); - p = section_ptr_add(text_section, 8); + p = section_ptr_add(text, 8); write32le(p, 0x4778); /* bx pc */ write32le(p+2, 0x46c0); /* nop */ write32le(p+4, 0xeafffffe); /* b $sym */ diff --git a/arm64-gen.c b/arm64-gen.c index 121108e7..26f6d610 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -43,6 +43,7 @@ /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ +#define USING_GLOBALS #include "tcc.h" #include diff --git a/arm64-link.c b/arm64-link.c index a4da6a3c..3c891ff6 100644 --- a/arm64-link.c +++ b/arm64-link.c @@ -46,8 +46,6 @@ int code_reloc (int reloc_type) case R_AARCH64_JUMP_SLOT: return 1; } - - tcc_error ("Unknown relocation type: %d", reloc_type); return -1; } @@ -79,8 +77,6 @@ int gotplt_entry_type (int reloc_type) case R_AARCH64_LD64_GOT_LO12_NC: return ALWAYS_GOTPLT_ENTRY; } - - tcc_error ("Unknown relocation type: %d", reloc_type); return -1; } diff --git a/c67-gen.c b/c67-gen.c index c1e15acb..f8c854ea 100644 --- a/c67-gen.c +++ b/c67-gen.c @@ -111,6 +111,7 @@ enum { /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ +#define USING_GLOBALS #include "tcc.h" ST_DATA const int reg_classes[NB_REGS] = { diff --git a/c67-link.c b/c67-link.c index 5a26bb12..514689c5 100644 --- a/c67-link.c +++ b/c67-link.c @@ -39,8 +39,6 @@ int code_reloc (int reloc_type) case R_C60_PLT32: return 1; } - - tcc_error ("Unknown relocation type: %d", reloc_type); return -1; } @@ -64,8 +62,6 @@ int gotplt_entry_type (int reloc_type) case R_C60_GOT32: return ALWAYS_GOTPLT_ENTRY; } - - tcc_error ("Unknown relocation type: %d", reloc_type); return -1; } diff --git a/i386-asm.c b/i386-asm.c index 55c95af9..43d09da8 100644 --- a/i386-asm.c +++ b/i386-asm.c @@ -19,6 +19,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define USING_GLOBALS #include "tcc.h" #define MAX_OPERANDS 3 diff --git a/i386-gen.c b/i386-gen.c index 214359ff..e4f6ddf3 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -74,6 +74,7 @@ enum { /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ +#define USING_GLOBALS #include "tcc.h" /* define to 1/0 to [not] have EBX as 4th register */ @@ -1030,7 +1031,8 @@ ST_FUNC void gen_cvt_ftoi(int t) gfunc_call(1); vpushi(0); vtop->r = REG_IRET; - vtop->r2 = REG_LRET; + if ((t & VT_BTYPE) == VT_LLONG) + vtop->r2 = REG_LRET; } /* convert from one floating point type to another */ diff --git a/i386-link.c b/i386-link.c index f4dd08ba..e4929b43 100644 --- a/i386-link.c +++ b/i386-link.c @@ -45,8 +45,6 @@ int code_reloc (int reloc_type) case R_386_JMP_SLOT: return 1; } - - tcc_error ("Unknown relocation type: %d", reloc_type); return -1; } @@ -82,8 +80,6 @@ int gotplt_entry_type (int reloc_type) case R_386_PLT32: return ALWAYS_GOTPLT_ENTRY; } - - tcc_error ("Unknown relocation type: %d", reloc_type); return -1; } diff --git a/libtcc.c b/libtcc.c index 64dae664..dec552ca 100644 --- a/libtcc.c +++ b/libtcc.c @@ -18,25 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "tcc.h" - -/********************************************************/ -/* global variables */ - -/* use GNU C extensions */ -ST_DATA int gnu_ext = 1; - -/* use TinyCC extensions */ -ST_DATA int tcc_ext = 1; - -/* XXX: get rid of this ASAP */ -ST_DATA struct TCCState *tcc_state; - -static int nb_states; - -/********************************************************/ - -#if ONE_SOURCE +#if !defined ONE_SOURCE || ONE_SOURCE #include "tccpp.c" #include "tccgen.c" #include "tccelf.c" @@ -74,17 +56,15 @@ static int nb_states; #endif #endif /* ONE_SOURCE */ +#include "tcc.h" + /********************************************************/ -#ifndef CONFIG_TCC_ASM -ST_FUNC void asm_instr(void) -{ - tcc_error("inline asm() not supported"); -} -ST_FUNC void asm_global_instr(void) -{ - tcc_error("inline asm() not supported"); -} -#endif +/* global variables */ + +/* XXX: get rid of this ASAP (or maybe not) */ +ST_DATA struct TCCState *tcc_state; + +static int nb_states; /********************************************************/ #ifdef _WIN32 @@ -130,6 +110,35 @@ BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved) #endif #endif +/********************************************************/ +#ifndef CONFIG_TCC_SEMLOCK +#define WAIT_SEM() +#define POST_SEM() +#elif defined _WIN32 +static int tcc_sem_init; +static CRITICAL_SECTION tcc_cr; +static void wait_sem(void) +{ + if (!tcc_sem_init) + InitializeCriticalSection(&tcc_cr), tcc_sem_init = 1; + EnterCriticalSection(&tcc_cr); +} +#define WAIT_SEM() wait_sem() +#define POST_SEM() LeaveCriticalSection(&tcc_cr); +#else +#include +static int tcc_sem_init; +static sem_t tcc_sem; +static void wait_sem(void) +{ + if (!tcc_sem_init) + sem_init(&tcc_sem, 0, 1), tcc_sem_init = 1; + while (sem_wait (&tcc_sem) < 0 && errno == EINTR); +} +#define WAIT_SEM() wait_sem() +#define POST_SEM() sem_post(&tcc_sem) +#endif + /********************************************************/ /* copy a string and truncate it. */ ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s) @@ -207,7 +216,7 @@ PUB_FUNC void *tcc_malloc(unsigned long size) void *ptr; ptr = malloc(size); if (!ptr && size) - tcc_error("memory full (malloc)"); + _tcc_error("memory full (malloc)"); return ptr; } @@ -224,7 +233,7 @@ PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size) void *ptr1; ptr1 = realloc(ptr, size); if (!ptr1 && size) - tcc_error("memory full (realloc)"); + _tcc_error("memory full (realloc)"); return ptr1; } @@ -293,7 +302,7 @@ PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line) header = malloc(sizeof(mem_debug_header_t) + size); if (!header) - tcc_error("memory full (malloc)"); + _tcc_error("memory full (malloc)"); header->magic1 = MEM_DEBUG_MAGIC1; header->magic2 = MEM_DEBUG_MAGIC2; @@ -353,7 +362,7 @@ PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file mem_debug_chain_update = (header == mem_debug_chain); header = realloc(header, sizeof(mem_debug_header_t) + size); if (!header) - tcc_error("memory full (realloc)"); + _tcc_error("memory full (realloc)"); header->size = size; MEM_DEBUG_CHECK3(header) = MEM_DEBUG_MAGIC3; if (header->next) @@ -474,10 +483,41 @@ static void strcat_printf(char *buf, int buf_size, const char *fmt, ...) va_end(ap); } -static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) +#define ERROR_WARN 0 +#define ERROR_NOABORT 1 +#define ERROR_ERROR 2 + +PUB_FUNC void tcc_enter_state(TCCState *s1) +{ + WAIT_SEM(); + tcc_state = s1; +} + +static void error1(int mode, const char *fmt, va_list ap) { char buf[2048]; BufferedFile **pf, *f; + TCCState *s1 = tcc_state; + + /* 's1->error_set_jmp_enabled' means that we're called from + within the parser/generator and 'tcc_state' was already + set (i.e. not by the function above). + + Otherwise, 's1 = NULL' means we're called because of severe + problems from tcc_malloc() which under normal conditions + should never happen. */ + + if (s1 && !s1->error_set_jmp_enabled) { + tcc_state = NULL; + POST_SEM(); + } + + if (mode == ERROR_WARN) { + if (s1->warn_none) + return; + if (s1->warn_error) + mode = ERROR_ERROR; + } buf[0] = '\0'; /* use upper file if inline ":asm:" or token ":paste:" */ @@ -497,15 +537,14 @@ static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) } else { strcat_printf(buf, sizeof(buf), "tcc: "); } - if (is_warning) + if (mode == ERROR_WARN) strcat_printf(buf, sizeof(buf), "warning: "); else strcat_printf(buf, sizeof(buf), "error: "); strcat_vprintf(buf, sizeof(buf), fmt, ap); - - if (!s1->error_func) { + if (!s1 || !s1->error_func) { /* default case: stderr */ - if (s1->output_type == TCC_OUTPUT_PREPROCESS && s1->ppfp == stdout) + if (s1 && s1->output_type == TCC_OUTPUT_PREPROCESS && s1->ppfp == stdout) /* print a newline during tcc -E */ printf("\n"), fflush(stdout); fflush(stdout); /* flush -v output */ @@ -514,8 +553,15 @@ static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) } else { s1->error_func(s1->error_opaque, buf); } - if (!is_warning || s1->warn_error) - s1->nb_errors++; + if (s1) { + if (mode != ERROR_WARN) + s1->nb_errors++; + if (mode != ERROR_ERROR) + return; + if (s1->error_set_jmp_enabled) + longjmp(s1->error_jmp_buf, 1); + } + exit(1); } LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func) @@ -535,43 +581,26 @@ LIBTCCAPI void *tcc_get_error_opaque(TCCState *s) } /* error without aborting current compilation */ -PUB_FUNC void tcc_error_noabort(const char *fmt, ...) +PUB_FUNC void _tcc_error_noabort(const char *fmt, ...) { - TCCState *s1 = tcc_state; va_list ap; - va_start(ap, fmt); - error1(s1, 0, fmt, ap); + error1(ERROR_NOABORT, fmt, ap); va_end(ap); } -PUB_FUNC void tcc_error(const char *fmt, ...) +PUB_FUNC void _tcc_error(const char *fmt, ...) { - TCCState *s1 = tcc_state; va_list ap; - va_start(ap, fmt); - error1(s1, 0, fmt, ap); - va_end(ap); - /* better than nothing: in some cases, we accept to handle errors */ - if (s1->error_set_jmp_enabled) { - longjmp(s1->error_jmp_buf, 1); - } else { - /* XXX: eliminate this someday */ - exit(1); - } + for (;;) error1(ERROR_ERROR, fmt, ap); } -PUB_FUNC void tcc_warning(const char *fmt, ...) +PUB_FUNC void _tcc_warning(const char *fmt, ...) { - TCCState *s1 = tcc_state; va_list ap; - - if (s1->warn_none) - return; - va_start(ap, fmt); - error1(s1, 1, fmt, ap); + error1(ERROR_WARN, fmt, ap); va_end(ap); } @@ -588,6 +617,9 @@ ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen) bf->buf_end = bf->buffer + initlen; bf->buf_end[0] = CH_EOB; /* put eob symbol */ pstrcpy(bf->filename, sizeof(bf->filename), filename); +#ifdef _WIN32 + normalize_slashes(bf->filename); +#endif bf->true_filename = bf->filename; bf->line_num = 1; bf->ifdef_stack_ptr = s1->ifdef_stack_ptr; @@ -610,7 +642,7 @@ ST_FUNC void tcc_close(void) tcc_free(bf); } -ST_FUNC int tcc_open(TCCState *s1, const char *filename) +static int _tcc_open(TCCState *s1, const char *filename) { int fd; if (strcmp(filename, "-") == 0) @@ -620,30 +652,52 @@ ST_FUNC int tcc_open(TCCState *s1, const char *filename) if ((s1->verbose == 2 && fd >= 0) || s1->verbose == 3) printf("%s %*s%s\n", fd < 0 ? "nf":"->", (int)(s1->include_stack_ptr - s1->include_stack), "", filename); - if (fd < 0) - return -1; - tcc_open_bf(s1, filename, 0); -#ifdef _WIN32 - normalize_slashes(file->filename); -#endif - file->fd = fd; return fd; } -/* compile the file opened in 'file'. Return non zero if errors. */ -static int tcc_compile(TCCState *s1, int filetype) +ST_FUNC int tcc_open(TCCState *s1, const char *filename) { - Sym *define_start; - int is_asm; + int fd = _tcc_open(s1, filename); + if (fd < 0) + return -1; + tcc_open_bf(s1, filename, 0); + file->fd = fd; + return 0; +} - define_start = define_stack; - is_asm = !!(filetype & (AFF_TYPE_ASM|AFF_TYPE_ASMPP)); +/* compile the file opened in 'file'. Return non zero if errors. */ +static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd) +{ tccelf_begin_file(s1); - if (setjmp(s1->error_jmp_buf) == 0) { - s1->nb_errors = 0; - s1->error_set_jmp_enabled = 1; + /* Here we enter the code section where we use the global variables for + parsing and code generation (tccpp.c, tccgen.c, -gen.c). + Other threads need to wait until we're done. + Alternatively we could of course pass TCCState *s1 everwhere + except that it would look extremly ugly. + + Alternatively we could use thread local storage for those global + variables, which may or may not have advantages */ + + WAIT_SEM(); + tcc_state = s1; + + if (setjmp(s1->error_jmp_buf) == 0) { + int is_asm; + s1->error_set_jmp_enabled = 1; + s1->nb_errors = 0; + + if (fd == -1) { + int len = strlen(str); + tcc_open_bf(s1, "", len); + memcpy(file->buffer, str, len); + } else { + tcc_open_bf(s1, str, 0); + file->fd = fd; + } + + is_asm = !!(filetype & (AFF_TYPE_ASM|AFF_TYPE_ASMPP)); preprocess_start(s1, is_asm); if (s1->output_type == TCC_OUTPUT_PREPROCESS) { tcc_preprocess(s1); @@ -658,92 +712,49 @@ static int tcc_compile(TCCState *s1, int filetype) } } s1->error_set_jmp_enabled = 0; - + tccgen_finish(s1, 1); preprocess_end(s1); - free_inline_functions(s1); - /* reset define stack, but keep -D and built-ins */ - free_defines(define_start); - sym_pop(&global_stack, NULL, 0); - sym_pop(&local_stack, NULL, 0); + tccgen_finish(s1, 2); + + tcc_state = NULL; + POST_SEM(); tccelf_end_file(s1); return s1->nb_errors != 0 ? -1 : 0; } LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str) { - int len, ret; - - len = strlen(str); - tcc_open_bf(s, "", len); - memcpy(file->buffer, str, len); - ret = tcc_compile(s, s->filetype); - tcc_close(); - return ret; + return tcc_compile(s, s->filetype, str, -1); } /* define a preprocessor symbol. A value can also be provided with the '=' operator */ LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *value) { - int len1, len2; - /* default value */ if (!value) value = "1"; - len1 = strlen(sym); - len2 = strlen(value); - - /* init file structure */ - tcc_open_bf(s1, "", len1 + len2 + 1); - memcpy(file->buffer, sym, len1); - file->buffer[len1] = ' '; - memcpy(file->buffer + len1 + 1, value, len2); - - /* parse with define parser */ - next_nomacro(); - parse_define(); - tcc_close(); + cstr_printf(&s1->cmdline_defs, "#define %s %s\n", sym, value); } /* undefine a preprocessor symbol */ LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym) { - TokenSym *ts; - Sym *s; - ts = tok_alloc(sym, strlen(sym)); - s = define_find(ts->tok); - if (s) { - define_undef(s); - tok_str_free_str(s->d); - s->d = NULL; - } + cstr_printf(&s1->cmdline_defs, "#undef %s\n", sym); } -/* cleanup all static data used during compilation */ -static void tcc_cleanup(void) -{ - if (NULL == tcc_state) - return; - while (file) - tcc_close(); - tccpp_delete(tcc_state); - tcc_state = NULL; - /* free sym_pools */ - dynarray_reset(&sym_pools, &nb_sym_pools); - /* reset symbol stack */ - sym_free_first = NULL; -} LIBTCCAPI TCCState *tcc_new(void) { TCCState *s; - tcc_cleanup(); - s = tcc_mallocz(sizeof(TCCState)); if (!s) return NULL; - tcc_state = s; ++nb_states; +#undef gnu_ext + + s->gnu_ext = 1; + s->tcc_ext = 1; s->nocommon = 1; s->dollars_in_identifiers = 1; /*on by default like in gcc/clang*/ s->cversion = 199901; /* default unless -std=c11 is supplied */ @@ -760,21 +771,21 @@ LIBTCCAPI TCCState *tcc_new(void) #if 0 /* def TCC_TARGET_PE */ s->leading_underscore = 1; #endif +#ifdef CONFIG_TCC_BACKTRACE + s->rt_num_callers = 6; +#endif + s->ppfp = stdout; + /* might be used in error() before preprocess_start() */ + s->include_stack_ptr = s->include_stack; + + tccelf_new(s); + #ifdef _WIN32 tcc_set_lib_path_w32(s); #else tcc_set_lib_path(s, CONFIG_TCCDIR); #endif - tccelf_new(s); - tccpp_new(s); - /* we add dummy defines for some special macros to speed up tests - and to have working defined() */ - define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL); - define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL); - define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL); - define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL); - define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL); { /* define __TINYC__ 92X */ char buffer[32]; int a,b,c; @@ -916,8 +927,6 @@ LIBTCCAPI TCCState *tcc_new(void) LIBTCCAPI void tcc_delete(TCCState *s1) { - tcc_cleanup(); - /* free sections */ tccelf_delete(s1); @@ -926,10 +935,8 @@ LIBTCCAPI void tcc_delete(TCCState *s1) dynarray_reset(&s1->crt_paths, &s1->nb_crt_paths); /* free include paths */ - dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes); dynarray_reset(&s1->include_paths, &s1->nb_include_paths); dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths); - dynarray_reset(&s1->cmd_include_files, &s1->nb_cmd_include_files); tcc_free(s1->tcc_lib_path); tcc_free(s1->soname); @@ -943,6 +950,8 @@ LIBTCCAPI void tcc_delete(TCCState *s1) dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs); dynarray_reset(&s1->argv, &s1->argc); + cstr_free(&s1->cmdline_defs); + cstr_free(&s1->cmdline_incl); #ifdef TCC_IS_NATIVE /* free runtime memory */ tcc_run_free(s1); @@ -1018,14 +1027,14 @@ LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname) ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) { - int ret; + int fd, ret; /* open the file */ - ret = tcc_open(s1, filename); - if (ret < 0) { + fd = _tcc_open(s1, filename); + if (fd < 0) { if (flags & AFF_PRINT_ERROR) tcc_error_noabort("file '%s' not found", filename); - return ret; + return -1; } /* update target deps */ @@ -1034,9 +1043,8 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) if (flags & AFF_TYPE_BIN) { ElfW(Ehdr) ehdr; - int fd, obj_type; + int obj_type; - fd = file->fd; obj_type = tcc_object_type(fd, &ehdr); lseek(fd, 0, SEEK_SET); @@ -1076,16 +1084,16 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) ret = pe_load_file(s1, filename, fd); #else /* as GNU ld, consider it is an ld script if not recognized */ - ret = tcc_load_ldscript(s1); + ret = tcc_load_ldscript(s1, fd); #endif if (ret < 0) tcc_error_noabort("unrecognized file type"); break; } + close(fd); } else { - ret = tcc_compile(s1, flags); + ret = tcc_compile(s1, flags, filename, fd); } - tcc_close(); return ret; } @@ -1141,10 +1149,10 @@ ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags) } #ifndef TCC_TARGET_PE -ST_FUNC int tcc_add_crt(TCCState *s, const char *filename) +ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename) { - if (-1 == tcc_add_library_internal(s, "%s/%s", - filename, 0, s->crt_paths, s->nb_crt_paths)) + if (-1 == tcc_add_library_internal(s1, "%s/%s", + filename, 0, s1->crt_paths, s1->nb_crt_paths)) tcc_error_noabort("file '%s' not found", filename); return 0; } @@ -1173,9 +1181,9 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname) return -1; } -PUB_FUNC int tcc_add_library_err(TCCState *s, const char *libname) +PUB_FUNC int tcc_add_library_err(TCCState *s1, const char *libname) { - int ret = tcc_add_library(s, libname); + int ret = tcc_add_library(s1, libname); if (ret < 0) tcc_error_noabort("library '%s' not found", libname); return ret; @@ -1189,12 +1197,12 @@ ST_FUNC void tcc_add_pragma_libs(TCCState *s1) tcc_add_library_err(s1, s1->pragma_libs[i]); } -LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val) +LIBTCCAPI int tcc_add_symbol(TCCState *s1, const char *name, const void *val) { #ifdef TCC_TARGET_PE /* On x86_64 'val' might not be reachable with a 32bit offset. So it is handled here as if it were in a DLL. */ - pe_putimport(s, 0, name, (uintptr_t)val); + pe_putimport(s1, 0, name, (uintptr_t)val); #else set_elf_sym(symtab_section, (uintptr_t)val, 0, ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, @@ -1346,6 +1354,7 @@ static void copy_linker_arg(char **pp, const char *s, int sep) /* set linker options */ static int tcc_set_linker(TCCState *s, const char *option) { + TCCState *s1 = s; while (*option) { const char *p = NULL; @@ -1663,6 +1672,7 @@ static int args_parser_make_argv(const char *r, int *argc, char ***argv) static void args_parser_listfile(TCCState *s, const char *filename, int optind, int *pargc, char ***pargv) { + TCCState *s1 = s; int fd, i; size_t len; char *p; @@ -1690,6 +1700,7 @@ static void args_parser_listfile(TCCState *s, PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind) { + TCCState *s1 = s; const TCCOption *popt; const char *optarg, *r; const char *run = NULL; @@ -1781,7 +1792,7 @@ reparse: break; #ifdef CONFIG_TCC_BACKTRACE case TCC_OPTION_bt: - tcc_set_num_callers(atoi(optarg)); + s->rt_num_callers = atoi(optarg); break; #endif #ifdef CONFIG_TCC_BCHECK @@ -1909,8 +1920,7 @@ reparse: tcc_add_sysinclude_path(s, optarg); break; case TCC_OPTION_include: - dynarray_add(&s->cmd_include_files, - &s->nb_cmd_include_files, tcc_strdup(optarg)); + cstr_printf(&s->cmdline_defs, "#include \"%s\"\n", optarg); break; case TCC_OPTION_nostdinc: s->nostdinc = 1; diff --git a/riscv64-gen.c b/riscv64-gen.c index 2359a0eb..b4cad369 100644 --- a/riscv64-gen.c +++ b/riscv64-gen.c @@ -28,6 +28,7 @@ #define CHAR_IS_UNSIGNED #else +#define USING_GLOBALS #include "tcc.h" #include diff --git a/riscv64-link.c b/riscv64-link.c index fbb378e5..f4db69bf 100644 --- a/riscv64-link.c +++ b/riscv64-link.c @@ -53,7 +53,6 @@ int code_reloc (int reloc_type) case R_RISCV_CALL_PLT: return 1; } - tcc_error ("Unknown relocation type in code_reloc: %d", reloc_type); return -1; } @@ -93,8 +92,6 @@ int gotplt_entry_type (int reloc_type) case R_RISCV_GOT_HI20: return ALWAYS_GOTPLT_ENTRY; } - - tcc_error ("Unknown relocation type: %d", reloc_type); return -1; } diff --git a/tcc.c b/tcc.c index 388d3533..63250c69 100644 --- a/tcc.c +++ b/tcc.c @@ -250,7 +250,7 @@ static unsigned getclock_ms(void) int main(int argc0, char **argv0) { - TCCState *s; + TCCState *s, *s1; int ret, opt, n = 0, t = 0; unsigned start_time = 0; const char *first_file; @@ -259,14 +259,14 @@ int main(int argc0, char **argv0) redo: argc = argc0, argv = argv0; - s = tcc_new(); + s = s1 = tcc_new(); opt = tcc_parse_args(s, &argc, &argv, 1); if ((n | t) == 0) { if (opt == OPT_HELP) - return 0>fputs(help,stdout) || 0>fclose(stdout); + return fputs(help, stdout), 1; if (opt == OPT_HELP2) - return 0>fputs(help2,stdout) || 0>fclose(stdout); + return fputs(help2, stdout), 1; if (opt == OPT_M32 || opt == OPT_M64) tcc_tool_cross(s, argv, opt); /* never returns */ if (s->verbose) diff --git a/tcc.h b/tcc.h index 4db8940c..db5d6dc9 100644 --- a/tcc.h +++ b/tcc.h @@ -317,6 +317,9 @@ extern long double strtold (const char *__nptr, char **__endptr); # define ONE_SOURCE 1 #endif +/* support using libtcc from threads */ +#define CONFIG_TCC_SEMLOCK + #if ONE_SOURCE #define ST_INLN static inline #define ST_FUNC static @@ -520,6 +523,7 @@ typedef struct Section { unsigned long data_offset; /* current data offset */ unsigned char *data; /* section data */ unsigned long data_allocated; /* used for realloc() handling */ + TCCState *s1; int sh_name; /* elf section name (only used during output) */ int sh_num; /* elf section number */ int sh_type; /* elf section type */ @@ -727,6 +731,11 @@ struct TCCState { unsigned section_align; /* section alignment */ + /* use GNU C extensions */ + unsigned char gnu_ext; + /* use TinyCC extensions */ + unsigned char tcc_ext; + char *init_symbol; /* symbols to call at load-time (not used currently) */ char *fini_symbol; /* symbols to call at unload-time (not used currently) */ @@ -756,9 +765,10 @@ struct TCCState { char **crt_paths; int nb_crt_paths; - /* -include files */ - char **cmd_include_files; - int nb_cmd_include_files; + /* -D / -U options */ + CString cmdline_defs; + /* -include options */ + CString cmdline_incl; /* error handling */ void *error_opaque; @@ -815,6 +825,22 @@ struct TCCState { Section *got; Section *plt; + /* predefined sections */ + Section *text_section, *data_section, *bss_section; + Section *common_section; + Section *cur_text_section; /* current section where function code is generated */ +#ifdef CONFIG_TCC_BCHECK + /* bound check related sections */ + Section *bounds_section; /* contains global data bound description */ + Section *lbounds_section; /* contains local data bound description */ +#endif + /* symbol sections */ + Section *symtab_section; + /* debug sections */ + Section *stab_section; + /* Is there a new undefined sym since last new_undef_sym() */ + int new_undef_sym; + /* temporary dynamic symbol sections (for dll loading) */ Section *dynsymtab_section; /* exported dynamic symbol section */ @@ -857,7 +883,14 @@ struct TCCState { const char *runtime_main; void **runtime_mem; int nb_runtime_mem; +#ifdef CONFIG_TCC_BACKTRACE + int rt_num_callers; + const char **rt_bound_error_msg; + void *rt_prog_main; #endif +#endif + + int fd, cc; /* used by tcc_load_ldscript */ /* used by main and tcc_parse_args only */ struct filespec **files; /* files seen on command line */ @@ -1129,11 +1162,6 @@ enum tcc_token { /* ------------ libtcc.c ------------ */ -/* use GNU C extensions */ -ST_DATA int gnu_ext; -/* use Tiny C extensions */ -ST_DATA int tcc_ext; -/* XXX: get rid of this ASAP */ ST_DATA struct TCCState *tcc_state; /* public functions currently used by the tcc main function */ @@ -1168,9 +1196,9 @@ PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line); #undef strdup #define strdup(s) use_tcc_strdup(s) PUB_FUNC void tcc_memcheck(void); -PUB_FUNC void tcc_error_noabort(const char *fmt, ...); -PUB_FUNC NORETURN void tcc_error(const char *fmt, ...); -PUB_FUNC void tcc_warning(const char *fmt, ...); +PUB_FUNC void _tcc_error_noabort(const char *fmt, ...); +PUB_FUNC NORETURN void _tcc_error(const char *fmt, ...); +PUB_FUNC void _tcc_warning(const char *fmt, ...); /* other utilities */ ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data); @@ -1180,6 +1208,7 @@ ST_FUNC void cstr_cat(CString *cstr, const char *str, int len); ST_FUNC void cstr_wccat(CString *cstr, int ch); ST_FUNC void cstr_new(CString *cstr); ST_FUNC void cstr_free(CString *cstr); +ST_FUNC int cstr_printf(CString *cs, const char *fmt, ...); ST_FUNC void cstr_reset(CString *cstr); ST_INLN void sym_free(Sym *sym); @@ -1327,9 +1356,6 @@ static inline int toup(int c) { /* ------------ tccgen.c ------------ */ #define SYM_POOL_NB (8192 / sizeof(Sym)) -ST_DATA Sym *sym_free_first; -ST_DATA void **sym_pools; -ST_DATA int nb_sym_pools; ST_DATA Sym *global_stack; ST_DATA Sym *local_stack; @@ -1358,7 +1384,7 @@ ST_FUNC void tcc_debug_funcend(TCCState *s1, int size); ST_FUNC void tcc_debug_line(TCCState *s1); ST_FUNC int tccgen_compile(TCCState *s1); -ST_FUNC void free_inline_functions(TCCState *s); +ST_FUNC void tccgen_finish(TCCState *s1, int f); ST_FUNC void check_vstack(void); ST_INLN int is_float(int t); @@ -1427,29 +1453,14 @@ typedef struct { unsigned int n_value; /* value of symbol */ } Stab_Sym; -ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */ -ST_DATA Section *common_section; -ST_DATA Section *cur_text_section; /* current section where function code is generated */ -#ifdef CONFIG_TCC_ASM -ST_DATA Section *last_text_section; /* to handle .previous asm directive */ -#endif -#ifdef CONFIG_TCC_BCHECK -/* bound check related sections */ -ST_DATA Section *bounds_section; /* contains global data bound description */ -ST_DATA Section *lbounds_section; /* contains local data bound description */ -ST_FUNC void tccelf_bounds_new(TCCState *s); -#endif -/* symbol sections */ -ST_DATA Section *symtab_section; -/* debug sections */ -ST_DATA Section *stab_section, *stabstr_section; - ST_FUNC void tccelf_new(TCCState *s); ST_FUNC void tccelf_delete(TCCState *s); ST_FUNC void tccelf_stab_new(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); @@ -1475,10 +1486,10 @@ ST_FUNC int find_elf_sym(Section *s, const char *name); ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol); ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, addr_t addend); -ST_FUNC void put_stabs(const char *str, int type, int other, int desc, unsigned long value); -ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index); -ST_FUNC void put_stabn(int type, int other, int desc, int value); -ST_FUNC void put_stabd(int type, int other, int desc); +ST_FUNC void put_stabs(TCCState *s1, const char *str, int type, int other, int desc, unsigned long value); +ST_FUNC void put_stabs_r(TCCState *s1, const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index); +ST_FUNC void put_stabn(TCCState *s1, int type, int other, int desc, int value); +ST_FUNC void put_stabd(TCCState *s1, int type, int other, int desc); ST_FUNC void resolve_common_syms(TCCState *s1); ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve); @@ -1504,7 +1515,7 @@ ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name); #ifndef TCC_TARGET_PE ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level); -ST_FUNC int tcc_load_ldscript(TCCState *s1); +ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd); ST_FUNC uint8_t *parse_comment(uint8_t *p); ST_FUNC void minp(void); ST_INLN void inp(void); @@ -1702,12 +1713,6 @@ ST_FUNC void dlclose(void *p); ST_FUNC const char *dlerror(void); ST_FUNC void *dlsym(void *handle, const char *symbol); #endif -#ifdef CONFIG_TCC_BACKTRACE -ST_DATA int rt_num_callers; -ST_DATA const char **rt_bound_error_msg; -ST_DATA void *rt_prog_main; -ST_FUNC void tcc_set_num_callers(int n); -#endif ST_FUNC void tcc_run_free(TCCState *s1); #endif @@ -1728,5 +1733,38 @@ ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename) #else #define ST_DATA #endif +/********************************************************/ + +#define text_section TCC_STATE_VAR(text_section) +#define data_section TCC_STATE_VAR(data_section) +#define bss_section TCC_STATE_VAR(bss_section) +#define common_section TCC_STATE_VAR(common_section) +#define cur_text_section TCC_STATE_VAR(cur_text_section) +#define bounds_section TCC_STATE_VAR(bounds_section) +#define lbounds_section TCC_STATE_VAR(lbounds_section) +#define symtab_section TCC_STATE_VAR(symtab_section) +#define stab_section TCC_STATE_VAR(stab_section) +#define stabstr_section stab_section->link +#define gnu_ext TCC_STATE_VAR(gnu_ext) +#define tcc_error_noabort TCC_SET_STATE(_tcc_error_noabort) +#define tcc_error TCC_SET_STATE(_tcc_error) +#define tcc_warning TCC_SET_STATE(_tcc_warning) + +PUB_FUNC void tcc_enter_state(TCCState *s1); + /********************************************************/ #endif /* _TCC_H */ + +#undef TCC_STATE_VAR +#undef TCC_SET_STATE + +#ifdef USING_GLOBALS +# define TCC_STATE_VAR(sym) tcc_state->sym +# define TCC_SET_STATE(fn) fn +# undef USING_GLOBALS +#else +# define TCC_STATE_VAR(sym) s1->sym +# define TCC_SET_STATE(fn) (tcc_enter_state(s1),fn) +/* actually we could avoid the tcc_enter_state(s1) hack by using + __VA_ARGS__ except that some compiler doesn't support it. */ +#endif diff --git a/tccasm.c b/tccasm.c index a8412f47..fefe549f 100644 --- a/tccasm.c +++ b/tccasm.c @@ -18,9 +18,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define USING_GLOBALS #include "tcc.h" #ifdef CONFIG_TCC_ASM +static Section *last_text_section; /* to handle .previous asm directive */ + ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n) { char buf[64]; diff --git a/tcccoff.c b/tcccoff.c index 1421ca26..651bbe82 100644 --- a/tcccoff.c +++ b/tcccoff.c @@ -40,12 +40,12 @@ int FuncEntries[MAX_FUNCS]; int OutputTheSection(Section * sect); short int GetCoffFlags(const char *s); -void SortSymbolTable(void); +void SortSymbolTable(TCCState *s1); Section *FindSection(TCCState * s1, const char *sname); int C67_main_entry_point; -int FindCoffSymbolIndex(const char *func_name); +int FindCoffSymbolIndex(TCCState * s1, const char *func_name); int nb_syms; typedef struct { @@ -92,7 +92,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f) sbss = FindSection(s1, ".bss"); nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym); - coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1"); + coff_nb_syms = FindCoffSymbolIndex(s1, "XXXXXXXXXX1"); file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */ file_hdr.f_timdat = 0; /* time & date stamp */ @@ -366,7 +366,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f) // finally global symbols if (s1->do_debug) - SortSymbolTable(); + SortSymbolTable(s1); // write line no data @@ -437,7 +437,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f) // output a function begin CoffLineNo.l_addr.l_symndx = - FindCoffSymbolIndex(func_name); + FindCoffSymbolIndex(s1, func_name); CoffLineNo.l_lnno = 0; fwrite(&CoffLineNo, 6, 1, f); @@ -690,7 +690,7 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f) // group the symbols in order of filename, func1, func2, etc // finally global symbols -void SortSymbolTable(void) +void SortSymbolTable(TCCState *s1) { int i, j, k, n = 0; Elf32_Sym *p, *p2, *NewTable; @@ -770,7 +770,7 @@ void SortSymbolTable(void) } -int FindCoffSymbolIndex(const char *func_name) +int FindCoffSymbolIndex(TCCState *s1, const char *func_name) { int i, n = 0; Elf32_Sym *p; diff --git a/tccelf.c b/tccelf.c index 6cdf02ae..2f149225 100644 --- a/tccelf.c +++ b/tccelf.c @@ -26,22 +26,6 @@ /********************************************************/ /* global variables */ -ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */ -ST_DATA Section *common_section; -ST_DATA Section *cur_text_section; /* current section where function code is generated */ -#ifdef CONFIG_TCC_ASM -ST_DATA Section *last_text_section; /* to handle .previous asm directive */ -#endif -#ifdef CONFIG_TCC_BCHECK -/* bound check related sections */ -ST_DATA Section *bounds_section; /* contains global data bound description */ -ST_DATA Section *lbounds_section; /* contains local data bound description */ -#endif -/* symbol sections */ -ST_DATA Section *symtab_section; -/* debug sections */ -ST_DATA Section *stab_section, *stabstr_section; - /* elf version information */ struct sym_version { char *lib; @@ -58,9 +42,6 @@ struct sym_version { #define versym_section s1->versym_section #define verneed_section s1->verneed_section -/* XXX: avoid static variable */ -static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */ - /* special flag to indicate that the section should not be linked to the other ones */ #define SHF_PRIVATE 0x80000000 /* section is dynsymtab_section */ @@ -70,6 +51,7 @@ static int new_undef_sym = 0; /* Is there a new undefined sym since last new_und ST_FUNC void tccelf_new(TCCState *s) { + TCCState *s1 = s; /* no section zero */ dynarray_add(&s->sections, &s->nb_sections, NULL); @@ -96,6 +78,7 @@ ST_FUNC void tccelf_new(TCCState *s) #ifdef CONFIG_TCC_BCHECK ST_FUNC void tccelf_bounds_new(TCCState *s) { + TCCState *s1 = s; /* create bounds sections */ bounds_section = new_section(s, ".bounds", SHT_PROGBITS, SHF_ALLOC); @@ -106,13 +89,13 @@ ST_FUNC void tccelf_bounds_new(TCCState *s) ST_FUNC void tccelf_stab_new(TCCState *s) { + TCCState *s1 = s; stab_section = new_section(s, ".stab", SHT_PROGBITS, 0); stab_section->sh_entsize = sizeof(Stab_Sym); - stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0); - put_elf_str(stabstr_section, ""); - stab_section->link = stabstr_section; + stab_section->link = new_section(s, ".stabstr", SHT_STRTAB, 0); + put_elf_str(stab_section->link, ""); /* put first entry */ - put_stabs("", 0, 0, 0, 0); + put_stabs(s, "", 0, 0, 0, 0); } static void free_section(Section *s) @@ -220,6 +203,7 @@ ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh Section *sec; sec = tcc_mallocz(sizeof(Section) + strlen(name)); + sec->s1 = s1; strcpy(sec->name, name); sec->sh_type = sh_type; sec->sh_flags = sh_flags; @@ -492,13 +476,13 @@ ST_FUNC int find_elf_sym(Section *s, const char *name) } /* return elf symbol value, signal error if 'err' is nonzero */ -ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err) +ST_FUNC addr_t get_elf_sym_addr(TCCState *s1, const char *name, int err) { int sym_index; ElfW(Sym) *sym; - sym_index = find_elf_sym(s->symtab, name); - sym = &((ElfW(Sym) *)s->symtab->data)[sym_index]; + sym_index = find_elf_sym(s1->symtab, name); + sym = &((ElfW(Sym) *)s1->symtab->data)[sym_index]; if (!sym_index || sym->st_shndx == SHN_UNDEF) { if (err) tcc_error("%s not defined", name); @@ -554,7 +538,7 @@ ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name) #ifndef ELF_OBJ_ONLY static void -version_add (TCCState *s) +version_add (TCCState *s1) { int i; ElfW(Sym) *sym; @@ -563,7 +547,6 @@ version_add (TCCState *s) int sym_index, end_sym, nb_versions = 2, nb_entries = 0; ElfW(Half) *versym; const char *name; - TCCState *s1 = s; if (0 == nb_sym_versions) return; @@ -574,14 +557,14 @@ version_add (TCCState *s) verneed_section->link = s1->dynsym->link; /* add needed symbols */ - symtab = s->dynsym; + symtab = s1->dynsym; end_sym = symtab->data_offset / sizeof (ElfSym); versym = section_ptr_add(versym_section, end_sym * sizeof(ElfW(Half))); for (sym_index = 0; sym_index < end_sym; ++sym_index) { int dllindex, verndx; sym = &((ElfW(Sym) *)symtab->data)[sym_index]; name = (char *) symtab->link->data + sym->st_name; - dllindex = find_elf_sym(s->dynsymtab_section, name); + dllindex = find_elf_sym(s1->dynsymtab_section, name); verndx = (dllindex && dllindex < nb_sym_to_version) ? sym_to_version[dllindex] : -1; if (verndx >= 0) { @@ -636,6 +619,7 @@ version_add (TCCState *s) ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name) { + TCCState *s1 = s->s1; ElfW(Sym) *esym; int sym_bind, sym_index, sym_type, esym_bind; unsigned char sym_vis, esym_vis, new_vis; @@ -705,7 +689,7 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, do_patch: esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type); esym->st_shndx = shndx; - new_undef_sym = 1; + s1->new_undef_sym = 1; esym->st_value = value; esym->st_size = size; esym->st_other = other; @@ -723,6 +707,7 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, addr_t addend) { + TCCState *s1 = s->s1; char buf[256]; Section *sr; ElfW_Rel *rel; @@ -733,7 +718,7 @@ ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name); /* if the symtab is allocated, then we consider the relocation are also */ - sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags); + sr = new_section(s->s1, buf, SHT_RELX, symtab->sh_flags); sr->sh_entsize = sizeof(ElfW_Rel); sr->link = symtab; sr->sh_info = s->sh_num; @@ -744,10 +729,9 @@ ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, rel->r_info = ELFW(R_INFO)(symbol, type); #if SHT_RELX == SHT_RELA rel->r_addend = addend; -#else - if (addend) - tcc_error("non-zero addend on REL architecture"); #endif + if (SHT_RELX != SHT_RELA && addend) + tcc_error("non-zero addend on REL architecture"); } ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, @@ -795,14 +779,14 @@ ST_FUNC void squeeze_multi_relocs(Section *s, size_t oldrelocoffset) /* put stab debug information */ -ST_FUNC void put_stabs(const char *str, int type, int other, int desc, +ST_FUNC void put_stabs(TCCState *s1, const char *str, int type, int other, int desc, unsigned long value) { Stab_Sym *sym; sym = section_ptr_add(stab_section, sizeof(Stab_Sym)); if (str) { - sym->n_strx = put_elf_str(stabstr_section, str); + sym->n_strx = put_elf_str(stab_section->link, str); } else { sym->n_strx = 0; } @@ -812,23 +796,23 @@ ST_FUNC void put_stabs(const char *str, int type, int other, int desc, sym->n_value = value; } -ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc, +ST_FUNC void put_stabs_r(TCCState *s1, const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index) { - put_stabs(str, type, other, desc, value); + put_stabs(s1, str, type, other, desc, value); put_elf_reloc(symtab_section, stab_section, stab_section->data_offset - sizeof(unsigned int), R_DATA_32, sym_index); } -ST_FUNC void put_stabn(int type, int other, int desc, int value) +ST_FUNC void put_stabn(TCCState *s1, int type, int other, int desc, int value) { - put_stabs(NULL, type, other, desc, value); + put_stabs(s1, NULL, type, other, desc, value); } -ST_FUNC void put_stabd(int type, int other, int desc) +ST_FUNC void put_stabd(TCCState *s1, int type, int other, int desc) { - put_stabs(NULL, type, other, desc, 0); + put_stabs(s1, NULL, type, other, desc, 0); } ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc) @@ -1180,6 +1164,8 @@ ST_FUNC void build_got_entries(TCCState *s1) for_each_elem(s, 0, rel, ElfW_Rel) { type = ELFW(R_TYPE)(rel->r_info); gotplt_entry = gotplt_entry_type(type); + if (gotplt_entry == -1) + tcc_error ("Unknown relocation type for got: %d", type); sym_index = ELFW(R_SYM)(rel->r_info); sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; @@ -1235,7 +1221,10 @@ ST_FUNC void build_got_entries(TCCState *s1) continue; } #endif - if (code_reloc(type)) { + reloc_type = code_reloc(type); + if (reloc_type == -1) + tcc_error ("Unknown relocation type: %d", type); + else if (reloc_type != 0) { jmp_slot: reloc_type = R_JMP_SLOT; } else @@ -3194,13 +3183,27 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) #define LD_TOK_NAME 256 #define LD_TOK_EOF (-1) +static int ld_inp(TCCState *s1) +{ + char b; + if (s1->cc != -1) { + int c = s1->cc; + s1->cc = -1; + return c; + } + if (1 == read(s1->fd, &b, 1)) + return b; + return CH_EOF; +} + /* return next ld script token */ static int ld_next(TCCState *s1, char *name, int name_size) { - int c; + int c, d, ch; char *q; redo: + ch = ld_inp(s1); switch(ch) { case ' ': case '\t': @@ -3208,13 +3211,15 @@ static int ld_next(TCCState *s1, char *name, int name_size) case '\v': case '\r': case '\n': - inp(); goto redo; case '/': - minp(); - if (ch == '*') { - file->buf_ptr = parse_comment(file->buf_ptr); - ch = file->buf_ptr[0]; + ch = ld_inp(s1); + if (ch == '*') { /* comment */ + for (d = 0;; d = ch) { + ch = ld_inp(s1); + if (ch == CH_EOF || (ch == '/' && d == '*')) + break; + } goto redo; } else { q = name; @@ -3223,10 +3228,6 @@ static int ld_next(TCCState *s1, char *name, int name_size) } break; case '\\': - ch = handle_eob(); - if (ch != '\\') - goto redo; - /* fall through */ /* case 'a' ... 'z': */ case 'a': case 'b': @@ -3296,8 +3297,9 @@ static int ld_next(TCCState *s1, char *name, int name_size) if ((q - name) < name_size - 1) { *q++ = ch; } - minp(); + ch = ld_inp(s1); } + s1->cc = ch; *q = '\0'; c = LD_TOK_NAME; break; @@ -3306,7 +3308,6 @@ static int ld_next(TCCState *s1, char *name, int name_size) break; default: c = ch; - inp(); break; } return c; @@ -3323,14 +3324,6 @@ static int ld_add_file(TCCState *s1, const char filename[]) return tcc_add_dll(s1, filename, 0); } -static inline int new_undef_syms(void) -{ - int ret = 0; - ret = new_undef_sym; - new_undef_sym = 0; - return ret; -} - static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed) { char filename[1024], libname[1024]; @@ -3339,7 +3332,7 @@ static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed) group = !strcmp(cmd, "GROUP"); if (!as_needed) - new_undef_syms(); + s1->new_undef_sym = 0; t = ld_next(s1, filename, sizeof(filename)); if (t != '(') expect("("); @@ -3394,9 +3387,9 @@ static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed) } } if (group && !as_needed) { - while (new_undef_syms()) { + while (s1->new_undef_sym) { int i; - + s1->new_undef_sym = 0; for (i = 0; i < nblibs; i ++) ld_add_file(s1, libs[i]); } @@ -3408,13 +3401,14 @@ lib_parse_error: /* interpret a subset of GNU ldscripts to handle the dummy libc.so files */ -ST_FUNC int tcc_load_ldscript(TCCState *s1) +ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd) { char cmd[64]; char filename[1024]; int t, ret; - ch = handle_eob(); + s1->fd = fd; + s1->cc = -1; for(;;) { t = ld_next(s1, cmd, sizeof(cmd)); if (t == LD_TOK_EOF) diff --git a/tccgen.c b/tccgen.c index 73a44948..af119673 100644 --- a/tccgen.c +++ b/tccgen.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define USING_GLOBALS #include "tcc.h" + /********************************************************/ /* global variables */ @@ -29,16 +31,16 @@ */ ST_DATA int rsym, anon_sym, ind, loc; -ST_DATA Sym *sym_free_first; -ST_DATA void **sym_pools; -ST_DATA int nb_sym_pools; - ST_DATA Sym *global_stack; ST_DATA Sym *local_stack; ST_DATA Sym *define_stack; ST_DATA Sym *global_label_stack; ST_DATA Sym *local_label_stack; +static Sym *sym_free_first; +static void **sym_pools; +static int nb_sym_pools; + static Sym *all_cleanups, *pending_gotos; static int local_scope; static int in_sizeof; @@ -106,6 +108,18 @@ static struct scope { Sym *lstk, *llstk; } *cur_scope, *loop_scope, *root_scope; +/********************************************************/ +#ifndef CONFIG_TCC_ASM +ST_FUNC void asm_instr(void) +{ + tcc_error("inline asm() not supported"); +} +ST_FUNC void asm_global_instr(void) +{ + tcc_error("inline asm() not supported"); +} +#endif + /* ------------------------------------------------------------------------- */ static void gen_cast(CType *type); @@ -129,6 +143,7 @@ static void vpush64(int ty, unsigned long long v); static void vpush(CType *type); static int gvtst(int inv, int t); static void gen_inline_functions(TCCState *s); +static void free_inline_functions(TCCState *s); static void skip_or_save_block(TokenString **str); static void gv_dup(void); static int get_temp_local_var(int size,int align); @@ -200,9 +215,9 @@ ST_FUNC void tcc_debug_start(TCCState *s1) normalize_slashes(buf); #endif pstrcat(buf, sizeof(buf), "/"); - put_stabs_r(buf, N_SO, 0, 0, + put_stabs_r(s1, buf, N_SO, 0, 0, text_section->data_offset, text_section, section_sym); - put_stabs_r(file->filename, N_SO, 0, 0, + put_stabs_r(s1, file->prev->filename, N_SO, 0, 0, text_section->data_offset, text_section, section_sym); last_ind = 0; last_line_num = 0; @@ -220,7 +235,7 @@ ST_FUNC void tcc_debug_end(TCCState *s1) { if (!s1->do_debug) return; - put_stabs_r(NULL, N_SO, 0, 0, + put_stabs_r(s1, NULL, N_SO, 0, 0, text_section->data_offset, text_section, section_sym); } @@ -231,7 +246,7 @@ ST_FUNC void tcc_debug_line(TCCState *s1) if (!s1->do_debug) return; if ((last_line_num != file->line_num || last_ind != ind)) { - put_stabn(N_SLINE, 0, file->line_num, ind - func_ind); + put_stabn(s1, N_SLINE, 0, file->line_num, ind - func_ind); last_ind = ind; last_line_num = file->line_num; } @@ -249,10 +264,10 @@ ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym) /* XXX: we put here a dummy type */ snprintf(buf, sizeof(buf), "%s:%c1", funcname, sym->type.t & VT_STATIC ? 'f' : 'F'); - put_stabs_r(buf, N_FUN, 0, file->line_num, 0, + put_stabs_r(s1, buf, N_FUN, 0, file->line_num, 0, cur_text_section, sym->c); /* //gr gdb wants a line at the function */ - put_stabn(N_SLINE, 0, file->line_num, 0); + put_stabn(s1, N_SLINE, 0, file->line_num, 0); last_ind = 0; last_line_num = 0; @@ -263,7 +278,7 @@ ST_FUNC void tcc_debug_funcend(TCCState *s1, int size) { if (!s1->do_debug) return; - put_stabn(N_FUN, 0, 0, size); + put_stabn(s1, N_FUN, 0, 0, size); } /* ------------------------------------------------------------------------- */ @@ -316,6 +331,21 @@ ST_FUNC int tccgen_compile(TCCState *s1) return 0; } +ST_FUNC void tccgen_finish(TCCState *s1, int f) +{ + if (f == 1) { + free_inline_functions(s1); + sym_pop(&global_stack, NULL, 0); + sym_pop(&local_stack, NULL, 0); + } + + if (f == 2) { + /* free sym_pools */ + dynarray_reset(&sym_pools, &nb_sym_pools); + sym_free_first = NULL; + } +} + /* ------------------------------------------------------------------------- */ ST_FUNC ElfSym *elfsym(Sym *s) { @@ -7684,7 +7714,7 @@ static void gen_inline_functions(TCCState *s) tcc_close(); } -ST_FUNC void free_inline_functions(TCCState *s) +static void free_inline_functions(TCCState *s) { int i; /* free tokens of unused inline functions */ diff --git a/tccpe.c b/tccpe.c index 6ecb87d9..6c15e048 100644 --- a/tccpe.c +++ b/tccpe.c @@ -602,6 +602,7 @@ static int pe_write(struct pe_info *pe) DWORD file_offset, sum; struct section_info *si; IMAGE_SECTION_HEADER *psh; + TCCState *s1 = pe->s1; op = fopen(pe->filename, "wb"); if (NULL == op) { @@ -784,6 +785,7 @@ static void pe_build_imports(struct pe_info *pe) int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i; DWORD rva_base = pe->thunk->sh_addr - pe->imagebase; int ndlls = pe->imp_count; + TCCState *s1 = pe->s1; for (sym_cnt = i = 0; i < ndlls; ++i) sym_cnt += pe->imp_info[i]->sym_count; @@ -895,6 +897,7 @@ static void pe_build_exports(struct pe_info *pe) IMAGE_EXPORT_DIRECTORY *hdr; int sym_count, ord; struct pe_sort_sym **sorted, *p; + TCCState *s1 = pe->s1; FILE *op; char buf[260]; @@ -1195,7 +1198,7 @@ static int pe_assign_addresses (struct pe_info *pe) /*----------------------------------------------------------------------------*/ -static int pe_isafunc(int sym_index) +static int pe_isafunc(TCCState *s1, int sym_index) { Section *sr = text_section->reloc; ElfW_Rel *rel, *rel_end; @@ -1215,6 +1218,7 @@ static int pe_check_symbols(struct pe_info *pe) ElfW(Sym) *sym; int sym_index, sym_end; int ret = 0; + TCCState *s1 = pe->s1; pe_align_section(text_section, 8); @@ -1234,7 +1238,7 @@ static int pe_check_symbols(struct pe_info *pe) if (type == STT_NOTYPE) { /* symbols from assembler have no type, find out which */ - if (pe_isafunc(sym_index)) + if (pe_isafunc(s1, sym_index)) type = STT_FUNC; else type = STT_OBJECT; @@ -1769,7 +1773,7 @@ ST_FUNC int pe_load_file(struct TCCState *s1, const char *filename, int fd) static unsigned pe_add_uwwind_info(TCCState *s1) { if (NULL == s1->uw_pdata) { - s1->uw_pdata = find_section(tcc_state, ".pdata"); + s1->uw_pdata = find_section(s1, ".pdata"); s1->uw_pdata->sh_addralign = 4; } if (0 == s1->uw_sym) diff --git a/tccpp.c b/tccpp.c index 8974f8c4..a6ad8218 100644 --- a/tccpp.c +++ b/tccpp.c @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define USING_GLOBALS #include "tcc.h" /********************************************************/ @@ -54,7 +55,6 @@ static void tok_print(const char *msg, const int *str); static struct TinyAlloc *toksym_alloc; static struct TinyAlloc *tokstr_alloc; -static struct TinyAlloc *cstr_alloc; static TokenString *macro_stack; @@ -331,7 +331,7 @@ static void cstr_realloc(CString *cstr, int new_size) size = 8; /* no need to allocate a too small first string */ while (size < new_size) size = size * 2; - cstr->data = tal_realloc(cstr_alloc, cstr->data, size); + cstr->data = tcc_realloc(cstr->data, size); cstr->size_allocated = size; } @@ -377,7 +377,7 @@ ST_FUNC void cstr_new(CString *cstr) /* free string and reset it to NULL */ ST_FUNC void cstr_free(CString *cstr) { - tal_free(cstr_alloc, cstr->data); + tcc_free(cstr->data); cstr_new(cstr); } @@ -387,6 +387,24 @@ ST_FUNC void cstr_reset(CString *cstr) cstr->size = 0; } +ST_FUNC int cstr_printf(CString *cstr, const char *fmt, ...) +{ + va_list v; + int len, size; + + va_start(v, fmt); + len = vsnprintf(NULL, 0, fmt, v); + va_end(v); + size = cstr->size + len + 1; + if (size > cstr->size_allocated) + cstr_realloc(cstr, size); + va_start(v, fmt); + vsnprintf((char*)cstr->data + cstr->size, size, fmt, v); + va_end(v); + cstr->size += len; + return len; +} + /* XXX: unicode ? */ static void add_char(CString *cstr, int c) { @@ -1338,18 +1356,6 @@ ST_FUNC void free_defines(Sym *b) define_undef(top); sym_free(top); } - - /* restore remaining (-D or predefined) symbols if they were - #undef'd in the file */ - while (b) { - int v = b->v; - if (v >= TOK_IDENT && v < tok_ident) { - Sym **d = &table_ident[v - TOK_IDENT]->sym_define; - if (!*d && b->d) - *d = b; - } - b = b->prev; - } } /* label lookup */ @@ -1855,7 +1861,7 @@ ST_FUNC void preprocess(int is_bof) } /* add include file debug info */ if (s1->do_debug) - put_stabs(file->filename, N_BINCL, 0, 0, 0); + put_stabs(tcc_state, file->filename, N_BINCL, 0, 0, 0); tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL; ch = file->buf_ptr[0]; goto the_end; @@ -1964,7 +1970,7 @@ include_done: total_lines += file->line_num - n; file->line_num = n; if (s1->do_debug) - put_stabs(file->filename, N_BINCL, 0, 0, 0); + put_stabs(tcc_state, file->filename, N_BINCL, 0, 0, 0); break; case TOK_ERROR: case TOK_WARNING: @@ -2278,7 +2284,7 @@ static void parse_number(const char *p) q--; ch = *p++; b = 16; - } else if (tcc_ext && (ch == 'b' || ch == 'B')) { + } else if (tcc_state->tcc_ext && (ch == 'b' || ch == 'B')) { q--; ch = *p++; b = 2; @@ -2622,7 +2628,7 @@ static inline void next_nomacro1(void) /* add end of include file debug info */ if (tcc_state->do_debug) { - put_stabd(N_EINCL, 0, 0); + put_stabd(tcc_state, N_EINCL, 0, 0); } /* pop include stack */ tcc_close(); @@ -3584,7 +3590,8 @@ ST_INLN void unget_tok(int last_tok) ST_FUNC void preprocess_start(TCCState *s1, int is_asm) { CString cstr; - int i; + + tccpp_new(s1); s1->include_stack_ptr = s1->include_stack; s1->ifdef_stack_ptr = s1->ifdef_stack; @@ -3602,26 +3609,18 @@ ST_FUNC void preprocess_start(TCCState *s1, int is_asm) set_idnum('.', is_asm ? IS_ID : 0); cstr_new(&cstr); - cstr_cat(&cstr, "\"", -1); - cstr_cat(&cstr, file->filename, -1); - cstr_cat(&cstr, "\"", 0); - tcc_define_symbol(s1, "__BASE_FILE__", cstr.data); - - cstr_reset(&cstr); - for (i = 0; i < s1->nb_cmd_include_files; i++) { - cstr_cat(&cstr, "#include \"", -1); - cstr_cat(&cstr, s1->cmd_include_files[i], -1); - cstr_cat(&cstr, "\"\n", -1); - } - if (cstr.size) { - *s1->include_stack_ptr++ = file; - tcc_open_bf(s1, "", cstr.size); - memcpy(file->buffer, cstr.data, cstr.size); - } - cstr_free(&cstr); - if (is_asm) - tcc_define_symbol(s1, "__ASSEMBLER__", NULL); + cstr_printf(&cstr, "#define __ASSEMBLER__ 1\n"); + cstr_printf(&cstr, "#define __BASE_FILE__ \"%s\"\n", file->filename); + if (s1->cmdline_defs.size) + cstr_cat(&cstr, s1->cmdline_defs.data, s1->cmdline_defs.size); + //printf("%s\n", (char*)s1->cmdline_defs.data); + if (s1->cmdline_incl.size) + cstr_cat(&cstr, s1->cmdline_incl.data, s1->cmdline_incl.size); + *s1->include_stack_ptr++ = file; + tcc_open_bf(s1, "", cstr.size); + memcpy(file->buffer, cstr.data, cstr.size); + cstr_free(&cstr); parse_flags = is_asm ? PARSE_FLAG_ASM_FILE : 0; tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; @@ -3633,6 +3632,11 @@ ST_FUNC void preprocess_end(TCCState *s1) while (macro_stack) end_macro(); macro_ptr = NULL; + + while (file) + tcc_close(); + + tccpp_delete(s1); } ST_FUNC void tccpp_new(TCCState *s) @@ -3640,10 +3644,6 @@ ST_FUNC void tccpp_new(TCCState *s) int i, c; const char *p, *r; - /* might be used in error() before preprocess_start() */ - s->include_stack_ptr = s->include_stack; - s->ppfp = stdout; - /* init isid table */ for(i = CH_EOF; i<128; i++) set_idnum(i, @@ -3658,9 +3658,10 @@ ST_FUNC void tccpp_new(TCCState *s) /* init allocators */ tal_new(&toksym_alloc, TOKSYM_TAL_LIMIT, TOKSYM_TAL_SIZE); tal_new(&tokstr_alloc, TOKSTR_TAL_LIMIT, TOKSTR_TAL_SIZE); - tal_new(&cstr_alloc, CSTR_TAL_LIMIT, CSTR_TAL_SIZE); memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *)); + memset(s->cached_includes_hash, 0, sizeof s->cached_includes_hash); + cstr_new(&cstr_buf); cstr_realloc(&cstr_buf, STRING_MAX_SIZE); tok_str_new(&tokstr_buf); @@ -3678,14 +3679,22 @@ ST_FUNC void tccpp_new(TCCState *s) tok_alloc(p, r - p - 1); p = r; } + + /* we add dummy defines for some special macros to speed up tests + and to have working defined() */ + define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL); + define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL); + define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL); + define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL); + define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL); } ST_FUNC void tccpp_delete(TCCState *s) { int i, n; - /* free -D and compiler defines */ free_defines(NULL); + dynarray_reset(&s->cached_includes, &s->nb_cached_includes); /* free tokens */ n = tok_ident - TOK_IDENT; @@ -3705,8 +3714,6 @@ ST_FUNC void tccpp_delete(TCCState *s) toksym_alloc = NULL; tal_delete(tokstr_alloc); tokstr_alloc = NULL; - tal_delete(cstr_alloc); - cstr_alloc = NULL; } /* ------------------------------------------------------------------------- */ diff --git a/tccrun.c b/tccrun.c index 71b9db3b..a733e9ae 100644 --- a/tccrun.c +++ b/tccrun.c @@ -36,15 +36,29 @@ # else # define ucontext_t CONTEXT # endif -ST_DATA int rt_num_callers = 6; -ST_DATA const char **rt_bound_error_msg; -ST_DATA void *rt_prog_main; + static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level); static void rt_error(ucontext_t *uc, const char *fmt, ...); static void set_exception_handler(void); + +#ifdef _WIN32 +static DWORD s1_for_run_idx; +void set_s1_for_run(TCCState *s) +{ + if (!s1_for_run_idx) + s1_for_run_idx = TlsAlloc(); + TlsSetValue(s1_for_run_idx, s); +} +#define get_s1_for_run() ((TCCState*)TlsGetValue(s1_for_run_idx)) +#else +/* XXX: add tls support for linux */ +static TCCState *s1_for_run; +#define set_s1_for_run(s) (s1_for_run = s) +#define get_s1_for_run() s1_for_run +#endif #endif -static void set_pages_executable(void *ptr, unsigned long length); +static void set_pages_executable(TCCState *s1, void *ptr, unsigned long length); static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff); #ifdef _WIN64 @@ -110,6 +124,8 @@ ST_FUNC void tcc_run_free(TCCState *s1) #endif } tcc_free(s1->runtime_mem); + if (get_s1_for_run() == s1) + set_s1_for_run(NULL); } /* launch the compiled program with the given arguments */ @@ -127,7 +143,9 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) #ifdef CONFIG_TCC_BACKTRACE if (s1->do_debug) { set_exception_handler(); - rt_prog_main = prog_main; + s1->rt_prog_main = prog_main; + /* set global state pointer for exception handlers*/ + set_s1_for_run(s1); } #endif @@ -142,7 +160,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) int ret; /* set error function */ - rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg"); + s1->rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg"); /* XXX: use .init section so that it also work in binary ? */ bound_init = tcc_get_symbol_err(s1, "__bound_init"); bound_exit = tcc_get_symbol_err(s1, "__bound_exit"); @@ -255,7 +273,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) memcpy(ptr, s->data, length); /* mark executable sections as executable in memory */ if (s->sh_flags & SHF_EXECINSTR) - set_pages_executable((char*)ptr + ptr_diff, length); + set_pages_executable(s1, (char*)ptr + ptr_diff, length); } #ifdef _WIN64 @@ -268,7 +286,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) /* ------------------------------------------------------------- */ /* allow to run code in memory */ -static void set_pages_executable(void *ptr, unsigned long length) +static void set_pages_executable(TCCState *s1, void *ptr, unsigned long length) { #ifdef _WIN32 unsigned long old_protect; @@ -319,14 +337,9 @@ static void win64_del_function_table(void *p) /* ------------------------------------------------------------- */ #ifdef CONFIG_TCC_BACKTRACE -ST_FUNC void tcc_set_num_callers(int n) -{ - rt_num_callers = n; -} - /* print the position in the source file of PC value 'pc' by reading the stabs debug information */ -static addr_t rt_printline(addr_t wanted_pc, const char *msg) +static addr_t rt_printline(TCCState *s1, addr_t wanted_pc, const char *msg) { char func_name[128], last_func_name[128]; addr_t func_addr, last_pc, pc; @@ -341,7 +354,7 @@ static addr_t rt_printline(addr_t wanted_pc, const char *msg) if (stab_section) { stab_len = stab_section->data_offset; stab_sym = (Stab_Sym *)stab_section->data; - stab_str = (char *) stabstr_section->data; + stab_str = (char *) stab_section->link->data; } func_name[0] = '\0'; @@ -473,6 +486,7 @@ static void rt_error(ucontext_t *uc, const char *fmt, ...) va_list ap; addr_t pc; int i; + TCCState *s1 = get_s1_for_run(); fprintf(stderr, "Runtime error: "); va_start(ap, fmt); @@ -480,11 +494,14 @@ static void rt_error(ucontext_t *uc, const char *fmt, ...) va_end(ap); fprintf(stderr, "\n"); - for(i=0;irt_num_callers;i++) { if (rt_get_caller_pc(&pc, uc, i) < 0) break; - pc = rt_printline(pc, i ? "by" : "at"); - if (pc == (addr_t)rt_prog_main && pc) + pc = rt_printline(s1, pc, i ? "by" : "at"); + if (pc == (addr_t)s1->rt_prog_main && pc) break; } } @@ -496,6 +513,7 @@ static void rt_error(ucontext_t *uc, const char *fmt, ...) static void sig_error(int signum, siginfo_t *siginf, void *puc) { ucontext_t *uc = puc; + TCCState *s1; switch(signum) { case SIGFPE: @@ -511,8 +529,9 @@ static void sig_error(int signum, siginfo_t *siginf, void *puc) break; case SIGBUS: case SIGSEGV: - if (rt_bound_error_msg && *rt_bound_error_msg) - rt_error(uc, *rt_bound_error_msg); + s1 = get_s1_for_run(); + if (s1 && s1->rt_bound_error_msg && *s1->rt_bound_error_msg) + rt_error(uc, *s1->rt_bound_error_msg); else rt_error(uc, "dereferencing invalid pointer"); break; @@ -728,10 +747,12 @@ static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info) { EXCEPTION_RECORD *er = ex_info->ExceptionRecord; CONTEXT *uc = ex_info->ContextRecord; + TCCState *s1; switch (er->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: - if (rt_bound_error_msg && *rt_bound_error_msg) - rt_error(uc, *rt_bound_error_msg); + s1 = get_s1_for_run(); + if (s1 && s1->rt_bound_error_msg && *s1->rt_bound_error_msg) + rt_error(uc, *s1->rt_bound_error_msg); else rt_error(uc, "access violation"); break; diff --git a/tcctools.c b/tcctools.c index 1d4424ea..d696d66b 100644 --- a/tcctools.c +++ b/tcctools.c @@ -430,7 +430,7 @@ the_end: #if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64 -ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option) +ST_FUNC void tcc_tool_cross(TCCState *s1, char **argv, int option) { tcc_error("-m%d not implemented.", option); } @@ -479,7 +479,7 @@ static int execvp_win32(const char *prog, char **argv) #define execvp execvp_win32 #endif /* _WIN32 */ -ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int target) +ST_FUNC void tcc_tool_cross(TCCState *s1, char **argv, int target) { char program[4096]; char *a0 = argv[0]; @@ -515,7 +515,7 @@ int _dowildcard = 1; /* -------------------------------------------------------------- */ /* generate xxx.d file */ -ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename) +ST_FUNC void gen_makedeps(TCCState *s1, const char *target, const char *filename) { FILE *depout; char buf[1024]; @@ -528,7 +528,7 @@ ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename) filename = buf; } - if (s->verbose) + if (s1->verbose) printf("<- %s\n", filename); /* XXX return err codes instead of error() ? */ @@ -537,8 +537,8 @@ ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename) tcc_error("could not open '%s'", filename); fprintf(depout, "%s: \\\n", target); - for (i=0; inb_target_deps; ++i) - fprintf(depout, " %s \\\n", s->target_deps[i]); + for (i=0; inb_target_deps; ++i) + fprintf(depout, " %s \\\n", s1->target_deps[i]); fprintf(depout, "\n"); fclose(depout); } diff --git a/tests/Makefile b/tests/Makefile index 88c5879e..4d9a6f61 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -12,6 +12,7 @@ TESTS = \ hello-exe \ hello-run \ libtest \ + libtest_mt \ test3 \ memtest \ dlltest \ @@ -71,11 +72,11 @@ hello-run: ../examples/ex1.c @echo ------------ $@ ------------ $(TCC) -run $< || $(DUMPTCC) -libtest: libtcc_test$(EXESUF) +libtes%: libtcc_tes%$(EXESUF) @echo ------------ $@ ------------ - ./libtcc_test$(EXESUF) $(TCCFLAGS) + ./libtcc_tes$*$(EXESUF) $(TCCFLAGS) -libtcc_test$(EXESUF): libtcc_test.c $(LIBTCC) +libtcc_tes%$(EXESUF): libtcc_tes%.c $(LIBTCC) $(CC) -o $@ $^ $(CFLAGS) $(LIBS) %-dir: @@ -283,7 +284,7 @@ clean: rm -f *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.cc *.gcc rm -f *-cc *-gcc *-tcc *.exe hello libtcc_test vla_test tcctest[1234] rm -f asm-c-connect$(EXESUF) asm-c-connect-sep$(EXESUF) - rm -f ex? tcc_g weaktest.*.txt *.def + rm -f ex? tcc_g weaktest.*.txt *.def libtcc_test_mt @$(MAKE) -C tests2 $@ @$(MAKE) -C pp $@ diff --git a/tests/libtcc_test_mt.c b/tests/libtcc_test_mt.c new file mode 100644 index 00000000..cebdec36 --- /dev/null +++ b/tests/libtcc_test_mt.c @@ -0,0 +1,292 @@ +/* + * Multi-thread Test for libtcc + */ + +#ifndef FIB +#include +#include +#include +#include "libtcc.h" + +#define M 20 /* number of states */ +#define F(n) (n % 20 + 2) /* fib argument */ + +#ifdef _WIN32 +#include +#define TF_TYPE(func, param) DWORD WINAPI func(void *param) +typedef TF_TYPE(ThreadFunc, x); +HANDLE hh[M]; +void create_thread(ThreadFunc f, int n) +{ + DWORD tid; + hh[n] = CreateThread(NULL, 0, f, (void*)(size_t)n, 0, &tid); +} +void wait_threads(int n) +{ + WaitForMultipleObjects(n, hh, TRUE, INFINITE); + while (n) + CloseHandle(hh[--n]); +} +void sleep_ms(unsigned n) +{ + Sleep(n); +} +#else +#include +#define TF_TYPE(func, param) void* func(void *param) +typedef TF_TYPE(ThreadFunc, x); +pthread_t hh[M]; +void create_thread(ThreadFunc f, int n) +{ + pthread_create(&hh[n], NULL, f, (void*)(size_t)n); +} +void wait_threads(int n) +{ + while (n) + pthread_join(hh[--n], NULL); + +} +void sleep_ms(unsigned n) +{ + usleep(n * 1000); +} +#endif + +void handle_error(void *opaque, const char *msg) +{ + fprintf(opaque, "%s\n", msg); +} + +/* this function is called by the generated code */ +int add(int a, int b) +{ + return a + b; +} + +#define _str(s) #s +#define str(s) _str(s) +/* as a trick, prepend #line directive for better error/warning messages */ +#define PROG(lbl) \ + char lbl[] = "#line " str(__LINE__) " " str(__FILE__) "\n\n" + +PROG(my_program) +"#include \n" /* include the "Simple libc header for TCC" */ +"int add(int a, int b);\n" +"int fib(int n)\n" +"{\n" +" if (n <= 2)\n" +" return 1;\n" +" else\n" +" return add(fib(n-1),fib(n-2));\n" +"}\n" +"\n" +"int foo(int n)\n" +"{\n" +" printf(\" %d\", fib(n));\n" +" return 0;\n" +"# warning is this the correct file:line...\n" +"}\n"; + +int g_argc; char **g_argv; + +void parse_args(TCCState *s) +{ + int i; + /* if tcclib.h and libtcc1.a are not installed, where can we find them */ + for (i = 1; i < g_argc; ++i) { + char *a = g_argv[i]; + if (a[0] == '-') { + if (a[1] == 'B') + tcc_set_lib_path(s, a+2); + else if (a[1] == 'I') + tcc_add_include_path(s, a+2); + else if (a[1] == 'L') + tcc_add_library_path(s, a+2); + } + } +} + +TCCState *new_state(int w) +{ + TCCState *s = tcc_new(); + if (!s) { + fprintf(stderr, __FILE__ ": could not create tcc state\n"); + exit(1); + } + tcc_set_error_func(s, stdout, handle_error); + parse_args(s); + if (!w) tcc_set_options(s, "-w"); + tcc_set_output_type(s, TCC_OUTPUT_MEMORY); + return s; +} + +void *reloc_state(TCCState *s, const char *entry) +{ + void *func; + tcc_add_symbol(s, "add", add); + if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0) { + fprintf(stderr, __FILE__ ": could not relocate tcc state.\n"); + return NULL; + } + func = tcc_get_symbol(s, entry); + if (!func) + fprintf(stderr, __FILE__ ": could not get entry symbol.\n"); + return func; +} + +/* work with several states at the same time */ +int state_test(void) +{ + TCCState *s[M]; + int (*func[M])(int); + int n; + + for (n = 0; n < M + 4; ++n) { + unsigned a = n, b = n - 1, c = n - 2, d = n - 3, e = n - 4; + if (a < M) + s[a] = new_state(0); + if (b < M) + if (tcc_compile_string(s[b], my_program) == -1) + break; + if (c < M) + func[c] = reloc_state(s[c], "foo"); + if (d < M && func[d]) + func[d](F(d)); + if (e < M) + tcc_delete(s[e]); + } + return 0; +} + +/* simple compilation in threads */ +TF_TYPE(thread_test_simple, vn) +{ + TCCState *s; + int (*func)(int); + int ret; + int n = (size_t)vn; + + s = new_state(0); + sleep_ms(1); + ret = tcc_compile_string(s, my_program); + sleep_ms(1); + if (ret >= 0) { + func = reloc_state(s, "foo"); + if (func) + func(F(n)); + } + tcc_delete(s); + return 0; +} + +/* more complex compilation in threads */ +TF_TYPE(thread_test_complex, vn) +{ + TCCState *s; + int ret; + int n = (size_t)vn; + char *argv[30], b[10]; + int argc = 0, i; + + sprintf(b, "%d", F(n)); + + argv[argc++] = "../tcc.c"; + for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i]; +#if 0 + argv[argc++] = "-run"; + argv[argc++] = "../tcc.c"; + for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i]; +#endif + argv[argc++] = "-g"; + argv[argc++] = "-DFIB"; + argv[argc++] = "-run"; + argv[argc++] = __FILE__; + argv[argc++] = b; + argv[argc] = NULL; + + s = new_state(1); + sleep_ms(1); + ret = tcc_add_file(s, argv[0]); + sleep_ms(1); + if (ret >= 0) + tcc_run(s, argc, argv); + tcc_delete(s); + return 0; +} + +void time_tcc(int n) +{ + TCCState *s; + int ret; + while (--n >= 0) { + s = new_state(1); + ret = tcc_add_file(s, "../tcc.c"); + tcc_delete(s); + if (ret < 0) + break; + } +} + +static unsigned getclock_ms(void) +{ +#ifdef _WIN32 + return GetTickCount(); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec*1000 + (tv.tv_usec+500)/1000; +#endif +} + +int main(int argc, char **argv) +{ + int n; + unsigned t; + + g_argc = argc; + g_argv = argv; + +#if 1 + printf("----- libtest : mixed calls -------\n"), fflush(stdout); + t = getclock_ms(); + state_test(); + printf("\n(%u ms)\n", getclock_ms() - t); +#endif +#if 1 + printf("----- libtest : threads ------------\n"), fflush(stdout); + t = getclock_ms(); + for (n = 0; n < M; ++n) + create_thread(thread_test_simple, n); + wait_threads(n); + printf("\n(%u ms)\n", getclock_ms() - t); +#endif +#if 1 + printf("----- libtest : tcc in threads -----\n"), fflush(stdout); + t = getclock_ms(); + for (n = 0; n < M; ++n) + create_thread(thread_test_complex, n); + wait_threads(n); + printf("\n(%u ms)\n", getclock_ms() - t); +#endif +#if 1 + printf("----- compilation of tcc -----------\n"), fflush(stdout); + t = getclock_ms(); + time_tcc(10); + printf("(%u ms)\n", (getclock_ms() - t) / 10), fflush(stdout); +#endif + return 0; +} + +#else +#include +int fib(n) +{ + return (n <= 2) ? 1 : fib(n-1) + fib(n-2); +} + +int main(int argc, char **argv) +{ + printf(" %d", fib(atoi(argv[1]), 2)); + return 0; +} +#endif diff --git a/x86_64-gen.c b/x86_64-gen.c index ce920d1b..a2b260e9 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -105,6 +105,7 @@ enum { /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ +#define USING_GLOBALS #include "tcc.h" #include @@ -1024,7 +1025,7 @@ void gfunc_call(int nb_args) if ((vtop->r & VT_SYM) && vtop->sym->v == TOK_alloca) { /* need to add the "func_scratch" area after alloca */ - o(0x48); func_alloca = oad(0x2d, func_alloca); /* sub $NN, %rax */ + o(0x48); func_alloca = oad(0x05, func_alloca); /* sub $NN, %rax */ } /* other compilers don't clear the upper bits when returning char/short */ diff --git a/x86_64-link.c b/x86_64-link.c index f5840655..61c2d1b0 100644 --- a/x86_64-link.c +++ b/x86_64-link.c @@ -52,8 +52,6 @@ int code_reloc (int reloc_type) case R_X86_64_JUMP_SLOT: return 1; } - - tcc_error ("Unknown relocation type: %d", reloc_type); return -1; } @@ -95,7 +93,6 @@ int gotplt_entry_type (int reloc_type) return ALWAYS_GOTPLT_ENTRY; } - tcc_error ("Unknown relocation type: %d", reloc_type); return -1; }