while last change fixed one part of label behaviour (undefined ones must be global) it again broke a different aspect (forward defs without .globl must stay local). This fixes both aspects. That a label is local instead of global is difficult to test without resorting to look at the symbol table or using two-file testcases, so we do without. In essence the local/global-ness of symbols should be the same between GAS and TCC for this input: .globl glob1 glob1: call glob1 .globl glob2 call glob2 glob2: glob3: .globl glob3 call glob3 glob4: call glob4 .globl glob4 call glob5 .globl glob5 glob5: call glob6 glob6: .globl glob6 locl1: call locl1 call locl2 locl2: unref1: unref2: .globl unref2 .globl unref3 unref3: call undef
Unified · Split
| @@ -52,7 +52,7 @@ ST_FUNC Sym* get_asm_sym(int name, Sym *csym) · 51 unmodified lines | |||
| 52 | Sym *sym = label_find(name); | 52 | Sym *sym = label_find(name); |
| 53 | if (!sym) { | 53 | if (!sym) { |
| 54 | sym = label_push(&tcc_state->asm_labels, name, 0); | 54 | sym = label_push(&tcc_state->asm_labels, name, 0); |
| 55 | sym->type.t = VT_VOID | VT_EXTERN; | 55 | sym->type.t = VT_VOID | VT_STATIC | VT_EXTERN; |
| 56 | if (!csym) { | 56 | if (!csym) { |
| 57 | csym = sym_find(name); | 57 | csym = sym_find(name); |
| 58 | /* We might be called for an asm block from inside a C routine | 58 | /* We might be called for an asm block from inside a C routine |
| @@ -72,7 +72,7 @@ ST_FUNC Sym* get_asm_sym(int name, Sym *csym) · 13 unmodified lines | |||
| 72 | sym->r = esym->st_shndx; | 72 | sym->r = esym->st_shndx; |
| 73 | sym->jnext = esym->st_value; | 73 | sym->jnext = esym->st_value; |
| 74 | /* XXX can't yet store st_size anywhere. */ | 74 | /* XXX can't yet store st_size anywhere. */ |
| 75 | sym->type.t &= ~VT_EXTERN; | 75 | sym->type.t = VT_VOID | (csym->type.t & VT_STATIC); |
| 76 | /* Mark that this asm symbol doesn't need to be fed back. */ | 76 | /* Mark that this asm symbol doesn't need to be fed back. */ |
| 77 | sym->a.dllimport = 1; | 77 | sym->a.dllimport = 1; |
| 78 | } | 78 | } |
| @@ -409,6 +409,24 @@ static Sym* set_symbol(TCCState *s1, int label) · 330 unmodified lines | |||
| 409 | return asm_new_label1(s1, label, 0, e.sym ? e.sym->r : SHN_ABS, n); | 409 | return asm_new_label1(s1, label, 0, e.sym ? e.sym->r : SHN_ABS, n); |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | /* Patch ELF symbol associated with SYM based on the assemblers | ||
| 413 | understanding. */ | ||
| 414 | static void patch_binding(Sym *sym) | ||
| 415 | { | ||
| 416 | ElfW(Sym) *esym; | ||
| 417 | if (0 == sym->c) | ||
| 418 | return; | ||
| 419 | esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; | ||
| 420 | if (sym->a.visibility) | ||
| 421 | esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1)) | ||
| 422 | | sym->a.visibility; | ||
| 423 | |||
| 424 | esym->st_info = ELFW(ST_INFO)(sym->a.weak ? STB_WEAK | ||
| 425 | : (sym->type.t & VT_STATIC) ? STB_LOCAL | ||
| 426 | : STB_GLOBAL, | ||
| 427 | ELFW(ST_TYPE)(esym->st_info)); | ||
| 428 | } | ||
| 429 | |||
| 412 | static void asm_free_labels(TCCState *st) | 430 | static void asm_free_labels(TCCState *st) |
| 413 | { | 431 | { |
| 414 | Sym *s, *s1; | 432 | Sym *s, *s1; |
| @@ -418,13 +436,17 @@ static void asm_free_labels(TCCState *st) · 3 unmodified lines | |||
| 418 | s1 = s->prev; | 436 | s1 = s->prev; |
| 419 | /* define symbol value in object file */ | 437 | /* define symbol value in object file */ |
| 420 | s->type.t &= ~VT_EXTERN; | 438 | s->type.t &= ~VT_EXTERN; |
| 421 | if (s->r && !s->a.dllimport) { | 439 | if (!s->a.dllimport) { |
| 422 | if (s->r == SHN_ABS) | 440 | if (s->r) { |
| 423 | sec = SECTION_ABS; | 441 | if (s->r == SHN_ABS) |
| 424 | else | 442 | sec = SECTION_ABS; |
| 425 | sec = st->sections[s->r]; | 443 | else |
| 426 | put_extern_sym2(s, sec, s->jnext, 0, 0); | 444 | sec = st->sections[s->r]; |
| 427 | } | 445 | put_extern_sym2(s, sec, s->jnext, 0, 0); |
| 446 | } else /* undefined symbols are global */ | ||
| 447 | s->type.t &= ~VT_STATIC; | ||
| 448 | } | ||
| 449 | patch_binding(s); | ||
| 428 | /* remove label */ | 450 | /* remove label */ |
| 429 | table_ident[s->v - TOK_IDENT]->sym_label = NULL; | 451 | table_ident[s->v - TOK_IDENT]->sym_label = NULL; |
| 430 | sym_free(s); | 452 | sym_free(s); |