misc fixes including: - tcc.c: fix "tcc -vv" for libtcc1.a on win32/PE - tccelf.c: fix a crash when GOT has no relocs (witn -nostdlib) - tccelf.c: fix stab linkage for zero n_strx - tccgen.c: fix stdcall decoration for array parameters int __stdcall func(char buf[10]) is _func@4 (was _func@12) - tccgen.c: fix static variables with nocode/nodata_wanted see tests2/96_nodata_wanted.c - tccrun.c: align sections using sh_addralign (for reliable function_alignment) - tests2/Makefile sort 100 after 99 - win32/include/sys/stat.h fix _stat and _wstat - x86_64-gen.c: win64/gfunc_call: fix a bug with xmmN register args previously overwrote valid other xmmN registers eventually
Unified · Split
| @@ -182,8 +182,10 @@ static void print_search_dirs(TCCState *s) · 181 unmodified lines | |||
| 182 | /* print_dirs("programs", NULL, 0); */ | 182 | /* print_dirs("programs", NULL, 0); */ |
| 183 | print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths); | 183 | print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths); |
| 184 | print_dirs("libraries", s->library_paths, s->nb_library_paths); | 184 | print_dirs("libraries", s->library_paths, s->nb_library_paths); |
| 185 | #ifdef TCC_TARGET_PE | ||
| 186 | printf("libtcc1:\n %s/lib/"TCC_LIBTCC1"\n", s->tcc_lib_path); | ||
| 187 | #else | ||
| 185 | printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path); | 188 | printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path); |
| 186 | #ifndef TCC_TARGET_PE | ||
| 187 | print_dirs("crt", s->crt_paths, s->nb_crt_paths); | 189 | print_dirs("crt", s->crt_paths, s->nb_crt_paths); |
| 188 | printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); | 190 | printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); |
| 189 | #endif | 191 | #endif |
| @@ -1364,6 +1364,8 @@ ST_FUNC void fill_got(TCCState *s1) · 1363 unmodified lines | |||
| 1364 | static void fill_local_got_entries(TCCState *s1) | 1364 | static void fill_local_got_entries(TCCState *s1) |
| 1365 | { | 1365 | { |
| 1366 | ElfW_Rel *rel; | 1366 | ElfW_Rel *rel; |
| 1367 | if (!s1->got->reloc) | ||
| 1368 | return; | ||
| 1367 | for_each_elem(s1->got->reloc, 0, rel, ElfW_Rel) { | 1369 | for_each_elem(s1->got->reloc, 0, rel, ElfW_Rel) { |
| 1368 | if (ELFW(R_TYPE)(rel->r_info) == R_RELATIVE) { | 1370 | if (ELFW(R_TYPE)(rel->r_info) == R_RELATIVE) { |
| 1369 | int sym_index = ELFW(R_SYM) (rel->r_info); | 1371 | int sym_index = ELFW(R_SYM) (rel->r_info); |
| @@ -2443,8 +2445,11 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, · 1073 unmodified lines | |||
| 2443 | a = (Stab_Sym *)(s->data + sm_table[stab_index].offset); | 2445 | a = (Stab_Sym *)(s->data + sm_table[stab_index].offset); |
| 2444 | b = (Stab_Sym *)(s->data + s->data_offset); | 2446 | b = (Stab_Sym *)(s->data + s->data_offset); |
| 2445 | o = sm_table[stabstr_index].offset; | 2447 | o = sm_table[stabstr_index].offset; |
| 2446 | while (a < b) | 2448 | while (a < b) { |
| 2447 | a->n_strx += o, a++; | 2449 | if (a->n_strx) |
| 2450 | a->n_strx += o; | ||
| 2451 | a++; | ||
| 2452 | } | ||
| 2448 | } | 2453 | } |
| 2449 | 2454 | ||
| 2450 | /* second short pass to update sh_link and sh_info fields of new | 2455 | /* second short pass to update sh_link and sh_info fields of new |
| @@ -4294,7 +4294,6 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td) · 4293 unmodified lines | |||
| 4294 | type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT); | 4294 | type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT); |
| 4295 | if ((pt.t & VT_BTYPE) == VT_VOID) | 4295 | if ((pt.t & VT_BTYPE) == VT_VOID) |
| 4296 | tcc_error("parameter declared as void"); | 4296 | tcc_error("parameter declared as void"); |
| 4297 | arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE; | ||
| 4298 | } else { | 4297 | } else { |
| 4299 | n = tok; | 4298 | n = tok; |
| 4300 | if (n < TOK_UIDENT) | 4299 | if (n < TOK_UIDENT) |
| @@ -4303,6 +4302,7 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td) · 2 unmodified lines | |||
| 4303 | next(); | 4302 | next(); |
| 4304 | } | 4303 | } |
| 4305 | convert_parameter_type(&pt); | 4304 | convert_parameter_type(&pt); |
| 4305 | arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE; | ||
| 4306 | s = sym_push(n | SYM_FIELD, &pt, 0, 0); | 4306 | s = sym_push(n | SYM_FIELD, &pt, 0, 0); |
| 4307 | *plast = s; | 4307 | *plast = s; |
| 4308 | plast = &s->next; | 4308 | plast = &s->next; |
| @@ -6856,11 +6856,16 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 2547 unmodified lines | |||
| 6856 | Sym *sym = NULL; | 6856 | Sym *sym = NULL; |
| 6857 | int saved_nocode_wanted = nocode_wanted; | 6857 | int saved_nocode_wanted = nocode_wanted; |
| 6858 | #ifdef CONFIG_TCC_BCHECK | 6858 | #ifdef CONFIG_TCC_BCHECK |
| 6859 | int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED; | 6859 | int bcheck; |
| 6860 | #endif | 6860 | #endif |
| 6861 | 6861 | ||
| 6862 | if (type->t & VT_STATIC) | 6862 | /* Always allocate static or global variables */ |
| 6863 | nocode_wanted |= NODATA_WANTED ? 0x40000000 : 0x80000000; | 6863 | if (v && (r & VT_VALMASK) == VT_CONST) |
| 6864 | nocode_wanted |= 0x80000000; | ||
| 6865 | |||
| 6866 | #ifdef CONFIG_TCC_BCHECK | ||
| 6867 | bcheck = tcc_state->do_bounds_check && !NODATA_WANTED; | ||
| 6868 | #endif | ||
| 6864 | 6869 | ||
| 6865 | flexible_array = NULL; | 6870 | flexible_array = NULL; |
| 6866 | if ((type->t & VT_BTYPE) == VT_STRUCT) { | 6871 | if ((type->t & VT_BTYPE) == VT_STRUCT) { |
| @@ -6926,7 +6931,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 59 unmodified lines | |||
| 6926 | align = 1; | 6931 | align = 1; |
| 6927 | } | 6932 | } |
| 6928 | 6933 | ||
| 6929 | if (NODATA_WANTED) | 6934 | if (!v && NODATA_WANTED) |
| 6930 | size = 0, align = 1; | 6935 | size = 0, align = 1; |
| 6931 | 6936 | ||
| 6932 | if ((r & VT_VALMASK) == VT_LOCAL) { | 6937 | if ((r & VT_VALMASK) == VT_LOCAL) { |
| @@ -7088,9 +7093,7 @@ static void gen_function(Sym *sym) · 155 unmodified lines | |||
| 7088 | if (sym->a.aligned) { | 7093 | if (sym->a.aligned) { |
| 7089 | size_t newoff = section_add(cur_text_section, 0, | 7094 | size_t newoff = section_add(cur_text_section, 0, |
| 7090 | 1 << (sym->a.aligned - 1)); | 7095 | 1 << (sym->a.aligned - 1)); |
| 7091 | if (ind != newoff) | 7096 | gen_fill_nops(newoff - ind); |
| 7092 | gen_fill_nops(newoff - ind); | ||
| 7093 | ind = newoff; | ||
| 7094 | } | 7097 | } |
| 7095 | /* NOTE: we patch the symbol size later */ | 7098 | /* NOTE: we patch the symbol size later */ |
| 7096 | put_extern_sym(sym, cur_text_section, ind, 0); | 7099 | put_extern_sym(sym, cur_text_section, ind, 0); |
| @@ -169,9 +169,12 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 168 unmodified lines | |||
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 | 171 | #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 |
| 172 | /* To avoid that x86 processors would reload cached instructions | ||
| 173 | each time when data is written in the near, we need to make | ||
| 174 | sure that code and data do not share the same 64 byte unit */ | ||
| 172 | #define RUN_SECTION_ALIGNMENT 63 | 175 | #define RUN_SECTION_ALIGNMENT 63 |
| 173 | #else | 176 | #else |
| 174 | #define RUN_SECTION_ALIGNMENT 15 | 177 | #define RUN_SECTION_ALIGNMENT 0 |
| 175 | #endif | 178 | #endif |
| 176 | 179 | ||
| 177 | /* relocate code. Return -1 on error, required size if ptr is NULL, | 180 | /* relocate code. Return -1 on error, required size if ptr is NULL, |
| @@ -179,8 +182,8 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 1 unmodified line | |||
| 179 | static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) | 182 | static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) |
| 180 | { | 183 | { |
| 181 | Section *s; | 184 | Section *s; |
| 182 | unsigned offset, length, fill, i, k; | 185 | unsigned offset, length, align, max_align, i, k, f; |
| 183 | addr_t mem; | 186 | addr_t mem, addr; |
| 184 | 187 | ||
| 185 | if (NULL == ptr) { | 188 | if (NULL == ptr) { |
| 186 | s1->nb_errors = 0; | 189 | s1->nb_errors = 0; |
| @@ -195,39 +198,32 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) · 8 unmodified lines | |||
| 195 | return -1; | 198 | return -1; |
| 196 | } | 199 | } |
| 197 | 200 | ||
| 198 | offset = 0, mem = (addr_t)ptr; | 201 | offset = max_align = 0, mem = (addr_t)ptr; |
| 199 | fill = -mem & RUN_SECTION_ALIGNMENT; | ||
| 200 | #ifdef _WIN64 | 202 | #ifdef _WIN64 |
| 201 | offset += sizeof (void*); | 203 | offset += sizeof (void*); /* space for function_table pointer */ |
| 202 | #endif | 204 | #endif |
| 203 | for (k = 0; k < 2; ++k) { | 205 | for (k = 0; k < 2; ++k) { |
| 206 | f = 0, addr = k ? mem : mem + ptr_diff; | ||
| 204 | for(i = 1; i < s1->nb_sections; i++) { | 207 | for(i = 1; i < s1->nb_sections; i++) { |
| 205 | s = s1->sections[i]; | 208 | s = s1->sections[i]; |
| 206 | if (0 == (s->sh_flags & SHF_ALLOC)) | 209 | if (0 == (s->sh_flags & SHF_ALLOC)) |
| 207 | continue; | 210 | continue; |
| 208 | if (k != !(s->sh_flags & SHF_EXECINSTR)) | 211 | if (k != !(s->sh_flags & SHF_EXECINSTR)) |
| 209 | continue; | 212 | continue; |
| 210 | offset += fill; | 213 | align = s->sh_addralign - 1; |
| 211 | if (!mem) | 214 | if (++f == 1 && align < RUN_SECTION_ALIGNMENT) |
| 212 | s->sh_addr = 0; | 215 | align = RUN_SECTION_ALIGNMENT; |
| 213 | else if (s->sh_flags & SHF_EXECINSTR) | 216 | if (max_align < align) |
| 214 | s->sh_addr = mem + offset + ptr_diff; | 217 | max_align = align; |
| 215 | else | 218 | offset += -(addr + offset) & align; |
| 216 | s->sh_addr = mem + offset; | 219 | s->sh_addr = mem ? addr + offset : 0; |
| 220 | offset += s->data_offset; | ||
| 217 | #if 0 | 221 | #if 0 |
| 218 | if (mem) | 222 | if (mem) |
| 219 | printf("%-16s +%02lx %p %04x\n", | 223 | printf("%-16s %p len %04x align %2d\n", |
| 220 | s->name, fill, (void*)s->sh_addr, (unsigned)s->data_offset); | 224 | s->name, (void*)s->sh_addr, (unsigned)s->data_offset, align + 1); |
| 221 | #endif | 225 | #endif |
| 222 | offset += s->data_offset; | ||
| 223 | fill = -(mem + offset) & 15; | ||
| 224 | } | 226 | } |
| 225 | #if RUN_SECTION_ALIGNMENT > 15 | ||
| 226 | /* To avoid that x86 processors would reload cached instructions each time | ||
| 227 | when data is written in the near, we need to make sure that code and data | ||
| 228 | do not share the same 64 byte unit */ | ||
| 229 | fill = -(mem + offset) & RUN_SECTION_ALIGNMENT; | ||
| 230 | #endif | ||
| 231 | } | 227 | } |
| 232 | 228 | ||
| 233 | /* relocate symbols */ | 229 | /* relocate symbols */ |
| @@ -236,7 +232,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) · 2 unmodified lines | |||
| 236 | return -1; | 232 | return -1; |
| 237 | 233 | ||
| 238 | if (0 == mem) | 234 | if (0 == mem) |
| 239 | return offset + RUN_SECTION_ALIGNMENT; | 235 | return offset + max_align; |
| 240 | 236 | ||
| 241 | #ifdef TCC_TARGET_PE | 237 | #ifdef TCC_TARGET_PE |
| 242 | s1->pe_imagebase = mem; | 238 | s1->pe_imagebase = mem; |
| @@ -55,11 +55,10 @@ te0:; · 54 unmodified lines | |||
| 55 | static char ds1 = 0; | 55 | static char ds1 = 0; |
| 56 | ts1:; | 56 | ts1:; |
| 57 | if (!SKIP) { | 57 | if (!SKIP) { |
| 58 | static void *p = (void*)&main; | 58 | void *p = (void*)&main; |
| 59 | static char cc[] = "static string"; | 59 | char cc[] = "static string"; |
| 60 | static double d = 8.0; | 60 | double d = 8.0; |
| 61 | 61 | struct __attribute__((packed)) { | |
| 62 | static struct __attribute__((packed)) { | ||
| 63 | unsigned x : 12; | 62 | unsigned x : 12; |
| 64 | unsigned char y : 7; | 63 | unsigned char y : 7; |
| 65 | unsigned z : 28, a: 4, b: 5; | 64 | unsigned z : 28, a: 4, b: 5; |
| @@ -81,4 +80,19 @@ te1:; · 15 unmodified lines | |||
| 81 | /*printf("# %d/%d\n", dl, tl);*/ | 80 | /*printf("# %d/%d\n", dl, tl);*/ |
| 82 | } | 81 | } |
| 83 | 82 | ||
| 83 | #elif defined test_static_data | ||
| 84 | |||
| 85 | #include <stdio.h> | ||
| 86 | int main(int argc, char **argv) | ||
| 87 | { | ||
| 88 | goto there; | ||
| 89 | if (0) { | ||
| 90 | static int a = 1; | ||
| 91 | printf("hello\n"); /* the "hello\n" string is still suppressed */ | ||
| 92 | there: | ||
| 93 | printf("a = %d\n", a); | ||
| 94 | } | ||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | |||
| 84 | #endif | 98 | #endif |
| @@ -21,3 +21,6 @@ size of data/text: · 20 unmodified lines | |||
| 21 | [test_data_suppression_on] | 21 | [test_data_suppression_on] |
| 22 | size of data/text: | 22 | size of data/text: |
| 23 | zero/zero | 23 | zero/zero |
| 24 | |||
| 25 | [test_static_data] | ||
| 26 | a = 1 | ||
| @@ -3,7 +3,9 @@ include $(TOP)/Makefile · 2 unmodified lines | |||
| 3 | SRC = $(TOPSRC)/tests/tests2 | 3 | SRC = $(TOPSRC)/tests/tests2 |
| 4 | VPATH = $(SRC) | 4 | VPATH = $(SRC) |
| 5 | 5 | ||
| 6 | TESTS = $(patsubst %.c,%.test,$(sort $(notdir $(wildcard $(SRC)/*.c)))) | 6 | TESTS = $(patsubst %.c,%.test,\ |
| 7 | $(sort $(notdir $(wildcard $(SRC)/??_*.c)))\ | ||
| 8 | $(sort $(notdir $(wildcard $(SRC)/???_*.c)))) | ||
| 7 | 9 | ||
| 8 | # some tests do not pass on all platforms, remove them for now | 10 | # some tests do not pass on all platforms, remove them for now |
| 9 | SKIP = 34_array_assignment.test # array assignment is not in C standard | 11 | SKIP = 34_array_assignment.test # array assignment is not in C standard |
| @@ -81,9 +81,9 @@ extern "C" { · 80 unmodified lines | |||
| 81 | #else | 81 | #else |
| 82 | #define _fstat _fstat64i32 | 82 | #define _fstat _fstat64i32 |
| 83 | #define _fstati64 _fstat64 | 83 | #define _fstati64 _fstat64 |
| 84 | #define _stat _stat64i32 | 84 | #define _stat _stat64 |
| 85 | #define _stati64 _stat64 | 85 | #define _stati64 _stat64 |
| 86 | #define _wstat _wstat64i32 | 86 | #define _wstat _wstat64 |
| 87 | #define _wstati64 _wstat64 | 87 | #define _wstati64 _wstat64 |
| 88 | #endif | 88 | #endif |
| 89 | 89 | ||
| @@ -877,19 +877,18 @@ void gfunc_call(int nb_args) · 876 unmodified lines | |||
| 877 | if (is_sse_float(vtop->type.t)) { | 877 | if (is_sse_float(vtop->type.t)) { |
| 878 | if (tcc_state->nosse) | 878 | if (tcc_state->nosse) |
| 879 | tcc_error("SSE disabled"); | 879 | tcc_error("SSE disabled"); |
| 880 | gv(RC_XMM0); /* only use one float register */ | ||
| 881 | if (arg >= REGN) { | 880 | if (arg >= REGN) { |
| 881 | gv(RC_XMM0); | ||
| 882 | /* movq %xmm0, j*8(%rsp) */ | 882 | /* movq %xmm0, j*8(%rsp) */ |
| 883 | gen_offs_sp(0xd60f66, 0x100, arg*8); | 883 | gen_offs_sp(0xd60f66, 0x100, arg*8); |
| 884 | } else { | 884 | } else { |
| 885 | /* movaps %xmm0, %xmmN */ | 885 | /* Load directly to xmmN register */ |
| 886 | o(0x280f); | 886 | gv(RC_XMM0 << arg); |
| 887 | o(0xc0 + (arg << 3)); | ||
| 888 | d = arg_prepare_reg(arg); | 887 | d = arg_prepare_reg(arg); |
| 889 | /* mov %xmm0, %rxx */ | 888 | /* mov %xmmN, %rxx */ |
| 890 | o(0x66); | 889 | o(0x66); |
| 891 | orex(1,d,0, 0x7e0f); | 890 | orex(1,d,0, 0x7e0f); |
| 892 | o(0xc0 + REG_VALUE(d)); | 891 | o(0xc0 + arg*8 + REG_VALUE(d)); |
| 893 | } | 892 | } |
| 894 | } else { | 893 | } else { |
| 895 | if (bt == VT_STRUCT) { | 894 | if (bt == VT_STRUCT) { |