From 2b0a663df9236763c3967575e2c0fb89a9e58566 Mon Sep 17 00:00:00 2001 From: grischka Date: Mon, 11 Mar 2024 11:53:46 +0100 Subject: [PATCH] libtcc usability improvements - tccgen.c: cleanup switch data etc. after errors (*) - tccpe.c: faster get_dllexports (*) - tccpe.c: support -Wl,-e[ntry]=... (*) - libtcc.c: win32: use ANSI functions (GetModuleFileNameA etc.) - tccrun.c: be nice to tcc-0.9.26 ("struct/enum already defined") - tccpp.c: be nice to tcc-0.9.27's va_start/end macros (*) suggested by Robert Schlicht https://lists.gnu.org/archive/html/tinycc-devel/2024-03/msg00012.html --- libtcc.c | 11 +++---- tccgen.c | 36 +++++++++++++++------- tccpe.c | 75 +++++++++++++++++++++++++-------------------- tccpp.c | 11 +++---- tccrun.c | 4 +-- tests/tcctest.c | 5 ++- win32/build-tcc.bat | 3 ++ 7 files changed, 83 insertions(+), 62 deletions(-) diff --git a/libtcc.c b/libtcc.c index f8e0e3377..9d4fdac04 100644 --- a/libtcc.c +++ b/libtcc.c @@ -101,7 +101,7 @@ BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved) static inline char *config_tccdir_w32(char *path) { char *p; - GetModuleFileName(tcc_module, path, MAX_PATH); + GetModuleFileNameA(tcc_module, path, MAX_PATH); p = tcc_basename(normalize_slashes(strlwr(path))); if (p > path) --p; @@ -115,7 +115,7 @@ static inline char *config_tccdir_w32(char *path) static void tcc_add_systemdir(TCCState *s) { char buf[1000]; - GetSystemDirectory(buf, sizeof buf); + GetSystemDirectoryA(buf, sizeof buf); tcc_add_library_path(s, normalize_slashes(buf)); } #endif @@ -801,14 +801,11 @@ LIBTCCAPI TCCState *tcc_new(void) TCCState *s; s = tcc_mallocz(sizeof(TCCState)); - if (!s) - return NULL; #ifdef MEM_DEBUG tcc_memcheck(1); #endif #undef gnu_ext - s->gnu_ext = 1; s->tcc_ext = 1; s->nocommon = 1; @@ -874,11 +871,13 @@ LIBTCCAPI void tcc_delete(TCCState *s1) cstr_free(&s1->cmdline_defs); cstr_free(&s1->cmdline_incl); cstr_free(&s1->linker_arg); + tcc_free(s1->dState); #ifdef TCC_IS_NATIVE /* free runtime memory */ tcc_run_free(s1); #endif - tcc_free(s1->dState); + /* free loaded dlls array */ + dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); tcc_free(s1); #ifdef MEM_DEBUG tcc_memcheck(-1); diff --git a/tccgen.c b/tccgen.c index 791c5c6d6..9da4a028c 100644 --- a/tccgen.c +++ b/tccgen.c @@ -157,6 +157,7 @@ static void gv_dup(void); static int get_temp_local_var(int size,int align); static void clear_temp_local_var_list(); static void cast_error(CType *st, CType *dt); +static void end_switch(void); /* ------------------------------------------------------------------------- */ /* Automagical code suppression */ @@ -381,12 +382,10 @@ ST_FUNC void tccgen_init(TCCState *s1) ST_FUNC int tccgen_compile(TCCState *s1) { - cur_text_section = NULL; funcname = ""; func_ind = -1; anon_sym = SYM_FIRST_ANOM; nocode_wanted = DATA_ONLY_WANTED; /* no code outside of functions */ - local_scope = 0; debug_modes = (s1->do_debug ? 1 : 0) | s1->test_coverage << 1; tcc_debug_start(s1); @@ -418,10 +417,19 @@ ST_FUNC void tccgen_finish(TCCState *s1) free_defines(NULL); /* free sym_pools */ dynarray_reset(&sym_pools, &nb_sym_pools); - sym_free_first = NULL; - global_label_stack = local_label_stack = NULL; cstr_free(&initstr); dynarray_reset(&stk_data, &nb_stk_data); + while (cur_switch) + end_switch(); + local_scope = 0; + loop_scope = NULL; + all_cleanups = NULL; + pending_gotos = NULL; + nb_temp_local_vars = 0; + global_label_stack = NULL; + local_label_stack = NULL; + cur_text_section = NULL; + sym_free_first = NULL; } /* ------------------------------------------------------------------------- */ @@ -6754,6 +6762,14 @@ static void gcase(struct case_t **base, int len, int *bsym) *bsym = gjmp(*bsym); } +static void end_switch(void) +{ + struct switch_t *sw = cur_switch; + dynarray_reset(&sw->p, &sw->n); + cur_switch = sw->prev; + tcc_free(sw); +} + /* ------------------------------------------------------------------------- */ /* __attribute__((cleanup(fn))) */ @@ -7154,15 +7170,14 @@ static void block(int flags) skip_switch: /* break label */ gsym(a); - - dynarray_reset(&sw->p, &sw->n); - cur_switch = sw->prev; - tcc_free(sw); + end_switch(); } else if (t == TOK_CASE) { - struct case_t *cr = tcc_malloc(sizeof(struct case_t)); + struct case_t *cr; if (!cur_switch) expect("switch"); + cr = tcc_malloc(sizeof(struct case_t)); + dynarray_add(&cur_switch->p, &cur_switch->n, cr); cr->v1 = cr->v2 = expr_const64(); if (gnu_ext && tok == TOK_DOTS) { next(); @@ -7174,7 +7189,6 @@ static void block(int flags) /* case and default are unreachable from a switch under nocode_wanted */ if (!cur_switch->nocode_wanted) cr->sym = gind(); - dynarray_add(&cur_switch->p, &cur_switch->n, cr); skip(':'); goto block_after_label; @@ -8574,9 +8588,9 @@ static int decl(int l) fn = tcc_malloc(sizeof *fn + strlen(file->filename)); strcpy(fn->filename, file->filename); fn->sym = sym; - skip_or_save_block(&fn->func_str); dynarray_add(&tcc_state->inline_fns, &tcc_state->nb_inline_fns, fn); + skip_or_save_block(&fn->func_str); } else { /* compute text section */ cur_text_section = ad.section; diff --git a/tccpe.c b/tccpe.c index 020f359f5..60a8efcfd 100644 --- a/tccpe.c +++ b/tccpe.c @@ -921,7 +921,7 @@ static void pe_build_imports(struct pe_info *pe) if (pe->type == PE_RUN) { if (dllref) { if ( !dllref->handle ) - dllref->handle = LoadLibrary(dllref->name); + dllref->handle = LoadLibraryA(dllref->name); v = (ADDR3264)GetProcAddress(dllref->handle, ordinal?(char*)0+ordinal:name); } if (!v) @@ -1600,14 +1600,15 @@ static int read_mem(int fd, unsigned offset, void *buffer, unsigned len) static int get_dllexports(int fd, char **pp) { - int l, i, n, n0, ret; + int i, k, l, n, n0, ret; char *p; IMAGE_SECTION_HEADER ish; IMAGE_EXPORT_DIRECTORY ied; IMAGE_DOS_HEADER dh; IMAGE_FILE_HEADER ih; - DWORD sig, ref, addr, ptr, namep; + DWORD sig, ref, addr; + DWORD *namep = NULL, p0 = 0, p1; int pef_hdroffset, opt_hdroffset, sec_hdroffset; @@ -1652,33 +1653,37 @@ static int get_dllexports(int fd, char **pp) goto found; } goto the_end_0; - found: ref = ish.VirtualAddress - ish.PointerToRawData; if (!read_mem(fd, addr - ref, &ied, sizeof ied)) goto the_end; - - namep = ied.AddressOfNames - ref; - for (i = 0; i < ied.NumberOfNames; ++i) { - if (!read_mem(fd, namep, &ptr, sizeof ptr)) + k = ied.NumberOfNames; + if (k) { + namep = tcc_malloc(l = k * sizeof *namep); + if (!read_mem(fd, ied.AddressOfNames - ref, namep, l)) goto the_end; - namep += sizeof ptr; - for (l = 0;;) { - if (n+1 >= n0) - p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256); - if (!read_mem(fd, ptr - ref + l++, p + n, 1)) { - tcc_free(p), p = NULL; - goto the_end; - } - if (p[n++] == 0) - break; + for (i = l = 0; i < k; ++i) { + p1 = namep[i] - ref; + if (p1 != p0) + lseek(fd, p0 = p1, SEEK_SET), l = 0; + do { + if (0 == l) { + if (n + 1000 >= n0) + p = tcc_realloc(p, n0 += 1000); + if ((l = read(fd, p + n, 1000 - 1)) <= 0) + goto the_end; + } + --l, ++p0; + } while (p[n++]); } - } - if (p) p[n] = 0; + } the_end_0: ret = 0; the_end: + tcc_free(namep); + if (ret && p) + tcc_free(p), p = NULL; *pp = p; return ret; } @@ -1810,15 +1815,14 @@ static int pe_load_def(TCCState *s1, int fd) static int pe_load_dll(TCCState *s1, int fd, const char *filename) { char *p, *q; - int index, ret; - - ret = get_dllexports(fd, &p); - if (ret) { + DLLReference *ref = tcc_add_dllref(s1, filename, 0); + if (ref->found) + return 0; + if (get_dllexports(fd, &p)) return -1; - } else if (p) { - index = tcc_add_dllref(s1, filename, 0)->index; + if (p) { for (q = p; *q; q += 1 + strlen(q)) - pe_putimport(s1, index, q, 0); + pe_putimport(s1, ref->index, q, 0); tcc_free(p); } return 0; @@ -1941,15 +1945,20 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) start_symbol = "__start"; run_symbol = "__runmain"; pe_type = PE_EXE; - + if (s1->pe_subsystem == 2) + pe_type = PE_GUI; } + if (TCC_OUTPUT_MEMORY == s1->output_type && !s1->nostdlib) start_symbol = run_symbol; } - - pe->start_symbol = start_symbol + 1; - if (!s1->leading_underscore || strchr(start_symbol, '@')) - ++start_symbol; + if (s1->elf_entryname) { + pe->start_symbol = start_symbol = s1->elf_entryname; + } else { + pe->start_symbol = start_symbol + 1; + if (!s1->leading_underscore || strchr(start_symbol, '@')) + ++start_symbol; + } #ifdef CONFIG_TCC_BACKTRACE if (s1->do_backtrace) { @@ -2055,8 +2064,8 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) #ifdef CONFIG_TCC_BCHECK tcc_add_bcheck(s1); #endif - tcc_add_pragma_libs(s1); pe_add_runtime(s1, &pe); + tcc_add_pragma_libs(s1); resolve_common_syms(s1); pe_set_options(s1, &pe); pe_check_symbols(&pe); diff --git a/tccpp.c b/tccpp.c index 1c6b5c7d2..d9d2bbc31 100644 --- a/tccpp.c +++ b/tccpp.c @@ -3547,11 +3547,7 @@ static void putdefs(CString *cs, const char *p) static void tcc_predefs(TCCState *s1, CString *cs, int is_asm) { - int a, b, c; - - sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c); - cstr_printf(cs, "#define __TINYC__ %d\n", a*10000 + b*100 + c); - + cstr_printf(cs, "#define __TINYC__ 9%.2s\n", TCC_VERSION + 4); putdefs(cs, target_machine_defs); putdefs(cs, target_os_defs); @@ -3742,7 +3738,10 @@ static void tok_print(const int *str, const char *msg, ...) va_list ap; int t, t0, s; CValue cval; - va_start(ap, msg), vfprintf(fp, msg, ap), va_end(ap); + + va_start(ap, msg); + vfprintf(fp, msg, ap); + va_end(ap); s = t0 = 0; while (str) { diff --git a/tccrun.c b/tccrun.c index 56ddcc202..b0cb4dba9 100644 --- a/tccrun.c +++ b/tccrun.c @@ -179,8 +179,6 @@ ST_FUNC void tcc_run_free(TCCState *s1) dlclose(ref->handle); #endif } - /* free loaded dlls array */ - dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); /* unmap or unprotect and free memory */ ptr = s1->run_ptr; if (NULL == ptr) @@ -854,7 +852,7 @@ static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc, bt_info *bi) char *dirs[DIR_TABLE_SIZE]; #endif unsigned int filename_size; - struct dwarf_filename_struct { + struct /*dwarf_filename_struct*/ { unsigned int dir_entry; char *name; } filename_table[FILE_TABLE_SIZE]; diff --git a/tests/tcctest.c b/tests/tcctest.c index d46ec7abe..531bb67f4 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -3760,14 +3760,13 @@ void asm_dot_test(void) void asm_pcrel_test(void) { -#if defined(__i386__) unsigned o1, o2; /* subtract text-section label from forward or other-section label */ asm("1: mov $2f-1b,%%eax; mov %%eax,%0" : "=m"(o1)); /* verify ... */ - asm("2: mov $2b,%%eax; sub $1b,%%eax; mov %%eax,%0" : "=m"(o2)); + asm("2: lea 2b"RX",%eax; lea 1b"RX",%ecx; sub %ecx,%eax"); + asm("mov %%eax,%0" : "=m"(o2)); printf("%s : %x\n", __FUNCTION__, o1 - o2); /* should be zero */ -#endif } void asm_test(void) diff --git a/win32/build-tcc.bat b/win32/build-tcc.bat index d215e3a8c..bcf366659 100644 --- a/win32/build-tcc.bat +++ b/win32/build-tcc.bat @@ -137,6 +137,7 @@ for %%f in (*tcc.exe *tcc.dll) do @del %%f @if _%TCC_C%_==__ goto compiler_2parts @rem if TCC_C was defined then build only tcc.exe %CC% -o tcc.exe %TCC_C% %D% +@if errorlevel 1 goto :the_end @goto :compiler_done :compiler_2parts @@ -144,8 +145,10 @@ for %%f in (*tcc.exe *tcc.dll) do @del %%f %CC% -o libtcc.dll -shared %LIBTCC_C% %D% -DLIBTCC_AS_DLL @if errorlevel 1 goto :the_end %CC% -o tcc.exe ..\tcc.c libtcc.dll %D% -DONE_SOURCE"=0" +@if errorlevel 1 goto :the_end if not _%XCC%_==_yes_ goto :compiler_done %CC% -o %PX%-tcc.exe ..\tcc.c %DX% +@if errorlevel 1 goto :the_end :compiler_done @if (%EXES_ONLY%)==(yes) goto :files_done