From 37b034899318a4e0f2283aa6e8564d839a52503f Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Tue, 11 Jun 2013 18:13:04 +0200 Subject: Define __ARM_PCS_VFP in hardfloat compilation mode --- libtcc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'libtcc.c') diff --git a/libtcc.c b/libtcc.c index f691218..b10a2a7 100644 --- a/libtcc.c +++ b/libtcc.c @@ -950,6 +950,9 @@ LIBTCCAPI TCCState *tcc_new(void) tcc_define_symbol(s, "__arm", NULL); tcc_define_symbol(s, "arm", NULL); tcc_define_symbol(s, "__APCS_32__", NULL); +#if defined(TCC_ARM_HARDFLOAT) + tcc_define_symbol(s, "__ARM_PCS_VFP", NULL); +#endif #endif #ifdef TCC_TARGET_PE -- cgit v1.3.1 From 73faaea227a53e365dd75f1dba7a5071c7b5e541 Mon Sep 17 00:00:00 2001 From: grischka Date: Wed, 28 Aug 2013 22:55:05 +0200 Subject: i386-gen: preserve fp control word in gen_cvt_ftoi - Use runtime function for conversion - Also initialize fp with tcc -run on windows This fixes a bug where double x = 1.0; double y = 1.0000000000000001; double z = x < y ? 0 : sqrt (x*x - y*y); caused a bad sqrt because rounding precision for the x < y comparison was different to the one used within the sqrt function. This also fixes a bug where printf("%d, %d", (int)pow(10, 2), (int)pow(10, 2)); would print 100, 99 Unrelated: win32: document relative include & lib lookup win32: normalize_slashes: do not mirror silly gcc behavior This reverts part of commit 8a81f9e1036637e21a47e14fb56bf64133546890 winapi: add missing WINAPI decl. for some functions --- i386-gen.c | 91 +++++++++++++----------------------------- lib/libtcc1.c | 23 ++++++++--- libtcc.c | 15 ++----- tcc.h | 1 + tccpe.c | 22 +++------- tccrun.c | 2 +- tcctok.h | 4 +- win32/include/winapi/winbase.h | 12 +++--- win32/lib/crt1.c | 6 +++ win32/lib/wincrt1.c | 2 +- win32/tcc-win32.txt | 6 +++ 11 files changed, 77 insertions(+), 107 deletions(-) (limited to 'libtcc.c') diff --git a/i386-gen.c b/i386-gen.c index 844a482..0a6d4d3 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -338,6 +338,15 @@ static void gadd_sp(int val) } } +static void gen_static_call(int v) +{ + Sym *sym; + + sym = external_global_sym(v, &func_old_type, 0); + oad(0xe8, -4); + greloc(cur_text_section, sym, ind-4, R_386_PC32); +} + /* 'is_jmp' is '1' if it is a jump */ static void gcall_or_jmp(int is_jmp) { @@ -570,6 +579,12 @@ ST_FUNC void gfunc_prolog(CType *func_type) func_bound_offset = lbounds_section->data_offset; } #endif + +#ifndef TCC_TARGET_PE + if (0 == strcmp(funcname, "main")) + gen_static_call(TOK___tcc_fpinit); +#endif + } /* generate function epilog */ @@ -582,7 +597,7 @@ ST_FUNC void gfunc_epilog(void) && func_bound_offset != lbounds_section->data_offset) { int saved_ind; int *bounds_ptr; - Sym *sym, *sym_data; + Sym *sym_data; /* add end of table info */ bounds_ptr = section_ptr_add(lbounds_section, sizeof(int)); *bounds_ptr = 0; @@ -594,20 +609,16 @@ ST_FUNC void gfunc_epilog(void) greloc(cur_text_section, sym_data, ind + 1, R_386_32); oad(0xb8, 0); /* mov %eax, xxx */ - sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0); - greloc(cur_text_section, sym, - ind + 1, R_386_PC32); - oad(0xe8, -4); + gen_static_call(TOK___bound_local_new); + ind = saved_ind; /* generate bound check local freeing */ o(0x5250); /* save returned value, if any */ greloc(cur_text_section, sym_data, ind + 1, R_386_32); oad(0xb8, 0); /* mov %eax, xxx */ - sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0); - greloc(cur_text_section, sym, - ind + 1, R_386_PC32); - oad(0xe8, -4); + gen_static_call(TOK___bound_local_delete); + o(0x585a); /* restore returned value, if any */ } #endif @@ -626,10 +637,8 @@ ST_FUNC void gfunc_epilog(void) ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; #ifdef TCC_TARGET_PE if (v >= 4096) { - Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0); oad(0xb8, v); /* mov stacksize, %eax */ - oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */ - greloc(cur_text_section, sym, ind-4, R_386_PC32); + gen_static_call(TOK___chkstk); /* call __chkstk, (does the stackframe too) */ } else #endif { @@ -992,52 +1001,13 @@ ST_FUNC void gen_cvt_itof(int t) /* XXX: handle long long case */ ST_FUNC void gen_cvt_ftoi(int t) { - int r, r2, size; - Sym *sym; - CType ushort_type; - - ushort_type.t = VT_SHORT | VT_UNSIGNED; - ushort_type.ref = 0; - gv(RC_FLOAT); - if (t != VT_INT) - size = 8; - else - size = 4; - - o(0x2dd9); /* ldcw xxx */ - sym = external_global_sym(TOK___tcc_int_fpu_control, - &ushort_type, VT_LVAL); - greloc(cur_text_section, sym, - ind, R_386_32); - gen_le32(0); - - oad(0xec81, size); /* sub $xxx, %esp */ - if (size == 4) - o(0x1cdb); /* fistpl */ - else - o(0x3cdf); /* fistpll */ - o(0x24); - o(0x2dd9); /* ldcw xxx */ - sym = external_global_sym(TOK___tcc_fpu_control, - &ushort_type, VT_LVAL); - greloc(cur_text_section, sym, - ind, R_386_32); - gen_le32(0); - - r = get_reg(RC_INT); - o(0x58 + r); /* pop r */ - if (size == 8) { - if (t == VT_LLONG) { - vtop->r = r; /* mark reg as used */ - r2 = get_reg(RC_INT); - o(0x58 + r2); /* pop r2 */ - vtop->r2 = r2; - } else { - o(0x04c483); /* add $4, %esp */ - } - } - vtop->r = r; + save_reg(TREG_EAX); + save_reg(TREG_EDX); + gen_static_call(TOK___tcc_cvt_ftol); + vtop->r = TREG_EAX; /* mark reg as used */ + if (t == VT_LLONG) + vtop->r2 = TREG_EDX; } /* convert from one floating point type to another */ @@ -1060,18 +1030,13 @@ ST_FUNC void ggoto(void) /* generate a bounded pointer addition */ ST_FUNC void gen_bounded_ptr_add(void) { - Sym *sym; - /* prepare fast i386 function call (args in eax and edx) */ gv2(RC_EAX, RC_EDX); /* save all temporary registers */ vtop -= 2; save_regs(0); /* do a fast function call */ - sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0); - greloc(cur_text_section, sym, - ind + 1, R_386_PC32); - oad(0xe8, -4); + gen_static_call(TOK___bound_ptr_add); /* returned pointer is in eax */ vtop++; vtop->r = TREG_EAX | VT_BOUNDED; diff --git a/lib/libtcc1.c b/lib/libtcc1.c index 53dbec4..a94a82d 100644 --- a/lib/libtcc1.c +++ b/lib/libtcc1.c @@ -478,13 +478,24 @@ long long __ashldi3(long long a, int b) #endif } -#if defined(__i386__) -/* FPU control word for rounding to nearest mode */ -unsigned short __tcc_fpu_control = 0x137f; -/* FPU control word for round to zero mode for int conversion */ -unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00; +#ifndef _WIN32 +void __tcc_fpinit(void) +{ + unsigned c = 0x137F; + __asm__ __volatile__ ("fldcw %0" : "=m" (c)); +} #endif - +long long __tcc_cvt_ftol(long double x) +{ + unsigned c0, c1; + long long ret; + __asm__ __volatile__ ("fnstcw %0" : "=m" (c0)); + c1 = c0 | 0x0C00; + __asm__ __volatile__ ("fldcw %0" : "=m" (c1)); + __asm__ __volatile__ ("fistpll %0" : "=m" (ret)); + __asm__ __volatile__ ("fldcw %0" : "=m" (c0)); + return ret; +} #endif /* !__x86_64__ */ /* XXX: fix tcc's code generator to do this instead */ diff --git a/libtcc.c b/libtcc.c index b10a2a7..3b018ae 100644 --- a/libtcc.c +++ b/libtcc.c @@ -78,21 +78,13 @@ ST_FUNC void asm_global_instr(void) #endif /********************************************************/ - #ifdef _WIN32 -// GCC appears to use '/' for relative paths and '\\' for absolute paths on Windows static char *normalize_slashes(char *path) { char *p; - if (path[1] == ':') { - for (p = path+2; *p; ++p) - if (*p == '/') - *p = '\\'; - } else { - for (p = path; *p; ++p) - if (*p == '\\') - *p = '/'; - } + for (p = path; *p; ++p) + if (*p == '\\') + *p = '/'; return path; } @@ -1036,6 +1028,7 @@ LIBTCCAPI TCCState *tcc_new(void) #ifdef TCC_TARGET_I386 s->seg_size = 32; #endif + s->runtime_main = "main"; return s; } diff --git a/tcc.h b/tcc.h index 859d4fd..c988e4f 100644 --- a/tcc.h +++ b/tcc.h @@ -665,6 +665,7 @@ struct TCCState { #endif #ifdef TCC_IS_NATIVE + const char *runtime_main; /* for tcc_relocate */ void *runtime_mem; # ifdef HAVE_SELINUX diff --git a/tccpe.c b/tccpe.c index 72c1572..05fed09 100644 --- a/tccpe.c +++ b/tccpe.c @@ -1726,7 +1726,6 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack) static void pe_add_runtime(TCCState *s1, struct pe_info *pe) { const char *start_symbol; - ADDR3264 addr = 0; int pe_type = 0; if (find_elf_sym(symtab_section, PE_STDSYM("WinMain","@16"))) @@ -1742,16 +1741,13 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) start_symbol = TCC_OUTPUT_MEMORY == s1->output_type - ? PE_GUI == pe_type ? "__runwinmain" : "_main" + ? PE_GUI == pe_type ? "__runwinmain" : "__runmain" : PE_DLL == pe_type ? PE_STDSYM("__dllstart","@12") : PE_GUI == pe_type ? "__winstart" : "__start" ; - if (!s1->leading_underscore || strchr(start_symbol, '@')) { + if (!s1->leading_underscore || strchr(start_symbol, '@')) ++start_symbol; - if (start_symbol[0] != '_') - start_symbol = NULL; - } /* grab the startup code from libtcc1 */ if (start_symbol) @@ -1776,21 +1772,13 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) } } - if (TCC_OUTPUT_MEMORY == s1->output_type) + if (TCC_OUTPUT_MEMORY == s1->output_type) { pe_type = PE_RUN; - - if (start_symbol) { - addr = get_elf_sym_addr(s1, start_symbol, 1); - if (PE_RUN == pe_type && addr) - /* for -run GUI's, put '_runwinmain' instead of 'main' */ - add_elf_sym(symtab_section, - addr, 0, - ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, - text_section->sh_num, "main"); + s1->runtime_main = start_symbol; } pe->type = pe_type; - pe->start_addr = addr; + pe->start_addr = (DWORD)tcc_get_symbol_err(s1, start_symbol); } ST_FUNC int pe_output_file(TCCState * s1, const char *filename) diff --git a/tccrun.c b/tccrun.c index d858ae6..b07ab0f 100644 --- a/tccrun.c +++ b/tccrun.c @@ -97,7 +97,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0) return -1; - prog_main = tcc_get_symbol_err(s1, "main"); + prog_main = tcc_get_symbol_err(s1, s1->runtime_main); #ifdef CONFIG_TCC_BACKTRACE if (s1->do_debug) { diff --git a/tcctok.h b/tcctok.h index fde13dd..9b47a60 100644 --- a/tcctok.h +++ b/tcctok.h @@ -194,8 +194,8 @@ DEF(TOK__remu, "_remu") #endif #ifdef TCC_TARGET_I386 - DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control") - DEF(TOK___tcc_fpu_control, "__tcc_fpu_control") + DEF(TOK___tcc_fpinit, "__tcc_fpinit") + DEF(TOK___tcc_cvt_ftol, "__tcc_cvt_ftol") #endif #ifdef TCC_ARM_EABI DEF(TOK___ashrdi3, "__aeabi_lasr") diff --git a/win32/include/winapi/winbase.h b/win32/include/winapi/winbase.h index a5d9b17..4a38006 100644 --- a/win32/include/winapi/winbase.h +++ b/win32/include/winapi/winbase.h @@ -968,15 +968,15 @@ extern "C" { LONG64 InterlockedExchangeAdd64(LONG64 volatile *Addend,LONG64 Value); LONG64 InterlockedCompareExchange64(LONG64 volatile *Destination,LONG64 ExChange,LONG64 Comperand); #else - LONG InterlockedIncrement(LONG volatile *lpAddend); - LONG InterlockedDecrement(LONG volatile *lpAddend); - LONG InterlockedExchange(LONG volatile *Target,LONG Value); + LONG WINAPI InterlockedIncrement(LONG volatile *lpAddend); + LONG WINAPI InterlockedDecrement(LONG volatile *lpAddend); + LONG WINAPI InterlockedExchange(LONG volatile *Target,LONG Value); #define InterlockedExchangePointer(Target,Value) (PVOID)InterlockedExchange((PLONG)(Target),(LONG)(Value)) - LONG InterlockedExchangeAdd(LONG volatile *Addend,LONG Value); - LONG InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange,LONG Comperand); - LONGLONG InterlockedCompareExchange64(LONGLONG volatile *Destination,LONGLONG Exchange,LONGLONG Comperand); + LONG WINAPI InterlockedExchangeAdd(LONG volatile *Addend,LONG Value); + LONG WINAPI InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange,LONG Comperand); + LONGLONG WINAPI InterlockedCompareExchange64(LONGLONG volatile *Destination,LONGLONG Exchange,LONGLONG Comperand); __CRT_INLINE LONGLONG InterlockedAnd64 (LONGLONG volatile *Destination,LONGLONG Value) { LONGLONG Old; diff --git a/win32/lib/crt1.c b/win32/lib/crt1.c index 3e1d17f..cde3910 100644 --- a/win32/lib/crt1.c +++ b/win32/lib/crt1.c @@ -31,4 +31,10 @@ int _start(void) exit(ret); } +int _runmain(int argc, char **argv) +{ + _controlfp(0x10000, 0x30000); + return main(argc, argv, NULL); +} + // ============================================= diff --git a/win32/lib/wincrt1.c b/win32/lib/wincrt1.c index 77e74b8..663fd33 100644 --- a/win32/lib/wincrt1.c +++ b/win32/lib/wincrt1.c @@ -59,6 +59,6 @@ int _runwinmain(int argc, char **argv) szCmd = ""; else if (szCmd > p && szCmd[-1] == '\"') --szCmd; + _controlfp(0x10000, 0x30000); return WinMain(GetModuleHandle(NULL), NULL, szCmd, SW_SHOWDEFAULT); } - diff --git a/win32/tcc-win32.txt b/win32/tcc-win32.txt index dc06b8f..1cb35c5 100644 --- a/win32/tcc-win32.txt +++ b/win32/tcc-win32.txt @@ -18,6 +18,12 @@ system PATH. + Include and library search paths + -------------------------------- + On windows, the standard "include" and "lib" directories are searched + relatively from the location of the executables (tcc.exe, libtcc.dll). + + Examples: --------- Open a console window (DOS box) and 'cd' to the examples directory. -- cgit v1.3.1 From 45b35a3d66ee95e2526bf609cc88c4b4b21ac175 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 23 Sep 2013 09:40:06 +0200 Subject: set the user-defined library search paths first --- libtcc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'libtcc.c') diff --git a/libtcc.c b/libtcc.c index 3b018ae..f841eb0 100644 --- a/libtcc.c +++ b/libtcc.c @@ -989,8 +989,6 @@ LIBTCCAPI TCCState *tcc_new(void) /* glibc defines */ tcc_define_symbol(s, "__REDIRECT(name, proto, alias)", "name proto __asm__ (#alias)"); tcc_define_symbol(s, "__REDIRECT_NTH(name, proto, alias)", "name proto __asm__ (#alias) __THROW"); - /* default library paths */ - tcc_add_library_path(s, CONFIG_TCC_LIBPATHS); /* paths for crt objects */ tcc_split_path(s, (void ***)&s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX); #endif @@ -1343,8 +1341,8 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) put_stabs("", 0, 0, 0, 0); } -#ifdef TCC_TARGET_PE tcc_add_library_path(s, CONFIG_TCC_LIBPATHS); +#ifdef TCC_TARGET_PE # ifdef _WIN32 tcc_add_systemdir(s); # endif -- cgit v1.3.1 From 1c4afd13501f07a673aed5f130166f2ee0f30927 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Tue, 29 Oct 2013 22:10:02 +0800 Subject: Add support for thread-local storage variables --- elf.h | 4 +++- libtcc.c | 5 ++++- tccelf.c | 29 +++++++++++++++++++++-------- tccgen.c | 29 +++++++++++++++++++++++++---- tcctok.h | 1 + 5 files changed, 54 insertions(+), 14 deletions(-) (limited to 'libtcc.c') diff --git a/elf.h b/elf.h index 2983c75..039a697 100644 --- a/elf.h +++ b/elf.h @@ -447,6 +447,7 @@ typedef struct #define STT_SECTION 3 /* Symbol associated with a section */ #define STT_FILE 4 /* Symbol's name is file name */ #define STT_NUM 5 /* Number of defined types. */ +#define STT_TLS 6 /* Symbol is a thread-local data object */ #define STT_GNU_IFUNC 10 /* Symbol is a indirect code object */ #define STT_LOOS 11 /* Start of OS-specific */ #define STT_HIOS 12 /* End of OS-specific */ @@ -555,7 +556,8 @@ typedef struct #define PT_NOTE 4 /* Auxiliary information */ #define PT_SHLIB 5 /* Reserved */ #define PT_PHDR 6 /* Entry for header table itself */ -#define PT_NUM 7 /* Number of defined types. */ +#define PT_TLS 7 /* Thread-local program segment */ +#define PT_NUM 8 /* Number of defined types. */ #define PT_LOOS 0x60000000 /* Start of OS-specific */ #define PT_HIOS 0x6fffffff /* End of OS-specific */ #define PT_LOPROC 0x70000000 /* Start of processor-specific */ diff --git a/libtcc.c b/libtcc.c index f841eb0..fbea50b 100644 --- a/libtcc.c +++ b/libtcc.c @@ -444,7 +444,10 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, } else if ((sym->type.t & VT_BTYPE) == VT_VOID) { sym_type = STT_NOTYPE; } else { - sym_type = STT_OBJECT; + if (section && section->sh_flags & SHF_TLS) + sym_type = STT_TLS; + else + sym_type = STT_OBJECT; } if (sym->type.t & VT_STATIC) diff --git a/tccelf.c b/tccelf.c index 8af4bb6..4602ce8 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1543,6 +1543,7 @@ static int elf_output_file(TCCState *s1, const char *filename) int fd, mode, ret; int *section_order; int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k; + int have_tls_section = 0; long long tmp; addr_t addr; Section *strsec, *s; @@ -1861,6 +1862,11 @@ static int elf_output_file(TCCState *s1, const char *filename) /* we output all sections if debug or object file */ s->sh_size = s->data_offset; } + /* if tls section we'll need to add one segment */ + if (s->sh_flags & SHF_TLS) { + have_tls_section = 1; + phnum++; + } } /* allocate program segment headers */ @@ -1904,12 +1910,16 @@ static int elf_output_file(TCCState *s1, const char *filename) if (interp) ph += 1 + HAVE_PHDR; - for(j = 0; j < 2; j++) { - ph->p_type = PT_LOAD; - if (j == 0) - ph->p_flags = PF_R | PF_X; + for(j = 0; j < 2 + have_tls_section; j++) { + if (j != 2) + ph->p_type = PT_LOAD; else - ph->p_flags = PF_R | PF_W; + ph->p_type = PT_TLS; + ph->p_flags = PF_R; + if (j == 0) + ph->p_flags |= PF_X; + else if (j == 1) + ph->p_flags |= PF_W; ph->p_align = s1->section_align; /* we do the following ordering: interp, symbol tables, @@ -1920,13 +1930,16 @@ static int elf_output_file(TCCState *s1, const char *filename) s = s1->sections[i]; /* compute if section should be included */ if (j == 0) { - if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != + if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS)) != SHF_ALLOC) continue; - } else { - if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != + } else if (j == 1) { + if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS)) != (SHF_ALLOC | SHF_WRITE)) continue; + } else { + if ((s->sh_flags & SHF_TLS) != SHF_TLS) + continue; } if (s == interp) { if (k != 0) diff --git a/tccgen.c b/tccgen.c index bab4f7c..bfe461f 100644 --- a/tccgen.c +++ b/tccgen.c @@ -31,6 +31,7 @@ ST_DATA int rsym, anon_sym, ind, loc; ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */ +ST_DATA Section *tdata_section, *tbss_section; /* thread-local storage sections */ 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 */ @@ -3092,6 +3093,10 @@ static int parse_btype(CType *type, AttributeDef *ad) t |= VT_INLINE; next(); break; + case TOK_THREAD: + t |= VT_TLS; + next(); + break; /* GNUC attribute */ case TOK_ATTRIBUTE1: @@ -5495,10 +5500,26 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, /* allocate symbol in corresponding section */ sec = ad->section; if (!sec) { - if (has_init) - sec = data_section; - else if (tcc_state->nocommon) - sec = bss_section; + if (has_init) { + if (type->t & VT_TLS) { + if (!tdata_section) + tdata_section = new_section(tcc_state, ".tdata", + SHT_PROGBITS, + SHF_ALLOC | SHF_WRITE | SHF_TLS); + sec = tdata_section; + } else + sec = data_section; + } + else if (tcc_state->nocommon) { + if (type->t & VT_TLS) { + if (!tbss_section) + tbss_section = new_section(tcc_state, ".tbss", + SHT_NOBITS, + SHF_ALLOC | SHF_WRITE | SHF_TLS); + sec = tbss_section; + } else + sec = bss_section; + } } if (sec) { data_offset = sec->data_offset; diff --git a/tcctok.h b/tcctok.h index 9b47a60..d55c9d7 100644 --- a/tcctok.h +++ b/tcctok.h @@ -10,6 +10,7 @@ DEF(TOK_FOR, "for") DEF(TOK_EXTERN, "extern") DEF(TOK_STATIC, "static") + DEF(TOK_THREAD, "__thread") DEF(TOK_UNSIGNED, "unsigned") DEF(TOK_GOTO, "goto") DEF(TOK_DO, "do") -- cgit v1.3.1 From cf02f920c148a77794b05ba09d73586e5f0b3601 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Sun, 3 Nov 2013 18:55:54 +0800 Subject: Revert "Add support for thread-local storage variables" TLS support in tinyCC is absolutely not ready: - segment register not select in load and store - no relocation added for computing offset of per-thread symbol - no support for TLS-specific relocations - no program header added as per Drepper document about TLS This reverts commit 1c4afd13501f07a673aed5f130166f2ee0f30927. --- elf.h | 4 +--- libtcc.c | 5 +---- tccelf.c | 29 ++++++++--------------------- tccgen.c | 29 ++++------------------------- tcctok.h | 1 - 5 files changed, 14 insertions(+), 54 deletions(-) (limited to 'libtcc.c') diff --git a/elf.h b/elf.h index 039a697..2983c75 100644 --- a/elf.h +++ b/elf.h @@ -447,7 +447,6 @@ typedef struct #define STT_SECTION 3 /* Symbol associated with a section */ #define STT_FILE 4 /* Symbol's name is file name */ #define STT_NUM 5 /* Number of defined types. */ -#define STT_TLS 6 /* Symbol is a thread-local data object */ #define STT_GNU_IFUNC 10 /* Symbol is a indirect code object */ #define STT_LOOS 11 /* Start of OS-specific */ #define STT_HIOS 12 /* End of OS-specific */ @@ -556,8 +555,7 @@ typedef struct #define PT_NOTE 4 /* Auxiliary information */ #define PT_SHLIB 5 /* Reserved */ #define PT_PHDR 6 /* Entry for header table itself */ -#define PT_TLS 7 /* Thread-local program segment */ -#define PT_NUM 8 /* Number of defined types. */ +#define PT_NUM 7 /* Number of defined types. */ #define PT_LOOS 0x60000000 /* Start of OS-specific */ #define PT_HIOS 0x6fffffff /* End of OS-specific */ #define PT_LOPROC 0x70000000 /* Start of processor-specific */ diff --git a/libtcc.c b/libtcc.c index fbea50b..f841eb0 100644 --- a/libtcc.c +++ b/libtcc.c @@ -444,10 +444,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, } else if ((sym->type.t & VT_BTYPE) == VT_VOID) { sym_type = STT_NOTYPE; } else { - if (section && section->sh_flags & SHF_TLS) - sym_type = STT_TLS; - else - sym_type = STT_OBJECT; + sym_type = STT_OBJECT; } if (sym->type.t & VT_STATIC) diff --git a/tccelf.c b/tccelf.c index 4602ce8..8af4bb6 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1543,7 +1543,6 @@ static int elf_output_file(TCCState *s1, const char *filename) int fd, mode, ret; int *section_order; int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k; - int have_tls_section = 0; long long tmp; addr_t addr; Section *strsec, *s; @@ -1862,11 +1861,6 @@ static int elf_output_file(TCCState *s1, const char *filename) /* we output all sections if debug or object file */ s->sh_size = s->data_offset; } - /* if tls section we'll need to add one segment */ - if (s->sh_flags & SHF_TLS) { - have_tls_section = 1; - phnum++; - } } /* allocate program segment headers */ @@ -1910,16 +1904,12 @@ static int elf_output_file(TCCState *s1, const char *filename) if (interp) ph += 1 + HAVE_PHDR; - for(j = 0; j < 2 + have_tls_section; j++) { - if (j != 2) - ph->p_type = PT_LOAD; - else - ph->p_type = PT_TLS; - ph->p_flags = PF_R; + for(j = 0; j < 2; j++) { + ph->p_type = PT_LOAD; if (j == 0) - ph->p_flags |= PF_X; - else if (j == 1) - ph->p_flags |= PF_W; + ph->p_flags = PF_R | PF_X; + else + ph->p_flags = PF_R | PF_W; ph->p_align = s1->section_align; /* we do the following ordering: interp, symbol tables, @@ -1930,15 +1920,12 @@ static int elf_output_file(TCCState *s1, const char *filename) s = s1->sections[i]; /* compute if section should be included */ if (j == 0) { - if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS)) != + if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != SHF_ALLOC) continue; - } else if (j == 1) { - if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS)) != - (SHF_ALLOC | SHF_WRITE)) - continue; } else { - if ((s->sh_flags & SHF_TLS) != SHF_TLS) + if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != + (SHF_ALLOC | SHF_WRITE)) continue; } if (s == interp) { diff --git a/tccgen.c b/tccgen.c index bfe461f..bab4f7c 100644 --- a/tccgen.c +++ b/tccgen.c @@ -31,7 +31,6 @@ ST_DATA int rsym, anon_sym, ind, loc; ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */ -ST_DATA Section *tdata_section, *tbss_section; /* thread-local storage sections */ 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 */ @@ -3093,10 +3092,6 @@ static int parse_btype(CType *type, AttributeDef *ad) t |= VT_INLINE; next(); break; - case TOK_THREAD: - t |= VT_TLS; - next(); - break; /* GNUC attribute */ case TOK_ATTRIBUTE1: @@ -5500,26 +5495,10 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, /* allocate symbol in corresponding section */ sec = ad->section; if (!sec) { - if (has_init) { - if (type->t & VT_TLS) { - if (!tdata_section) - tdata_section = new_section(tcc_state, ".tdata", - SHT_PROGBITS, - SHF_ALLOC | SHF_WRITE | SHF_TLS); - sec = tdata_section; - } else - sec = data_section; - } - else if (tcc_state->nocommon) { - if (type->t & VT_TLS) { - if (!tbss_section) - tbss_section = new_section(tcc_state, ".tbss", - SHT_NOBITS, - SHF_ALLOC | SHF_WRITE | SHF_TLS); - sec = tbss_section; - } else - sec = bss_section; - } + if (has_init) + sec = data_section; + else if (tcc_state->nocommon) + sec = bss_section; } if (sec) { data_offset = sec->data_offset; diff --git a/tcctok.h b/tcctok.h index d55c9d7..9b47a60 100644 --- a/tcctok.h +++ b/tcctok.h @@ -10,7 +10,6 @@ DEF(TOK_FOR, "for") DEF(TOK_EXTERN, "extern") DEF(TOK_STATIC, "static") - DEF(TOK_THREAD, "__thread") DEF(TOK_UNSIGNED, "unsigned") DEF(TOK_GOTO, "goto") DEF(TOK_DO, "do") -- cgit v1.3.1 From 0650ab01c8a86dcf5247c1621e47dac06c0fc30c Mon Sep 17 00:00:00 2001 From: Joseph Poirier Date: Fri, 8 Nov 2013 13:24:15 -0600 Subject: struct variable behind guard, proper macro check, and remove some whitespace. Wrap runtime_main as per its declaration in tcc.h. Fix preprocessor check for TCC_ARM_EABI macro definition. Signed-off-by: Joseph Poirier --- arm-gen.c | 34 ++++++++++++++-------------- libtcc.c | 76 ++++++++++++++++++++++++++++++++------------------------------- 2 files changed, 56 insertions(+), 54 deletions(-) (limited to 'libtcc.c') diff --git a/arm-gen.c b/arm-gen.c index c9d4e55..b9e622f 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -1,6 +1,6 @@ /* * ARMv4 code generator for TCC - * + * * Copyright (c) 2003 Daniel Glöckner * Copyright (c) 2012 Thomas Preud'homme * @@ -46,7 +46,7 @@ #define RC_INT 0x0001 /* generic integer register */ #define RC_FLOAT 0x0002 /* generic float register */ #define RC_R0 0x0004 -#define RC_R1 0x0008 +#define RC_R1 0x0008 #define RC_R2 0x0010 #define RC_R3 0x0020 #define RC_R12 0x0040 @@ -211,7 +211,7 @@ void o(uint32_t i) cur_text_section->data[ind++] = i&255; i>>=8; cur_text_section->data[ind++] = i&255; - i>>=8; + i>>=8; cur_text_section->data[ind++] = i&255; i>>=8; cur_text_section->data[ind++] = i; @@ -506,7 +506,7 @@ void load(int r, SValue *sv) sign=1; fc=-fc; } - + v = fr & VT_VALMASK; if (fr & VT_LVAL) { uint32_t base = 0xB; // fp @@ -645,8 +645,8 @@ void store(int r, SValue *sv) sign=1; fc=-fc; } - - v = fr & VT_VALMASK; + + v = fr & VT_VALMASK; if (fr & VT_LVAL || fr == VT_LOCAL) { uint32_t base = 0xb; if(v < VT_CONST) { @@ -660,16 +660,16 @@ void store(int r, SValue *sv) v1.sym=sv->sym; load(base=14, &v1); fc=sign=0; - v=VT_LOCAL; + v=VT_LOCAL; } if(v == VT_LOCAL) { if(is_float(ft)) { calcaddr(&base,&fc,&sign,1020,2); #ifdef TCC_ARM_VFP op=0xED000A00; /* fsts */ - if(!sign) - op|=0x800000; - if ((ft & VT_BTYPE) != VT_FLOAT) + if(!sign) + op|=0x800000; + if ((ft & VT_BTYPE) != VT_FLOAT) op|=0x100; /* fsts -> fstd */ o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16)); #else @@ -802,7 +802,7 @@ int assign_fpreg(struct avail_regs *avregs, int align, int size) /* Return 1 if this function returns via an sret pointer, 0 otherwise */ ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) { -#if TCC_ARM_EABI +#ifdef TCC_ARM_EABI int size, align; size = type_size(vt, &align); if (size > 4) { @@ -855,7 +855,7 @@ void gfunc_call(int nb_args) vtop[-nb_args+1]=tmp; --nb_args; } - + vpushi(0), nb_args++; vtop->type.t = VT_LLONG; #endif @@ -1023,7 +1023,7 @@ void gfunc_call(int nb_args) size = 8; else size = LDOUBLE_SIZE; - + if (size == 12) r|=0x400000; else if(size == 8) @@ -1362,7 +1362,7 @@ int gtst(int inv, int t) return gtst(inv, t); } else if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { /* constant jmp optimization */ - if ((vtop->c.i != 0) != inv) + if ((vtop->c.i != 0) != inv) t = gjmp(t); } else { v = gv(RC_INT); @@ -1370,7 +1370,7 @@ int gtst(int inv, int t) vtop->r = VT_CMP; vtop->c.i = TOK_NE; return gtst(inv, t); - } + } } vtop--; return t; @@ -1628,7 +1628,7 @@ void gen_opf(int op) case TOK_UGE: op=TOK_GE; break; case TOK_UGT: op=TOK_GT; break; } - + vtop->r = VT_CMP; vtop->c.i = op; return; @@ -1779,7 +1779,7 @@ void gen_opf(int op) r=fpr(gv(RC_FLOAT)); vswap(); r2=fpr(gv(RC_FLOAT)); - } + } break; default: if(op >= TOK_ULT && op <= TOK_GT) { diff --git a/libtcc.c b/libtcc.c index f841eb0..aea81a3 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1,6 +1,6 @@ /* * TCC - Tiny C Compiler - * + * * Copyright (c) 2001-2004 Fabrice Bellard * * This library is free software; you can redistribute it and/or @@ -156,7 +156,7 @@ PUB_FUNC char *pstrcat(char *buf, int buf_size, const char *s) { int len; len = strlen(buf); - if (len < buf_size) + if (len < buf_size) pstrcpy(buf + len, buf_size - len, s); return buf; } @@ -275,7 +275,7 @@ ST_FUNC void dynarray_add(void ***ptab, int *nb_ptr, void *data) { int nb, nb_alloc; void **pp; - + nb = *nb_ptr; pp = *ptab; /* every power of two we double array size */ @@ -371,7 +371,7 @@ ST_FUNC void section_realloc(Section *sec, unsigned long new_size) { unsigned long size; unsigned char *data; - + size = sec->data_allocated; if (size == 0) size = 1; @@ -414,7 +414,7 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name) int i; for(i = 1; i < s1->nb_sections; i++) { sec = s1->sections[i]; - if (!strcmp(name, sec->name)) + if (!strcmp(name, sec->name)) return sec; } /* sections are created as PROGBITS */ @@ -423,7 +423,7 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name) /* update sym->c so that it points to an external symbol in section 'section' with value 'value' */ -ST_FUNC void put_extern_sym2(Sym *sym, Section *section, +ST_FUNC void put_extern_sym2(Sym *sym, Section *section, addr_t value, unsigned long size, int can_add_underscore) { @@ -434,7 +434,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, if (section == NULL) sh_num = SHN_UNDEF; - else if (section == SECTION_ABS) + else if (section == SECTION_ABS) sh_num = SHN_ABS; else sh_num = section->sh_num; @@ -468,13 +468,13 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, switch(sym->v) { #ifdef TCC_TARGET_PE /* XXX: we rely only on malloc hooks */ - case TOK_malloc: - case TOK_free: - case TOK_realloc: - case TOK_memalign: - case TOK_calloc: + case TOK_malloc: + case TOK_free: + case TOK_realloc: + case TOK_memalign: + case TOK_calloc: #endif - case TOK_memcpy: + case TOK_memcpy: case TOK_memmove: case TOK_memset: case TOK_strlen: @@ -527,7 +527,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, } } -ST_FUNC void put_extern_sym(Sym *sym, Section *section, +ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size) { put_extern_sym2(sym, section, value, size, 1); @@ -567,7 +567,7 @@ static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) { char buf[2048]; BufferedFile **pf, *f; - + buf[0] = '\0'; /* use upper file if inline ":asm:" or token ":paste:" */ for (f = file; f && f->filename[0] == ':'; f = f->prev) @@ -718,28 +718,28 @@ static int tcc_compile(TCCState *s1) cur_text_section = NULL; funcname = ""; - anon_sym = SYM_FIRST_ANOM; + anon_sym = SYM_FIRST_ANOM; /* file info: full path + filename */ section_sym = 0; /* avoid warning */ if (s1->do_debug) { - section_sym = put_elf_sym(symtab_section, 0, 0, - ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0, + section_sym = put_elf_sym(symtab_section, 0, 0, + ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0, text_section->sh_num, NULL); getcwd(buf, sizeof(buf)); #ifdef _WIN32 normalize_slashes(buf); #endif pstrcat(buf, sizeof(buf), "/"); - put_stabs_r(buf, N_SO, 0, 0, + put_stabs_r(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(file->filename, N_SO, 0, 0, text_section->data_offset, text_section, section_sym); } /* an elf symbol of type STT_FILE must be put so that STB_LOCAL symbols can be safely used */ - put_elf_sym(symtab_section, 0, 0, - ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, + put_elf_sym(symtab_section, 0, 0, + ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, SHN_ABS, file->filename); /* define some often used types */ @@ -794,7 +794,7 @@ static int tcc_compile(TCCState *s1) /* end of translation unit info */ if (s1->do_debug) { - put_stabs_r(NULL, N_SO, 0, 0, + put_stabs_r(NULL, N_SO, 0, 0, text_section->data_offset, text_section, section_sym); } } @@ -803,7 +803,7 @@ static int tcc_compile(TCCState *s1) /* reset define stack, but leave -Dsymbols (may be incorrect if they are undefined) */ - free_defines(define_start); + free_defines(define_start); gen_inline_functions(); @@ -1004,13 +1004,13 @@ LIBTCCAPI TCCState *tcc_new(void) /* symbols are always generated for linking stage */ symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0, ".strtab", - ".hashtab", SHF_PRIVATE); + ".hashtab", SHF_PRIVATE); strtab_section = symtab_section->link; s->symtab = symtab_section; - + /* private symbol table for dynamic symbols */ s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE, - ".dynstrtab", + ".dynstrtab", ".dynhashtab", SHF_PRIVATE); s->alacarte_link = 1; s->nocommon = 1; @@ -1026,7 +1026,9 @@ LIBTCCAPI TCCState *tcc_new(void) #ifdef TCC_TARGET_I386 s->seg_size = 32; #endif +#ifdef TCC_IS_NATIVE s->runtime_main = "main"; +#endif return s; } @@ -1044,7 +1046,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1) for(i = 0; i < s1->nb_priv_sections; i++) free_section(s1->priv_sections[i]); dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections); - + /* free any loaded DLLs */ #ifdef TCC_IS_NATIVE for ( i = 0; i < s1->nb_loaded_dlls; i++) { @@ -1053,7 +1055,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1) dlclose(ref->handle); } #endif - + /* free loaded dlls array */ dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); @@ -1079,7 +1081,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1) #ifdef TCC_IS_NATIVE # ifdef HAVE_SELINUX munmap (s1->write_mem, s1->mem_size); - munmap (s1->runtime_mem, s1->mem_size); + munmap (s1->runtime_mem, s1->mem_size); # else tcc_free(s1->runtime_mem); # endif @@ -1186,7 +1188,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) #endif ret = 0; } else { - ret = tcc_load_dll(s1, fd, filename, + ret = tcc_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0); } goto the_end; @@ -1318,9 +1320,9 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) /* define symbol */ tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL); /* create bounds sections */ - bounds_section = new_section(s, ".bounds", + bounds_section = new_section(s, ".bounds", SHT_PROGBITS, SHF_ALLOC); - lbounds_section = new_section(s, ".lbounds", + lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, SHF_ALLOC); } #endif @@ -1693,7 +1695,7 @@ static const TCCOption tcc_options[] = { { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG }, { "nostdinc", TCC_OPTION_nostdinc, 0 }, { "nostdlib", TCC_OPTION_nostdlib, 0 }, - { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, + { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "w", TCC_OPTION_w, 0 }, { "pipe", TCC_OPTION_pipe, 0}, @@ -1859,7 +1861,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) goto unsupported_option; break; case TCC_OPTION_W: - if (tcc_set_warning(s, optarg, 1) < 0 && + if (tcc_set_warning(s, optarg, 1) < 0 && s->warn_unsupported) goto unsupported_option; break; @@ -1946,7 +1948,7 @@ PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time) tt = 0.001; if (total_bytes < 1) total_bytes = 1; - printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n", + printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n", tok_ident - TOK_IDENT, total_lines, total_bytes, tt, (int)(total_lines / tt), total_bytes / tt / 1000000.0); @@ -1955,7 +1957,7 @@ PUB_FUNC void tcc_print_stats(TCCState *s, int64_t total_time) PUB_FUNC void tcc_set_environment(TCCState *s) { char * path; - + path = getenv("C_INCLUDE_PATH"); if(path != NULL) { tcc_add_include_path(s, path); -- cgit v1.3.1 From 3676f61983ca65506186c5429fc85a8da6642f3e Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Tue, 26 Nov 2013 12:06:21 +0800 Subject: Define __ARM_EABI__ and __ARMEL__ when applicable --- libtcc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'libtcc.c') diff --git a/libtcc.c b/libtcc.c index aea81a3..df201ae 100644 --- a/libtcc.c +++ b/libtcc.c @@ -942,10 +942,14 @@ LIBTCCAPI TCCState *tcc_new(void) tcc_define_symbol(s, "__arm", NULL); tcc_define_symbol(s, "arm", NULL); tcc_define_symbol(s, "__APCS_32__", NULL); + tcc_define_symbol(s, "__ARMEL__", NULL); +#if defined(TCC_ARM_EABI) + tcc_define_symbol(s, "__ARM_EABI__", NULL); #if defined(TCC_ARM_HARDFLOAT) tcc_define_symbol(s, "__ARM_PCS_VFP", NULL); #endif #endif +#endif #ifdef TCC_TARGET_PE tcc_define_symbol(s, "_WIN32", NULL); -- cgit v1.3.1 From 2bd0daabbe1fc40e65e4a4631e68f5ca093ea1fb Mon Sep 17 00:00:00 2001 From: grischka Date: Mon, 6 Jan 2014 19:56:26 +0100 Subject: misc. fixes - tccgen: error out for cast to void, as in void foo(void) { return 1; } This avoids an assertion failure in x86_64-gen.c, also. also fix tests2/03_struct.c accordingly - Error: "memory full" - be more specific - Makefiles: remove circular dependencies, lookup tcctest.c from VPATH - tcc.h: cleanup lib, include, crt and libgcc search paths" avoid duplication or trailing slashes with no CONFIG_MULTIARCHDIR (as from 9382d6f1a0e2d0104a82ed805207d9e742c6b068) - tcc.h: remove ";{B}" from PE search path in ce5e12c2f950052d8109b6b7a56d900547705c08 James Lyon wrote: "... I'm not sure this is the right way to fix this problem." And the answer is: No, please. (copying libtcc1.a for tests instead) - win32/build_tcc.bat: do not move away a versioned file --- Makefile | 3 --- lib/Makefile | 3 --- libtcc.c | 4 ++-- tcc.h | 30 +++++++++++++++--------------- tccgen.c | 8 ++++---- tccpp.c | 4 ++-- tests/Makefile | 39 ++++++++++++++++++++------------------- tests/tests2/03_struct.c | 2 +- tests/tests2/Makefile | 3 --- win32/build-tcc.bat | 4 ++-- 10 files changed, 46 insertions(+), 54 deletions(-) (limited to 'libtcc.c') diff --git a/Makefile b/Makefile index 24a7c09..5052758 100644 --- a/Makefile +++ b/Makefile @@ -362,9 +362,6 @@ tar: tcc-doc.html rm -rf $(TCC-VERSION) git reset -Makefile: $(top_srcdir)/Makefile - cp $< $@ - .PHONY: all clean tar distclean install uninstall FORCE endif # ifeq ($(TOP),.) diff --git a/lib/Makefile b/lib/Makefile index a8a2b5d..394df67 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -111,6 +111,3 @@ $(DIR)/exists : clean : rm -rfv i386-win32 x86_64-win32 i386 x86_64 - -Makefile: $(top_srcdir)/lib/Makefile - cp $< $@ diff --git a/libtcc.c b/libtcc.c index df201ae..072b77f 100644 --- a/libtcc.c +++ b/libtcc.c @@ -214,7 +214,7 @@ PUB_FUNC void *tcc_malloc(unsigned long size) void *ptr; ptr = malloc(size); if (!ptr && size) - tcc_error("memory full"); + tcc_error("memory full (malloc)"); #ifdef MEM_DEBUG mem_cur_size += malloc_usable_size(ptr); if (mem_cur_size > mem_max_size) @@ -239,7 +239,7 @@ PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size) #endif ptr1 = realloc(ptr, size); if (!ptr1 && size) - tcc_error("memory full"); + tcc_error("memory full (realloc)"); #ifdef MEM_DEBUG /* NOTE: count not correct if alloc error, but not critical */ mem_cur_size += malloc_usable_size(ptr1); diff --git a/tcc.h b/tcc.h index 21957e7..0933b01 100644 --- a/tcc.h +++ b/tcc.h @@ -169,13 +169,18 @@ #ifndef CONFIG_LDDIR # define CONFIG_LDDIR "lib" #endif -#ifndef CONFIG_MULTIARCHDIR -#define CONFIG_MULTIARCHDIR + +#ifdef CONFIG_MULTIARCHDIR +# define USE_MUADIR(s) s "/" CONFIG_MULTIARCHDIR +# define ALSO_MUADIR(s) s "/" CONFIG_MULTIARCHDIR ":" s +#else +# define USE_MUADIR(s) s +# define ALSO_MUADIR(s) s #endif /* path to find crt1.o, crti.o and crtn.o */ #ifndef CONFIG_TCC_CRTPREFIX -# define CONFIG_TCC_CRTPREFIX CONFIG_SYSROOT "/usr/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR +# define CONFIG_TCC_CRTPREFIX USE_MUADIR(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) #endif /* Below: {B} is substituted by CONFIG_TCCDIR (rsp. -B option) */ @@ -186,10 +191,8 @@ # define CONFIG_TCC_SYSINCLUDEPATHS "{B}/include;{B}/include/winapi" # else # define CONFIG_TCC_SYSINCLUDEPATHS \ - CONFIG_SYSROOT "/usr/local/include/" CONFIG_MULTIARCHDIR \ - ":" CONFIG_SYSROOT "/usr/local/include" \ - ":" CONFIG_SYSROOT "/usr/include/" CONFIG_MULTIARCHDIR \ - ":" CONFIG_SYSROOT "/usr/include" \ + ALSO_MUADIR(CONFIG_SYSROOT "/usr/local/include") \ + ":" ALSO_MUADIR(CONFIG_SYSROOT "/usr/include") \ ":" "{B}/include" # endif #endif @@ -197,15 +200,12 @@ /* library search paths */ #ifndef CONFIG_TCC_LIBPATHS # ifdef TCC_TARGET_PE -# define CONFIG_TCC_LIBPATHS "{B}/lib;{B}" +# define CONFIG_TCC_LIBPATHS "{B}/lib" # else # define CONFIG_TCC_LIBPATHS \ - CONFIG_SYSROOT "/usr/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR \ - ":" CONFIG_SYSROOT "/usr/" CONFIG_LDDIR \ - ":" CONFIG_SYSROOT "/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR \ - ":" CONFIG_SYSROOT "/" CONFIG_LDDIR \ - ":" CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR \ - ":" CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR + ALSO_MUADIR(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \ + ":" ALSO_MUADIR(CONFIG_SYSROOT "/" CONFIG_LDDIR) \ + ":" ALSO_MUADIR(CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR) # endif #endif @@ -237,7 +237,7 @@ #endif /* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */ -#define TCC_LIBGCC CONFIG_SYSROOT "/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR "/libgcc_s.so.1" +#define TCC_LIBGCC USE_MUADIR(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1" /* -------------------------------------------- */ /* include the target specific definitions */ diff --git a/tccgen.c b/tccgen.c index 8355aae..f23cd07 100644 --- a/tccgen.c +++ b/tccgen.c @@ -309,7 +309,7 @@ static void vsetc(CType *type, int r, CValue *vc) int v; if (vtop >= vstack + (VSTACK_SIZE - 1)) - tcc_error("memory full"); + tcc_error("memory full (vstack)"); /* cannot let cpu flags if other instruction are generated. Also avoid leaving VT_JMP anywhere except on the top of the stack because it would complicate the code generator. */ @@ -483,7 +483,7 @@ ST_FUNC void vswap(void) ST_FUNC void vpushv(SValue *v) { if (vtop >= vstack + (VSTACK_SIZE - 1)) - tcc_error("memory full"); + tcc_error("memory full (vstack)"); vtop++; *vtop = *v; } @@ -2348,8 +2348,8 @@ static void gen_assign_cast(CType *dt) st = &vtop->type; /* source type */ dbt = dt->t & VT_BTYPE; sbt = st->t & VT_BTYPE; - if (sbt == VT_VOID) - tcc_error("Cannot assign void value"); + if (sbt == VT_VOID || dbt == VT_VOID) + tcc_error("cannot cast from/to void"); if (dt->t & VT_CONSTANT) tcc_warning("assignment of read-only location"); switch(dbt) { diff --git a/tccpp.c b/tccpp.c index aeaf6be..e1ccded 100644 --- a/tccpp.c +++ b/tccpp.c @@ -197,7 +197,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) int i; if (tok_ident >= SYM_FIRST_ANOM) - tcc_error("memory full"); + tcc_error("memory full (symbols)"); /* expand token table if needed */ i = tok_ident - TOK_IDENT; @@ -1528,7 +1528,7 @@ include_done: c = (define_find(tok) != 0) ^ c; do_if: if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE) - tcc_error("memory full"); + tcc_error("memory full (ifdef)"); *s1->ifdef_stack_ptr++ = c; goto test_skip; case TOK_ELSE: diff --git a/tests/Makefile b/tests/Makefile index 08dfa42..b958a48 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -27,7 +27,7 @@ ifneq ($(ARCH),i386) TESTS := $(filter-out btest,$(TESTS)) endif ifdef CONFIG_WIN32 - TESTS := $(filter-out test3,$(TESTS)) + TESTS := w32-prep $(filter-out test3,$(TESTS)) endif ifeq ($(TARGETOS),Darwin) TESTS := $(filter-out hello-exe test3 btest,$(TESTS)) @@ -84,6 +84,9 @@ moretests: @echo ------------ $@ ------------ $(MAKE) -C tests2 +w32-prep: + cp ../libtcc1.a ../lib + # test.ref - generate using gcc # copy only tcclib.h so GCC's stddef and stdarg will be used test.ref: tcctest.c @@ -91,41 +94,41 @@ test.ref: tcctest.c ./tcctest.gcc > $@ # auto test -test1: test.ref +test1: tcctest.c test.ref @echo ------------ $@ ------------ - $(TCC) -run $(SRCDIR)/tcctest.c > test.out1 + $(TCC) -run $< > test.out1 @if diff -u test.ref test.out1 ; then echo "Auto Test OK"; fi # iterated test2 (compile tcc then compile tcctest.c !) -test2: test.ref +test2: tcctest.c test.ref @echo ------------ $@ ------------ - $(TCC) $(RUN_TCC) $(RUN_TCC) -run $(SRCDIR)/tcctest.c > test.out2 + $(TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out2 @if diff -u test.ref test.out2 ; then echo "Auto Test2 OK"; fi # iterated test3 (compile tcc then compile tcc then compile tcctest.c !) -test3: test.ref +test3: tcctest.c test.ref @echo ------------ $@ ------------ - $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $(SRCDIR)/tcctest.c > test.out3 + $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out3 @if diff -u test.ref test.out3 ; then echo "Auto Test3 OK"; fi # binary output test -test4: test.ref +test4: tcctest.c test.ref @echo ------------ $@ ------------ # object + link output - $(TCC) -c -o tcctest3.o $(SRCDIR)/tcctest.c + $(TCC) -c -o tcctest3.o $< $(TCC) -o tcctest3 tcctest3.o ./tcctest3 > test3.out @if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi # dynamic output - $(TCC) -o tcctest1 $(SRCDIR)/tcctest.c + $(TCC) -o tcctest1 $< ./tcctest1 > test1.out @if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi # dynamic output + bound check - $(TCC) -b -o tcctest4 $(SRCDIR)/tcctest.c + $(TCC) -b -o tcctest4 $< ./tcctest4 > test4.out @if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi # static output - $(TCC) -static -o tcctest2 $(SRCDIR)/tcctest.c + $(TCC) -static -o tcctest2 $< ./tcctest2 > test2.out @if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi @@ -161,9 +164,9 @@ speedtest: ex2 ex3 time ./ex3 35 time $(TCC) -run $(top_srcdir)/examples/ex3.c 35 -weaktest: test.ref - $(TCC) -c tcctest.c -o weaktest.tcc.o $(CPPFLAGS) $(CFLAGS) - $(CC) -c tcctest.c -o weaktest.gcc.o -I. $(CPPFLAGS) -w $(CFLAGS) +weaktest: tcctest.c test.ref + $(TCC) -c $< -o weaktest.tcc.o $(CPPFLAGS) $(CFLAGS) + $(CC) -c $< -o weaktest.gcc.o -I. $(CPPFLAGS) -w $(CFLAGS) objdump -t weaktest.tcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.tcc.o.txt objdump -t weaktest.gcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.gcc.o.txt diff weaktest.gcc.o.txt weaktest.tcc.o.txt && echo "Weak Auto Test OK" @@ -220,7 +223,5 @@ cache: tcc_g clean: $(MAKE) -C tests2 $@ rm -vf *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.gcc *.exe \ - hello libtcc_test tcctest[1234] ex? tcc_g tcclib.h - -Makefile: $(SRCDIR)/Makefile - cp $< $@ + hello libtcc_test tcctest[1234] ex? tcc_g tcclib.h \ + ../lib/libtcc1.a diff --git a/tests/tests2/03_struct.c b/tests/tests2/03_struct.c index df0d3e7..c5d48c5 100644 --- a/tests/tests2/03_struct.c +++ b/tests/tests2/03_struct.c @@ -6,7 +6,7 @@ struct fred int natasha; }; -void main() +int main() { struct fred bloggs; diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 369ed47..51dc38d 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -96,6 +96,3 @@ all test: $(TESTS) clean: rm -vf fred.txt *.output - -Makefile: $(top_srcdir)/tests/tests2/Makefile - cp $< $@ diff --git a/win32/build-tcc.bat b/win32/build-tcc.bat index 772ed26..bd897c4 100644 --- a/win32/build-tcc.bat +++ b/win32/build-tcc.bat @@ -63,5 +63,5 @@ del *.o echo>..\config.texi @set VERSION %VERSION% if not exist doc md doc makeinfo --html --no-split -o doc\tcc-doc.html ../tcc-doc.texi -if exist tcc-win32.txt move tcc-win32.txt doc\ -copy ..\tests\libtcc_test.c examples\ +copy tcc-win32.txt doc +copy ..\tests\libtcc_test.c examples -- cgit v1.3.1 From 3fe2a95d7fe854c8cf496a009a467bb65cdf030d Mon Sep 17 00:00:00 2001 From: grischka Date: Tue, 7 Jan 2014 14:57:07 +0100 Subject: be stricter with aliasing Refactoring (no logical changes): - use memcpy in tccgen.c:ieee_finite(double d) - use union to store attribute flags in Sym Makefile: "CFLAGS+=-fno-strict-aliasing" basically not necessary anymore but I left it for now because gcc sometimes behaves unexpectedly without. Also: - configure: back to mode 100755 - tcc.h: remove unused variables tdata/tbss_section - x86_64-gen.c: adjust gfunc_sret for prototype --- configure | 0 i386-gen.c | 4 +-- libtcc.c | 8 ++--- tcc.h | 57 ++++++++++++++++------------------- tccgen.c | 97 +++++++++++++++++++++++++++++++----------------------------- x86_64-gen.c | 15 ++++++---- 6 files changed, 92 insertions(+), 89 deletions(-) mode change 100644 => 100755 configure (limited to 'libtcc.c') diff --git a/configure b/configure old mode 100644 new mode 100755 diff --git a/i386-gen.c b/i386-gen.c index 4c4a54b..ece054b 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -457,7 +457,7 @@ ST_FUNC void gfunc_call(int nb_args) } save_regs(0); /* save used temporary registers */ func_sym = vtop->type.ref; - func_call = FUNC_CALL(func_sym->r); + func_call = func_sym->a.func_call; /* fast call case */ if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || func_call == FUNC_FASTCALLW) { @@ -505,7 +505,7 @@ ST_FUNC void gfunc_prolog(CType *func_type) CType *type; sym = func_type->ref; - func_call = FUNC_CALL(sym->r); + func_call = sym->a.func_call; addr = 8; loc = 0; func_vc = 0; diff --git a/libtcc.c b/libtcc.c index 072b77f..154a266 100644 --- a/libtcc.c +++ b/libtcc.c @@ -493,11 +493,11 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, if (sym->type.t & VT_EXPORT) other |= 1; if (sym_type == STT_FUNC && sym->type.ref) { - int attr = sym->type.ref->r; - if (FUNC_EXPORT(attr)) + Sym *ref = sym->type.ref; + if (ref->a.func_export) other |= 1; - if (FUNC_CALL(attr) == FUNC_STDCALL && can_add_underscore) { - sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr) * PTR_SIZE); + if (ref->a.func_call == FUNC_STDCALL && can_add_underscore) { + sprintf(buf1, "_%s@%d", name, ref->a.func_args * PTR_SIZE); name = buf1; other |= 2; can_add_underscore = 0; diff --git a/tcc.h b/tcc.h index 0933b01..f3d868f 100644 --- a/tcc.h +++ b/tcc.h @@ -326,11 +326,35 @@ typedef struct SValue { struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */ } SValue; +struct Attribute { + unsigned + func_call : 3, /* calling convention (0..5), see below */ + aligned : 5, /* alignement (0..16) */ + packed : 1, + func_export : 1, + func_import : 1, + func_args : 5, + func_proto : 1, + mode : 4, + weak : 1, + fill : 10; // 10 bits left to fit well in union below +}; + +/* GNUC attribute definition */ +typedef struct AttributeDef { + struct Attribute a; + struct Section *section; + int alias_target; /* token */ +} AttributeDef; + /* symbol management */ typedef struct Sym { int v; /* symbol token */ char *asm_label; /* associated asm label */ - long r; /* associated register */ + union { + long r; /* associated register */ + struct Attribute a; + }; union { long c; /* associated number */ int *d; /* define token stream */ @@ -381,34 +405,6 @@ typedef struct DLLReference { char name[1]; } DLLReference; -/* GNUC attribute definition */ -typedef struct AttributeDef { - unsigned - func_call : 3, /* calling convention (0..5), see below */ - aligned : 5, /* alignement (0..16) */ - packed : 1, - func_export : 1, - func_import : 1, - func_args : 5, - func_proto : 1, - mode : 4, - weak : 1, - fill : 10; - struct Section *section; - int alias_target; /* token */ -} AttributeDef; - -/* gr: wrappers for casting sym->r for other purposes */ -#define FUNC_CALL(r) (((AttributeDef*)&(r))->func_call) -#define FUNC_EXPORT(r) (((AttributeDef*)&(r))->func_export) -#define FUNC_IMPORT(r) (((AttributeDef*)&(r))->func_import) -#define FUNC_ARGS(r) (((AttributeDef*)&(r))->func_args) -#define FUNC_PROTO(r) (((AttributeDef*)&(r))->func_proto) -#define FUNC_ALIGN(r) (((AttributeDef*)&(r))->aligned) -#define FUNC_PACKED(r) (((AttributeDef*)&(r))->packed) -#define ATTR_MODE(r) (((AttributeDef*)&(r))->mode) -#define INT_ATTR(ad) (*(int*)(ad)) - /* -------------------------------------------------- */ #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */ @@ -1142,7 +1138,6 @@ ST_FUNC void expect(const char *msg); /* ------------ tccgen.c ------------ */ ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */ -ST_DATA Section *tdata_section, *tbss_section; /* thread-local storage sections */ 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 */ @@ -1268,7 +1263,7 @@ ST_FUNC void build_got_entries(TCCState *s1); ST_FUNC void tcc_add_runtime(TCCState *s1); ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err); -#ifdef TCC_IS_NATIVE +#if defined TCC_IS_NATIVE || defined TCC_TARGET_PE ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name); #endif diff --git a/tccgen.c b/tccgen.c index f23cd07..7a675cc 100644 --- a/tccgen.c +++ b/tccgen.c @@ -103,7 +103,8 @@ ST_INLN int is_float(int t) /* XXX: endianness dependent */ ST_FUNC int ieee_finite(double d) { - int *p = (int *)&d; + int p[4]; + memcpy(p, &d, sizeof(double)); return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31; } @@ -2172,7 +2173,7 @@ static int is_compatible_func(CType *type1, CType *type2) if (!is_compatible_types(&s1->type, &s2->type)) return 0; /* check func_call */ - if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r)) + if (s1->a.func_call != s2->a.func_call) return 0; /* XXX: not complete */ if (s1->c == FUNC_OLD || s2->c == FUNC_OLD) @@ -2659,15 +2660,15 @@ static void parse_attribute(AttributeDef *ad) } else { n = MAX_ALIGN; } - ad->aligned = n; + ad->a.aligned = n; break; case TOK_PACKED1: case TOK_PACKED2: - ad->packed = 1; + ad->a.packed = 1; break; case TOK_WEAK1: case TOK_WEAK2: - ad->weak = 1; + ad->a.weak = 1; break; case TOK_UNUSED1: case TOK_UNUSED2: @@ -2682,12 +2683,12 @@ static void parse_attribute(AttributeDef *ad) case TOK_CDECL1: case TOK_CDECL2: case TOK_CDECL3: - ad->func_call = FUNC_CDECL; + ad->a.func_call = FUNC_CDECL; break; case TOK_STDCALL1: case TOK_STDCALL2: case TOK_STDCALL3: - ad->func_call = FUNC_STDCALL; + ad->a.func_call = FUNC_STDCALL; break; #ifdef TCC_TARGET_I386 case TOK_REGPARM1: @@ -2699,26 +2700,26 @@ static void parse_attribute(AttributeDef *ad) else if (n < 0) n = 0; if (n > 0) - ad->func_call = FUNC_FASTCALL1 + n - 1; + ad->a.func_call = FUNC_FASTCALL1 + n - 1; skip(')'); break; case TOK_FASTCALL1: case TOK_FASTCALL2: case TOK_FASTCALL3: - ad->func_call = FUNC_FASTCALLW; + ad->a.func_call = FUNC_FASTCALLW; break; #endif case TOK_MODE: skip('('); switch(tok) { case TOK_MODE_DI: - ad->mode = VT_LLONG + 1; + ad->a.mode = VT_LLONG + 1; break; case TOK_MODE_HI: - ad->mode = VT_SHORT + 1; + ad->a.mode = VT_SHORT + 1; break; case TOK_MODE_SI: - ad->mode = VT_INT + 1; + ad->a.mode = VT_INT + 1; break; default: tcc_warning("__mode__(%s) not supported\n", get_tok_str(tok, NULL)); @@ -2728,10 +2729,10 @@ static void parse_attribute(AttributeDef *ad) skip(')'); break; case TOK_DLLEXPORT: - ad->func_export = 1; + ad->a.func_export = 1; break; case TOK_DLLIMPORT: - ad->func_import = 1; + ad->a.func_import = 1; break; default: if (tcc_state->warn_unsupported) @@ -2873,10 +2874,10 @@ static void struct_decl(CType *type, int u, int tdef) get_tok_str(v, NULL)); } size = type_size(&type1, &align); - if (ad.aligned) { - if (align < ad.aligned) - align = ad.aligned; - } else if (ad.packed) { + if (ad.a.aligned) { + if (align < ad.a.aligned) + align = ad.a.aligned; + } else if (ad.a.packed) { align = 1; } else if (*tcc_state->pack_stack_ptr) { if (align > *tcc_state->pack_stack_ptr) @@ -3118,8 +3119,8 @@ static int parse_btype(CType *type, AttributeDef *ad) case TOK_ATTRIBUTE1: case TOK_ATTRIBUTE2: parse_attribute(ad); - if (ad->mode) { - u = ad->mode -1; + if (ad->a.mode) { + u = ad->a.mode -1; t = (t & ~VT_BTYPE) | u; } break; @@ -3143,11 +3144,11 @@ static int parse_btype(CType *type, AttributeDef *ad) type->ref = s->type.ref; if (s->r) { /* get attributes from typedef */ - if (0 == ad->aligned) - ad->aligned = FUNC_ALIGN(s->r); - if (0 == ad->func_call) - ad->func_call = FUNC_CALL(s->r); - ad->packed |= FUNC_PACKED(s->r); + if (0 == ad->a.aligned) + ad->a.aligned = s->a.aligned; + if (0 == ad->a.func_call) + ad->a.func_call = s->a.func_call; + ad->a.packed |= s->a.packed; } next(); typespec_found = 1; @@ -3287,8 +3288,9 @@ static void post_type(CType *type, AttributeDef *ad) type->t |= VT_PTR; } /* we push a anonymous symbol which will contain the function prototype */ - ad->func_args = arg_size; - s = sym_push(SYM_FIELD, type, INT_ATTR(ad), l); + ad->a.func_args = arg_size; + s = sym_push(SYM_FIELD, type, 0, l); + s->a = ad->a; s->next = first; type->t = VT_FUNC; type->ref = s; @@ -5484,10 +5486,10 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, if (flexible_array) size += flexible_array->type.ref->c * pointed_size(&flexible_array->type); /* take into account specified alignment if bigger */ - if (ad->aligned) { - if (ad->aligned > align) - align = ad->aligned; - } else if (ad->packed) { + if (ad->a.aligned) { + if (ad->a.aligned > align) + align = ad->a.aligned; + } else if (ad->a.packed) { align = 1; } if ((r & VT_VALMASK) == VT_LOCAL) { @@ -5869,12 +5871,12 @@ static int decl0(int l, int is_for_loop_init) parse_attribute(&ad); } - if (ad.weak) + if (ad.a.weak) type.t |= VT_WEAK; #ifdef TCC_TARGET_PE - if (ad.func_import) + if (ad.a.func_import) type.t |= VT_IMPORT; - if (ad.func_export) + if (ad.a.func_export) type.t |= VT_EXPORT; #endif if (tok == '{') { @@ -5895,22 +5897,22 @@ static int decl0(int l, int is_for_loop_init) sym = sym_find(v); if (sym) { + Sym *ref; if ((sym->type.t & VT_BTYPE) != VT_FUNC) goto func_error1; - r = sym->type.ref->r; - - if (!FUNC_PROTO(r)) + ref = sym->type.ref; + if (0 == ref->a.func_proto) tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); /* use func_call from prototype if not defined */ - if (FUNC_CALL(r) != FUNC_CDECL - && FUNC_CALL(type.ref->r) == FUNC_CDECL) - FUNC_CALL(type.ref->r) = FUNC_CALL(r); + if (ref->a.func_call != FUNC_CDECL + && type.ref->a.func_call == FUNC_CDECL) + type.ref->a.func_call = ref->a.func_call; /* use export from prototype */ - if (FUNC_EXPORT(r)) - FUNC_EXPORT(type.ref->r) = 1; + if (ref->a.func_export) + type.ref->a.func_export = 1; /* use static from prototype */ if (sym->type.t & VT_STATIC) @@ -5921,7 +5923,7 @@ static int decl0(int l, int is_for_loop_init) tcc_error("incompatible types for redefinition of '%s'", get_tok_str(v, NULL)); } - FUNC_PROTO(type.ref->r) = 0; + type.ref->a.func_proto = 0; /* if symbol is already defined, then put complete type */ sym->type = type; } else { @@ -5980,15 +5982,16 @@ static int decl0(int l, int is_for_loop_init) if (btype.t & VT_TYPEDEF) { /* save typedefed type */ /* XXX: test storage specifiers ? */ - sym = sym_push(v, &type, INT_ATTR(&ad), 0); + sym = sym_push(v, &type, 0, 0); + sym->a = ad.a; sym->type.t |= VT_TYPEDEF; } else { r = 0; if ((type.t & VT_BTYPE) == VT_FUNC) { /* external function definition */ /* specific case for func_call attribute */ - ad.func_proto = 1; - type.ref->r = INT_ATTR(&ad); + ad.a.func_proto = 1; + type.ref->a = ad.a; } else if (!(type.t & VT_ARRAY)) { /* not lvalue if array */ r |= lvalue_type(type.t); @@ -6039,7 +6042,7 @@ static int decl0(int l, int is_for_loop_init) } next(); } - ad.aligned = 0; + ad.a.aligned = 0; } } return 0; diff --git a/x86_64-gen.c b/x86_64-gen.c index 9aee875..9acca3c 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -933,7 +933,8 @@ typedef enum X86_64_Mode { x86_64_mode_x87 } X86_64_Mode; -static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) { +static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) +{ if (a == b) return a; else if (a == x86_64_mode_none) @@ -950,7 +951,8 @@ static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) { return x86_64_mode_sse; } -static X86_64_Mode classify_x86_64_inner(CType *ty) { +static X86_64_Mode classify_x86_64_inner(CType *ty) +{ X86_64_Mode mode; Sym *f; @@ -988,7 +990,8 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) { assert(0); } -static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count) { +static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count) +{ X86_64_Mode mode; int size, align, ret_t = 0; @@ -1045,7 +1048,8 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p return mode; } -ST_FUNC int classify_x86_64_va_arg(CType *ty) { +ST_FUNC int classify_x86_64_va_arg(CType *ty) +{ /* This definition must be synced with stdarg.h */ enum __va_arg_type { __va_gen_reg, __va_float_reg, __va_stack @@ -1061,7 +1065,8 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty) { /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ -int gfunc_sret(CType *vt, CType *ret, int *ret_align) { +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) +{ int size, align, reg_count; *ret_align = 1; // Never have to re-align return values for x86-64 return (classify_x86_64_arg(vt, ret, &size, &align, ®_count) != x86_64_mode_memory); -- cgit v1.3.1 From b6247d1f3c34e93e8603fddf5fc6da8dc6b81d00 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Tue, 7 Jan 2014 15:23:54 +0800 Subject: Add support for runtime selection of float ABI --- Changelog | 1 + arm-gen.c | 131 ++++++++++++++++++++++++++++++++--------------------------- libtcc.c | 23 ++++++++++- tcc-doc.texi | 3 ++ tcc.c | 2 +- tcc.h | 21 +++++++--- tccelf.c | 2 +- 7 files changed, 113 insertions(+), 70 deletions(-) (limited to 'libtcc.c') diff --git a/Changelog b/Changelog index 52f8a10..9a497cf 100644 --- a/Changelog +++ b/Changelog @@ -18,6 +18,7 @@ Features: - improved variable length array support (James Lyon) - add the possibility to use noname functions by ordinal (YX Hao) - add a install-strip target to install tcc (Thomas Preud'homme) +- add runtime selection of float ABI on ARM (Thomas Preud'homme) Platforms: - support Debian GNU/kfreeBSD 64bit userspace (Thomas Preud'homme) diff --git a/arm-gen.c b/arm-gen.c index 05bccb0..bc24f70 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -141,6 +141,13 @@ enum { #define ELF_START_ADDR 0x00008000 #define ELF_PAGE_SIZE 0x1000 +enum float_abi { + ARM_SOFTFP_FLOAT, + ARM_HARD_FLOAT, +}; + +enum float_abi float_abi; + /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ @@ -169,7 +176,7 @@ static int leaffunc; #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) static CType float_type, double_type, func_float_type, func_double_type; -ST_FUNC void arm_init_types(void) +ST_FUNC void arm_init(struct TCCState *s) { float_type.t = VT_FLOAT; double_type.t = VT_DOUBLE; @@ -177,12 +184,14 @@ ST_FUNC void arm_init_types(void) func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD); func_double_type.t = VT_FUNC; func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD); + + float_abi = s->float_abi; } #else #define func_float_type func_old_type #define func_double_type func_old_type #define func_ldouble_type func_old_type -ST_FUNC void arm_init_types(void) {} +ST_FUNC void arm_init(void) {} #endif static int two2mask(int a,int b) { @@ -195,6 +204,16 @@ static int regmask(int r) { /******************************************************/ +#ifdef TCC_ARM_EABI +char *default_elfinterp(struct TCCState *s) +{ + if (s->float_abi == ARM_HARD_FLOAT) + return "/lib/ld-linux-armhf.so.3"; + else + return "/lib/ld-linux.so.3"; +} +#endif + void o(uint32_t i) { /* this is a good place to start adding big-endian support*/ @@ -841,22 +860,19 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) { #ifdef TCC_ARM_EABI int size, align; size = type_size(vt, &align); -#ifdef TCC_ARM_HARDFLOAT - if (!variadic && (is_float(vt->t) || is_hgen_float_aggr(vt))) { + if (float_abi == ARM_HARD_FLOAT && !variadic && + (is_float(vt->t) || is_hgen_float_aggr(vt))) { *ret_align = 8; ret->ref = NULL; ret->t = VT_DOUBLE; return (size + 7) >> 3; - } else -#endif - if (size > 4) { - return 0; - } else { + } else if (size <= 4) { *ret_align = 4; ret->ref = NULL; ret->t = VT_INT; return 1; - } + } else + return 0; #else return 0; #endif @@ -1171,9 +1187,11 @@ void gfunc_call(int nb_args) int todo; struct plan plan; -#ifdef TCC_ARM_HARDFLOAT - variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); - corefloat = variadic || floats_in_core_regs(&vtop[-nb_args]); +#ifdef TCC_ARM_EABI + if (float_abi == ARM_HARD_FLOAT) { + variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); + corefloat = variadic || floats_in_core_regs(&vtop[-nb_args]); + } #endif /* cannot let cpu flags if other instruction are generated. Also avoid leaving VT_JMP anywhere except on the top of the stack because it would complicate @@ -1199,9 +1217,9 @@ void gfunc_call(int nb_args) gcall_or_jmp(0); if (args_size) gadd_sp(args_size); /* pop all parameters passed on the stack */ -#ifdef TCC_ARM_EABI -#ifdef TCC_ARM_VFP - if(corefloat && is_float(vtop->type.ref->type.t)) { +#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) + if(float_abi == ARM_SOFTFP_FLOAT && corefloat && + is_float(vtop->type.ref->type.t)) { if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) { o(0xEE000A10); /*vmov s0, r0 */ } else { @@ -1209,7 +1227,6 @@ void gfunc_call(int nb_args) o(0xEE201B10); /* vmov.32 d0[1], r1 */ } } -#endif #endif vtop -= nb_args + 1; /* Pop all params and fct address from value stack */ leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */ @@ -1220,9 +1237,8 @@ void gfunc_prolog(CType *func_type) { Sym *sym,*sym2; int n, nf, size, align, struct_ret = 0; -#ifdef TCC_ARM_HARDFLOAT + int addr, pn, sn; /* pn=core, sn=stack */ struct avail_regs avregs = AVAIL_REGS_INITIALIZER; -#endif CType ret_type; sym = func_type->ref; @@ -1237,11 +1253,11 @@ void gfunc_prolog(CType *func_type) struct_ret = 1; func_vc = 12; /* Offset from fp of the place to store the result */ } - for(sym2=sym->next;sym2 && (n<4 || nf<16);sym2=sym2->next) { + for(sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) { size = type_size(&sym2->type, &align); -#ifdef TCC_ARM_HARDFLOAT - if (!func_var && (is_float(sym2->type.t) - || is_hgen_float_aggr(&sym2->type))) { +#ifdef TCC_ARM_EABI + if (float_abi == ARM_HARD_FLOAT && !func_var && + (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) { int tmpnf = assign_vfpreg(&avregs, align, size); tmpnf += (size + 3) / 4; nf = (tmpnf > nf) ? tmpnf : nf; @@ -1270,50 +1286,49 @@ void gfunc_prolog(CType *func_type) o(0xE92D5800); /* save fp, ip, lr */ o(0xE1A0B00D); /* mov fp, sp */ func_sub_sp_offset = ind; - o(0xE1A00000); /* nop, leave space for stack adjustment in epilogue */ - { - int addr, pn = struct_ret, sn = 0; /* pn=core, sn=stack */ + o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */ -#ifdef TCC_ARM_HARDFLOAT +#ifdef TCC_ARM_EABI + if (float_abi == ARM_HARD_FLOAT) { func_vc += nf * 4; avregs = AVAIL_REGS_INITIALIZER; + } #endif - while ((sym = sym->next)) { - CType *type; - type = &sym->type; - size = type_size(type, &align); - size = (size + 3) >> 2; - align = (align + 3) & ~3; -#ifdef TCC_ARM_HARDFLOAT - if (!func_var && (is_float(sym->type.t) - || is_hgen_float_aggr(&sym->type))) { - int fpn = assign_vfpreg(&avregs, align, size << 2); - if (fpn >= 0) { - addr = fpn * 4; - } else - goto from_stack; - } else + pn = struct_ret, sn = 0; + while ((sym = sym->next)) { + CType *type; + type = &sym->type; + size = type_size(type, &align); + size = (size + 3) >> 2; + align = (align + 3) & ~3; +#ifdef TCC_ARM_EABI + if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym->type.t) + || is_hgen_float_aggr(&sym->type))) { + int fpn = assign_vfpreg(&avregs, align, size << 2); + if (fpn >= 0) + addr = fpn * 4; + else + goto from_stack; + } else #endif - if (pn < 4) { + if (pn < 4) { #ifdef TCC_ARM_EABI pn = (pn + (align-1)/4) & -(align/4); #endif - addr = (nf + pn) * 4; - pn += size; - if (!sn && pn > 4) - sn = (pn - 4); - } else { -#ifdef TCC_ARM_HARDFLOAT + addr = (nf + pn) * 4; + pn += size; + if (!sn && pn > 4) + sn = (pn - 4); + } else { from_stack: -#endif #ifdef TCC_ARM_EABI sn = (sn + (align-1)/4) & -(align/4); #endif - addr = (n + nf + sn) * 4; - sn += size; - } - sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr+12); + addr = (n + nf + sn) * 4; + sn += size; } + sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), + addr + 12); } last_itod_magic=0; leaffunc = 1; @@ -1327,12 +1342,8 @@ void gfunc_epilog(void) int diff; /* Copy float return value to core register if base standard is used and float computation is made with VFP */ -#ifdef TCC_ARM_EABI - if ( -#ifdef TCC_ARM_HARDFLOAT - func_var && -#endif - is_float(func_vt.t)) { +#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) + if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) { if((func_vt.t & VT_BTYPE) == VT_FLOAT) o(0xEE100A10); /* fmrs r0, s0 */ else { diff --git a/libtcc.c b/libtcc.c index 154a266..127806f 100644 --- a/libtcc.c +++ b/libtcc.c @@ -757,7 +757,7 @@ static int tcc_compile(TCCState *s1) func_old_type.t = VT_FUNC; func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD); #ifdef TCC_TARGET_ARM - arm_init_types(); + arm_init(s1); #endif #if 0 @@ -945,9 +945,12 @@ LIBTCCAPI TCCState *tcc_new(void) tcc_define_symbol(s, "__ARMEL__", NULL); #if defined(TCC_ARM_EABI) tcc_define_symbol(s, "__ARM_EABI__", NULL); +#endif #if defined(TCC_ARM_HARDFLOAT) + s->float_abi = ARM_HARD_FLOAT; tcc_define_symbol(s, "__ARM_PCS_VFP", NULL); -#endif +#else + s->float_abi = ARM_SOFTFP_FLOAT; #endif #endif @@ -1628,6 +1631,7 @@ enum { TCC_OPTION_b, TCC_OPTION_g, TCC_OPTION_c, + TCC_OPTION_float_abi, TCC_OPTION_static, TCC_OPTION_shared, TCC_OPTION_soname, @@ -1680,6 +1684,9 @@ static const TCCOption tcc_options[] = { #endif { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "c", TCC_OPTION_c, 0 }, +#ifdef TCC_TARGET_ARM + { "mfloat-abi", TCC_OPTION_float_abi, TCC_OPTION_HAS_ARG }, +#endif { "static", TCC_OPTION_static, 0 }, { "shared", TCC_OPTION_shared, 0 }, { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG }, @@ -1817,6 +1824,18 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) case TCC_OPTION_c: s->output_type = TCC_OUTPUT_OBJ; break; +#ifdef TCC_TARGET_ARM + case TCC_OPTION_float_abi: + /* tcc doesn't support soft float yet */ + if (!strcmp(optarg, "softfp")) { + s->float_abi = ARM_SOFTFP_FLOAT; + tcc_undefine_symbol(s, "__ARM_PCS_VFP"); + } else if (!strcmp(optarg, "hard")) + s->float_abi = ARM_HARD_FLOAT; + else + tcc_error("unsupported float abi '%s'", optarg); + break; +#endif case TCC_OPTION_static: s->static_link = 1; break; diff --git a/tcc-doc.texi b/tcc-doc.texi index 540b4b6..e8832f6 100644 --- a/tcc-doc.texi +++ b/tcc-doc.texi @@ -176,6 +176,9 @@ In a script, it gives the following header: #!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11 @end example +@item -mfloat-abi (ARM only) +Select the float ABI. Possible values: @code{softfp} and @code{hard} + @item -dumpversion Print only the compiler version and nothing else. diff --git a/tcc.c b/tcc.c index 58f9007..9b5ca2e 100644 --- a/tcc.c +++ b/tcc.c @@ -224,7 +224,7 @@ static void display_info(TCCState *s, int what) print_paths("crt", s->crt_paths, s->nb_crt_paths); print_paths("libraries", s->library_paths, s->nb_library_paths); print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths); - printf("elfinterp:\n %s\n", CONFIG_TCC_ELFINTERP); + printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); break; } } diff --git a/tcc.h b/tcc.h index f3d868f..73285ae 100644 --- a/tcc.h +++ b/tcc.h @@ -221,21 +221,24 @@ # endif # elif defined __GNU__ # define CONFIG_TCC_ELFINTERP "/lib/ld.so" -# elif defined TCC_ARM_HARDFLOAT -# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-armhf.so.3" -# elif defined TCC_ARM_EABI -# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.3" # elif defined(TCC_TARGET_X86_64) # define CONFIG_TCC_ELFINTERP "/lib64/ld-linux-x86-64.so.2" # elif defined(TCC_UCLIBC) # define CONFIG_TCC_ELFINTERP "/lib/ld-uClibc.so.0" # elif defined(TCC_TARGET_PE) # define CONFIG_TCC_ELFINTERP "-" -# else +# elif !defined(TCC_ARM_EABI) # define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2" # endif #endif +/* var elf_interp dans *-gen.c */ +#ifdef CONFIG_TCC_ELFINTERP +# define DEFAULT_ELFINTERP(s) CONFIG_TCC_ELFINTERP +#else +# define DEFAULT_ELFINTERP(s) default_elfinterp(s) +#endif + /* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */ #define TCC_LIBGCC USE_MUADIR(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1" @@ -561,6 +564,9 @@ struct TCCState { /* compile with built-in memory and bounds checker */ int do_bounds_check; #endif +#ifdef TCC_TARGET_ARM + enum float_abi float_abi; /* float ABI of the generated code*/ +#endif addr_t text_addr; /* address of text section */ int has_text_addr; @@ -1329,7 +1335,10 @@ ST_FUNC void gen_opl(int op); /* ------------ arm-gen.c ------------ */ #ifdef TCC_TARGET_ARM -ST_FUNC void arm_init_types(void); +#ifdef TCC_ARM_EABI +ST_FUNC char *default_elfinterp(struct TCCState *s); +#endif +ST_FUNC void arm_init(struct TCCState *s); ST_FUNC uint32_t encbranch(int pos, int addr, int fail); ST_FUNC void gen_cvt_itof1(int t); #endif diff --git a/tccelf.c b/tccelf.c index aa3daac..43a8086 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1592,7 +1592,7 @@ static int elf_output_file(TCCState *s1, const char *filename) /* allow override the dynamic loader */ const char *elfint = getenv("LD_SO"); if (elfint == NULL) - elfint = CONFIG_TCC_ELFINTERP; + elfint = DEFAULT_ELFINTERP(s1); /* add interpreter section only if executable */ interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC); interp->sh_addralign = 1; -- cgit v1.3.1 From ba286136bf8e48c71ffd6c2fd9ce97e64a6eeeb1 Mon Sep 17 00:00:00 2001 From: Austin English Date: Thu, 6 Mar 2014 12:29:19 -0800 Subject: libtcc: ignore linker optizimization and as-needed options. This allows compiling some packages from Gentoo's portage --- libtcc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'libtcc.c') diff --git a/libtcc.c b/libtcc.c index 127806f..dc78643 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1560,6 +1560,10 @@ static int tcc_set_linker(TCCState *s, const char *option) } else goto err; + } else if (link_option(option, "as-needed", &p)) { + ignoring = 1; + } else if (link_option(option, "O", &p)) { + ignoring = 1; } else if (link_option(option, "rpath=", &p)) { s->rpath = copy_linker_arg(p); } else if (link_option(option, "section-alignment=", &p)) { -- cgit v1.3.1 From ad9568060eefbf79073f260249fe1ff8df59bf53 Mon Sep 17 00:00:00 2001 From: mingodad Date: Tue, 25 Mar 2014 18:06:14 +0000 Subject: A possible fix for the memory leak reported by valgrind when running tcctest.c with tcc. --- libtcc.c | 2 ++ tccelf.c | 1 + 2 files changed, 3 insertions(+) (limited to 'libtcc.c') diff --git a/libtcc.c b/libtcc.c index dc78643..601999e 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1094,6 +1094,8 @@ LIBTCCAPI void tcc_delete(TCCState *s1) # endif #endif + if(s1->sym_attrs) tcc_free(s1->sym_attrs); + tcc_free(s1); } diff --git a/tccelf.c b/tccelf.c index 036dba3..6bde7d5 100644 --- a/tccelf.c +++ b/tccelf.c @@ -2444,6 +2444,7 @@ static int elf_output_file(TCCState *s1, const char *filename) tcc_free(sec_order); tcc_free(phdr); tcc_free(s1->sym_attrs); + s1->sym_attrs = NULL; return ret; } -- cgit v1.3.1 From 14bb8302c42576112472fdf7491dbb369c3e6db5 Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 27 Mar 2014 22:15:45 +0000 Subject: Fix a incorrect size for malloc. --- libtcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libtcc.c') diff --git a/libtcc.c b/libtcc.c index 601999e..9f486f3 100644 --- a/libtcc.c +++ b/libtcc.c @@ -330,7 +330,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 = tcc_mallocz(sizeof(Section) + strlen(name)+1); strcpy(sec->name, name); sec->sh_type = sh_type; sec->sh_flags = sh_flags; -- cgit v1.3.1 From 700c2f769bd5e49a2a7e93119a6ad51d704d857d Mon Sep 17 00:00:00 2001 From: mingodad Date: Fri, 28 Mar 2014 20:25:39 +0000 Subject: Remove the fix from my last commit, it was pointed by scan-build and is a false positive, thanks to grischka for pointing it. --- libtcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libtcc.c') diff --git a/libtcc.c b/libtcc.c index 9f486f3..601999e 100644 --- a/libtcc.c +++ b/libtcc.c @@ -330,7 +330,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)+1); + sec = tcc_mallocz(sizeof(Section) + strlen(name)); strcpy(sec->name, name); sec->sh_type = sh_type; sec->sh_flags = sh_flags; -- cgit v1.3.1 From 0961a38493c545cd23a791cf66b45d8fc78accbd Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 7 Apr 2014 00:26:36 +0200 Subject: Declare wint_t in when needed Some old glibcs require to provide wint_t, accomodate them. --- include/stddef.h | 15 +++++++++++++++ libtcc.c | 9 +++++++++ 2 files changed, 24 insertions(+) (limited to 'libtcc.c') diff --git a/include/stddef.h b/include/stddef.h index fbc61fc..eaf0669 100644 --- a/include/stddef.h +++ b/include/stddef.h @@ -26,3 +26,18 @@ typedef unsigned long long int uint64_t; void *alloca(size_t size); #endif + +/* Older glibc require a wint_t from (when requested + by __need_wint_t, as otherwise stddef.h isn't allowed to + define this type). Note that this must be outside the normal + _STDDEF_H guard, so that it works even when we've included the file + already (without requring wint_t). Some other libs define _WINT_T + if they've already provided that type, so we can use that as guard. + TCC defines __WINT_TYPE__ for us. */ +#if defined (__need_wint_t) +#ifndef _WINT_T +#define _WINT_T +typedef __WINT_TYPE__ wint_t; +#endif +#undef __need_wint_t +#endif diff --git a/libtcc.c b/libtcc.c index 601999e..cc84cd7 100644 --- a/libtcc.c +++ b/libtcc.c @@ -988,8 +988,17 @@ LIBTCCAPI TCCState *tcc_new(void) #ifdef TCC_TARGET_PE tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short"); + tcc_define_symbol(s, "__WINT_TYPE__", "unsigned short"); #else tcc_define_symbol(s, "__WCHAR_TYPE__", "int"); + /* wint_t is unsigned int by default, but (signed) int on BSDs + and unsigned short on windows. Other OSes might have still + other conventions, sigh. */ +#if defined(__FreeBSD__) || defined (__FreeBSD_kernel__) + tcc_define_symbol(s, "__WINT_TYPE__", "int"); +#else + tcc_define_symbol(s, "__WINT_TYPE__", "unsigned int"); +#endif #endif #ifndef TCC_TARGET_PE -- cgit v1.3.1 From f90bad092510c751afbd9286b9946691a416d2a1 Mon Sep 17 00:00:00 2001 From: grischka Date: Mon, 7 Apr 2014 11:20:45 +0200 Subject: tests2: cleanup - remove -norunsrc switch Meaning and usage (-run -norun...???) look sort of screwed. Also general usefulness is unclear, so it was actually to support exactly one (not even very interesting) test This partially reverts e31579b0769e1f9c0947d12e83316d1149307b1a --- libtcc.c | 9 +-------- tcc.c | 1 - tests/tests2/31_args.c | 2 +- tests/tests2/31_args.expect | 11 +++++------ tests/tests2/Makefile | 35 +++++++++++++++++++---------------- 5 files changed, 26 insertions(+), 32 deletions(-) (limited to 'libtcc.c') diff --git a/libtcc.c b/libtcc.c index cc84cd7..5df1949 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1666,7 +1666,6 @@ enum { TCC_OPTION_pedantic, TCC_OPTION_pthread, TCC_OPTION_run, - TCC_OPTION_norunsrc, TCC_OPTION_v, TCC_OPTION_w, TCC_OPTION_pipe, @@ -1709,7 +1708,6 @@ static const TCCOption tcc_options[] = { { "pedantic", TCC_OPTION_pedantic, 0}, { "pthread", TCC_OPTION_pthread, 0}, { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, - { "norunsrc", TCC_OPTION_norunsrc, 0 }, { "rdynamic", TCC_OPTION_rdynamic, 0 }, { "r", TCC_OPTION_r, 0 }, { "s", TCC_OPTION_s, 0 }, @@ -1748,7 +1746,6 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) const TCCOption *popt; const char *optarg, *r; int run = 0; - int norunsrc = 0; int pthread = 0; int optind = 0; @@ -1761,8 +1758,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) r = argv[optind++]; if (r[0] != '-' || r[1] == '\0') { /* add a new file */ - if (!run || !norunsrc) - dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r)); + dynarray_add((void ***)&s->files, &s->nb_files, tcc_strdup(r)); if (run) { optind--; /* argv[0] will be this file */ @@ -1888,9 +1884,6 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) tcc_set_options(s, optarg); run = 1; break; - case TCC_OPTION_norunsrc: - norunsrc = 1; - break; case TCC_OPTION_v: do ++s->verbose; while (*optarg++ == 'v'); break; diff --git a/tcc.c b/tcc.c index 9b5ca2e..74a5f1b 100644 --- a/tcc.c +++ b/tcc.c @@ -69,7 +69,6 @@ static void help(void) " -Bdir use 'dir' as tcc internal library and include path\n" " -MD generate target dependencies for make\n" " -MF depfile put generated dependencies here\n" - " -norunsrc Do not compile the file which is the first argument after -run.\n" ); } diff --git a/tests/tests2/31_args.c b/tests/tests2/31_args.c index 275f8cf..dcafed5 100644 --- a/tests/tests2/31_args.c +++ b/tests/tests2/31_args.c @@ -5,7 +5,7 @@ int main(int argc, char **argv) int Count; printf("hello world %d\n", argc); - for (Count = 0; Count < argc; Count++) + for (Count = 1; Count < argc; Count++) printf("arg %d: %s\n", Count, argv[Count]); return 0; diff --git a/tests/tests2/31_args.expect b/tests/tests2/31_args.expect index c392b67..8c60bfc 100644 --- a/tests/tests2/31_args.expect +++ b/tests/tests2/31_args.expect @@ -1,7 +1,6 @@ hello world 6 -arg 0: 31_args.c -arg 1: - -arg 2: arg1 -arg 3: arg2 -arg 4: arg3 -arg 5: arg4 +arg 1: arg1 +arg 2: arg2 +arg 3: arg3 +arg 4: arg4 +arg 5: arg5 diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index e5790c7..4d5546d 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -46,9 +46,11 @@ TESTS = \ 27_sizeof.test \ 28_strings.test \ 29_array_address.test \ + 30_hanoi.test \ 31_args.test \ 32_led.test \ 33_ternary_op.test \ + 34_array_assignment.test \ 35_sizeof.test \ 36_array_initialisers.test \ 37_sprintf.test \ @@ -60,6 +62,7 @@ TESTS = \ 43_void_param.test \ 44_scoped_declarations.test \ 45_empty_for.test \ + 46_grep.test \ 47_switch_return.test \ 48_nested_break.test \ 49_bracket_evaluation.test \ @@ -81,31 +84,31 @@ TESTS = \ # 34_array_assignment.test -- array assignment is not in C standard # 46_grep.test -- does not compile even with gcc +SKIP = 30_hanoi.test 34_array_assignment.test 46_grep.test + # some tests do not pass on all platforms, remove them for now ifeq ($(TARGETOS),Darwin) - TESTS := $(filter-out 40_stdio.test,$(TESTS)) + SKIP += 40_stdio.test endif ifdef CONFIG_WIN32 - TESTS := $(filter-out 24_math_library.test 28_strings.test,$(TESTS)) + SKIP += 24_math_library.test # don't have round() + SKIP += 28_strings.test # don't have r/index() / strings.h endif +# Some tests might need arguments +ARGS = +31_args.test : ARGS = arg1 arg2 arg3 arg4 arg5 + +all test: $(filter-out $(SKIP),$(TESTS)) + %.test: %.c %.expect @echo Test: $*... - @if [ "x`echo $* | grep args`" != "x" ]; \ - then $(TCC) $< -norunsrc -run $(notdir $<) - arg1 arg2 arg3 arg4 >$*.output 2>&1; \ - else $(TCC) -run $< >$*.output 2>&1; \ - ($(TCC) -o $*.exe $< && ./$*.exe) >$*.output2 2>&1; \ - fi || true - @if diff -bu $(<:.c=.expect) $*.output ; \ - then rm -f $*.output; \ - else exit 1; \ - fi - @if test -f $*.output2; then if diff -bu $(<:.c=.expect) $*.output2 ; \ - then rm -f $*.output2; \ - else exit 1; \ - fi; fi -all test: $(TESTS) + @$(TCC) -run $< $(ARGS) >$*.output 2>&1 || true + @diff -bu $*.expect $*.output && rm -f $*.output + + @($(TCC) $< -o $*.exe && ./$*.exe $(ARGS)) >$*.output2 2>&1 || true + @diff -bu $*.expect $*.output2 && rm -f $*.output2 $*.exe clean: rm -vf fred.txt *.output* *.exe -- cgit v1.3.1 From df0267b28799422393bfa70b5cf76608923ad8e7 Mon Sep 17 00:00:00 2001 From: minux Date: Fri, 11 Apr 2014 23:49:53 -0400 Subject: tcc, libtcc: fix build on windows with latest mingw. --- libtcc.c | 2 +- tcc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'libtcc.c') diff --git a/libtcc.c b/libtcc.c index 5df1949..a24ef2d 100644 --- a/libtcc.c +++ b/libtcc.c @@ -121,7 +121,7 @@ void dlclose(void *p) #endif #ifdef LIBTCC_AS_DLL -BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) +BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved) { if (DLL_PROCESS_ATTACH == dwReason) tcc_module = hDll; diff --git a/tcc.c b/tcc.c index 74a5f1b..392efca 100644 --- a/tcc.c +++ b/tcc.c @@ -78,7 +78,7 @@ static void help(void) #include static int execvp_win32(const char *prog, char **argv) { - int ret = spawnvp(P_NOWAIT, prog, (char *const*)argv); + int ret = spawnvp(P_NOWAIT, prog, (const char *const*)argv); if (-1 == ret) return ret; cwait(&ret, ret, WAIT_CHILD); -- cgit v1.3.1 From a9fda392a0d03d62f0bef0acd42ec82b29216ab3 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 14 Apr 2014 03:33:50 +0200 Subject: Parse assembler .hidden directive This makes TCCs assembler understand the '.hidden symbol' directive (and emits a STV_HIDDEN ELF symbol then). --- libtcc.c | 3 +++ tccasm.c | 12 ++++++++---- tcctok.h | 1 + 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'libtcc.c') diff --git a/libtcc.c b/libtcc.c index a24ef2d..05abaef 100644 --- a/libtcc.c +++ b/libtcc.c @@ -508,6 +508,9 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, if (sym->type.t & VT_IMPORT) other |= 4; } +#else + if (! (sym->type.t & VT_STATIC)) + other = (sym->type.t & VT_VIS_MASK) >> VT_VIS_SHIFT; #endif if (tcc_state->leading_underscore && can_add_underscore) { buf1[0] = '_'; diff --git a/tccasm.c b/tccasm.c index 1c6a65d..38efe1c 100644 --- a/tccasm.c +++ b/tccasm.c @@ -483,6 +483,7 @@ static void asm_parse_directive(TCCState *s1) case TOK_ASM_globl: case TOK_ASM_global: case TOK_ASM_weak: + case TOK_ASM_hidden: tok1 = tok; do { Sym *sym; @@ -493,9 +494,12 @@ static void asm_parse_directive(TCCState *s1) sym = label_push(&s1->asm_labels, tok, 0); sym->type.t = VT_VOID; } - sym->type.t &= ~VT_STATIC; + if (tok1 != TOK_ASM_hidden) + sym->type.t &= ~VT_STATIC; if (tok1 == TOK_ASM_weak) sym->type.t |= VT_WEAK; + else if (tok1 == TOK_ASM_hidden) + sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT; next(); } while (tok == ','); break; @@ -588,12 +592,12 @@ static void asm_parse_directive(TCCState *s1) tcc_error("label not found: %s", get_tok_str(tok, NULL)); } - next(); - skip(','); /* XXX .size name,label2-label1 */ if (s1->warn_unsupported) tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL)); + next(); + skip(','); while (tok != '\n' && tok != CH_EOF) { next(); } @@ -622,7 +626,7 @@ static void asm_parse_directive(TCCState *s1) } if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) { - sym->type.t = VT_FUNC; + sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC; } else if (s1->warn_unsupported) tcc_warning("change type of '%s' from 0x%x to '%s' ignored", diff --git a/tcctok.h b/tcctok.h index d8c0344..735ccdd 100644 --- a/tcctok.h +++ b/tcctok.h @@ -266,6 +266,7 @@ DEF_ASM(file) DEF_ASM(globl) DEF_ASM(global) + DEF_ASM(hidden) DEF_ASM(ident) DEF_ASM(size) DEF_ASM(type) -- cgit v1.3.1 From 2ac238fc507b64a8dd2d5d3d5c00210c1ffabea5 Mon Sep 17 00:00:00 2001 From: grischka Date: Thu, 17 Apr 2014 17:01:28 +0200 Subject: tccpe: adjust for new 'hidden' symbols feature in order to avoid conflicts with windows specific (ab)usage of the Elf32_Sym -> st_other field. --- libtcc.c | 12 +++++------- tcc.h | 4 ++++ tccpe.c | 16 ++++++++-------- 3 files changed, 17 insertions(+), 15 deletions(-) (limited to 'libtcc.c') diff --git a/libtcc.c b/libtcc.c index 05abaef..deda7e6 100644 --- a/libtcc.c +++ b/libtcc.c @@ -491,22 +491,22 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, #ifdef TCC_TARGET_PE if (sym->type.t & VT_EXPORT) - other |= 1; + other |= ST_PE_EXPORT; if (sym_type == STT_FUNC && sym->type.ref) { Sym *ref = sym->type.ref; if (ref->a.func_export) - other |= 1; + other |= ST_PE_EXPORT; if (ref->a.func_call == FUNC_STDCALL && can_add_underscore) { sprintf(buf1, "_%s@%d", name, ref->a.func_args * PTR_SIZE); name = buf1; - other |= 2; + other |= ST_PE_STDCALL; can_add_underscore = 0; } } else { if (find_elf_sym(tcc_state->dynsymtab_section, name)) - other |= 4; + other |= ST_PE_IMPORT; if (sym->type.t & VT_IMPORT) - other |= 4; + other |= ST_PE_IMPORT; } #else if (! (sym->type.t & VT_STATIC)) @@ -1316,8 +1316,6 @@ LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val) So it is handled here as if it were in a DLL. */ pe_putimport(s, 0, name, (uintptr_t)val); #else - /* XXX: Same problem on linux but currently "solved" elsewhere - via the rather dirty 'runtime_plt_and_got' hack. */ add_elf_sym(symtab_section, (uintptr_t)val, 0, ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, SHN_ABS, name); diff --git a/tcc.h b/tcc.h index ab14b38..c93cedf 100644 --- a/tcc.h +++ b/tcc.h @@ -1392,6 +1392,10 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2); #ifdef TCC_TARGET_X86_64 ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack); #endif +/* symbol properties stored in Elf32_Sym->st_other */ +# define ST_PE_EXPORT 0x10 +# define ST_PE_IMPORT 0x20 +# define ST_PE_STDCALL 0x40 #endif /* ------------ tccrun.c ----------------- */ diff --git a/tccpe.c b/tccpe.c index 6ee3865..b972d75 100644 --- a/tccpe.c +++ b/tccpe.c @@ -363,7 +363,7 @@ struct pe_info { static const char *pe_export_name(TCCState *s1, ElfW(Sym) *sym) { const char *name = symtab_section->link->data + sym->st_name; - if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & 2)) + if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL)) return name + 1; return name; } @@ -378,7 +378,7 @@ static int pe_find_import(TCCState * s1, ElfW(Sym) *sym) s = pe_export_name(s1, sym); if (n) { /* second try: */ - if (sym->st_other & 2) { + if (sym->st_other & ST_PE_STDCALL) { /* try w/0 stdcall deco (windows API convention) */ p = strrchr(s, '@'); if (!p || s[0] != '_') @@ -899,7 +899,7 @@ static void pe_build_exports(struct pe_info *pe) for (sym_index = 1; sym_index < sym_end; ++sym_index) { sym = (ElfW(Sym)*)symtab_section->data + sym_index; name = pe_export_name(pe->s1, sym); - if ((sym->st_other & 1) + if ((sym->st_other & ST_PE_EXPORT) /* export only symbols from actually written sections */ && pe->s1->sections[sym->st_shndx]->sh_addr) { p = tcc_malloc(sizeof *p); @@ -908,9 +908,9 @@ static void pe_build_exports(struct pe_info *pe) dynarray_add((void***)&sorted, &sym_count, p); } #if 0 - if (sym->st_other & 1) + if (sym->st_other & ST_PE_EXPORT) printf("export: %s\n", name); - if (sym->st_other & 2) + if (sym->st_other & ST_PE_STDCALL) printf("stdcall: %s\n", name); #endif } @@ -1282,7 +1282,7 @@ static int pe_check_symbols(struct pe_info *pe) /* patch the original symbol */ sym->st_value = offset; sym->st_shndx = text_section->sh_num; - sym->st_other &= ~1; /* do not export */ + sym->st_other &= ~ST_PE_EXPORT; /* do not export */ continue; } @@ -1301,7 +1301,7 @@ static int pe_check_symbols(struct pe_info *pe) } else if (pe->s1->rdynamic && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { /* if -rdynamic option, then export all non local symbols */ - sym->st_other |= 1; + sym->st_other |= ST_PE_EXPORT; } } return ret; @@ -1463,7 +1463,7 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2) if (!sym->c) put_extern_sym(sym, NULL, 0, 0); esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; - if (!(esym->st_other & 4)) + if (!(esym->st_other & ST_PE_IMPORT)) return sv; // printf("import %04x %04x %04x %s\n", sv->type.t, sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL)); -- cgit v1.3.1