History

tccasm: Unify C and asm symbol table

This makes the asm symbols use the same members as the C symbols for global decls, e.g. using the ELF symbol to hold offset and section. That allows us to use only one symbol table for C and asm symbols and to get rid of hacks to synch between them. We still need some special handling for symbols that come purely from asm sources.

Michael Matz committed 8 years ago

Commit 9e0d23c1 parent 3494e5d8 files · +165 −189Browse files

Unified · Split

8 files
  1. i386-asm.c +7 −8
  2. tcc.h +7 −4
  3. tccasm.c +90 −152
  4. tccelf.c +9 −3
  5. tccgen.c +42 −21
  6. tccpp.c +0 −1
  7. tests/asm-c-connect-1.c +7 −0
  8. tests/asm-c-connect-2.c +3 −0
i386-asm.c+7−8
@@ -500,12 +500,13 @@ ST_FUNC void gen_expr64(ExprValue *pe) · 499 unmodified lines
500500 static void gen_disp32(ExprValue *pe)
501501 {
502502 Sym *sym = pe->sym;
503− if (sym && sym->r == cur_text_section->sh_num) {
503+ ElfSym *esym = elfsym(sym);
504+ if (esym && esym->st_shndx == cur_text_section->sh_num) {
504505 /* same section: we can output an absolute value. Note
505506 that the TCC compiler behaves differently here because
506507 it always outputs a relocation to ease (future) code
507508 elimination in the linker */
508− gen_le32(pe->v + sym->jnext - ind - 4);
509+ gen_le32(pe->v + esym->st_value - ind - 4);
509510 } else {
510511 if (sym && sym->type.t == VT_VOID) {
511512 sym->type.t = VT_FUNC;
@@ -1017,16 +1018,14 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 505 unmodified lines
10171018 if (pa->instr_type & OPC_B)
10181019 v += s >= 1;
10191020 if (nb_ops == 1 && pa->op_type[0] == OPT_DISP8) {
1020− Sym *sym;
1021+ ElfSym *esym;
10211022 int jmp_disp;
10221023
10231024 /* see if we can really generate the jump with a byte offset */
1024− sym = ops[0].e.sym;
1025− if (!sym)
1025+ esym = elfsym(ops[0].e.sym);
1026+ if (!esym || esym->st_shndx != cur_text_section->sh_num)
10261027 goto no_short_jump;
1027− if (sym->r != cur_text_section->sh_num)
1028− goto no_short_jump;
1029− jmp_disp = ops[0].e.v + sym->jnext - ind - 2 - (v >= 0xff);
1028+ jmp_disp = ops[0].e.v + esym->st_value - ind - 2 - (v >= 0xff);
10301029 if (jmp_disp == (int8_t)jmp_disp) {
10311030 /* OK to generate jump */
10321031 ops[0].e.sym = 0;
tcc.h+7−4
@@ -356,6 +356,7 @@ extern long double strtold (const char *__nptr, char **__endptr); · 355 unmodified lines
356356 #endif
357357 /* target address type */
358358 #define addr_t ElfW(Addr)
359+#define ElfSym ElfW(Sym)
359360
360361 #if PTR_SIZE == 8 && !defined TCC_TARGET_PE
361362 # define LONG_SIZE 8
@@ -383,7 +384,6 @@ typedef struct TokenSym { · 21 unmodified lines
383384 struct Sym *sym_label; /* direct pointer to label */
384385 struct Sym *sym_struct; /* direct pointer to structure */
385386 struct Sym *sym_identifier; /* direct pointer to identifier */
386− struct Sym *sym_asm_label; /* direct pointer to asm label */
387387 int tok; /* token number */
388388 int len;
389389 char str[1];
@@ -440,9 +440,8 @@ struct SymAttr { · 50 unmodified lines
440440 visibility : 2,
441441 dllexport : 1,
442442 dllimport : 1,
443− asmcsym : 1,
444443 asmexport : 1,
445− unused : 3;
444+ unused : 4;
446445 };
447446
448447 /* function attributes or temporary attributes for parsing */
@@ -799,6 +798,7 @@ struct TCCState { · 350 unmodified lines
799798 int nb_sym_attrs;
800799 /* tiny assembler state */
801800 Sym *asm_labels;
801+ ElfSym esym_dot;
802802
803803 #ifdef TCC_TARGET_PE
804804 /* PE info */
@@ -1147,7 +1147,7 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c); · 342 unmodified lines
11471147 ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep);
11481148 ST_INLN Sym *struct_find(int v);
11491149 ST_INLN Sym *sym_find(int v);
1150−ST_FUNC Sym *global_identifier_push(int v, int t, int c);
1150+ST_FUNC Sym *global_identifier_push_1(Sym **, int v, int t, int c);
11511151
11521152 ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
11531153 ST_FUNC int tcc_open(TCCState *s1, const char *filename);
@@ -1316,6 +1316,7 @@ ST_INLN int is_float(int t); · 162 unmodified lines
13161316 ST_FUNC int ieee_finite(double d);
13171317 ST_FUNC void test_lvalue(void);
13181318 ST_FUNC void vpushi(int v);
1319+ST_FUNC ElfSym *elfsym(Sym *);
13191320 ST_FUNC Sym *external_global_sym(int v, CType *type, int r);
13201321 ST_FUNC void vset(CType *type, int r, int v);
13211322 ST_FUNC void vswap(void);
@@ -1618,6 +1619,8 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp); · 296 unmodified lines
16181619 # define ST_PE_IMPORT 0x20
16191620 # define ST_PE_STDCALL 0x40
16201621 #endif
1622+#define ST_ASM_SET 0x04
1623+
16211624 /* ------------ tccrun.c ----------------- */
16221625 #ifdef TCC_IS_NATIVE
16231626 #ifdef CONFIG_TCC_STATIC
tccasm.c+90−152
@@ -36,64 +36,40 @@ static Sym sym_dot; · 35 unmodified lines
3636
3737 static Sym *asm_label_find(int v)
3838 {
39− v -= TOK_IDENT;
40− if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
41− return NULL;
42− return table_ident[v]->sym_asm_label;
39+ Sym *sym = sym_find(v);
40+ while (sym && sym->sym_scope)
41+ sym = sym->prev_tok;
42+ return sym;
4343 }
4444
45−static Sym *asm_label_push(Sym **ptop, int v)
45+static Sym *asm_label_push(int v, int t)
4646 {
47− Sym *s, **ps;
48− s = sym_push2(ptop, v, 0, 0);
49− ps = &table_ident[v - TOK_IDENT]->sym_asm_label;
50− s->prev_tok = *ps;
51− *ps = s;
52− return s;
47+ Sym *sym = global_identifier_push_1(&tcc_state->asm_labels, v, t, 0);
48+ /* We always add VT_EXTERN, for sym definition that's tentative
49+ (for .set, removed for real defs), for mere references it's correct
50+ as is. */
51+ sym->type.t |= VT_VOID | VT_EXTERN;
52+ sym->r = VT_CONST | VT_SYM;
53+ return sym;
5354 }
5455
5556 /* Return a symbol we can use inside the assembler, having name NAME.
56− The assembler symbol table is different from the C symbol table
57− (and the Sym members are used differently). But we must be able
58− to look up file-global C symbols from inside the assembler, e.g.
59− for global asm blocks to be able to refer to defined C symbols.
60−
61− This routine gives back either an existing asm-internal
62− symbol, or a new one. In the latter case the new asm-internal
63− symbol is initialized with info from the C symbol table.
64−
65− If CSYM is non-null we take symbol info from it, otherwise
66− we look up NAME in the C symbol table and use that. */
57+ Symbols from asm and C source share a namespace. If we generate
58+ an asm symbol it's also a (file-global) C symbol, but it's
59+ either not accessible by name (like "L.123"), or its type information
60+ is such that it's not usable without a proper C declaration.
61+
62+ Sometimes we need symbols accessible by name from asm, which
63+ are anonymous in C, in this case CSYM can be used to transfer
64+ all information from that symbol to the (possibly newly created)
65+ asm symbol. */
6766 ST_FUNC Sym* get_asm_sym(int name, Sym *csym)
6867 {
6968 Sym *sym = asm_label_find(name);
7069 if (!sym) {
71− sym = asm_label_push(&tcc_state->asm_labels, name);
72− sym->type.t = VT_VOID | VT_EXTERN;
73− if (!csym) {
74− csym = sym_find(name);
75− /* We might be called for an asm block from inside a C routine
76− and so might have local decls on the identifier stack. Search
77− for the first global one. */
78− while (csym && csym->sym_scope)
79− csym = csym->prev_tok;
80− }
81− /* Now, if we have a defined global symbol copy over
82− section and offset. */
83− if (csym &&
84− ((csym->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST)) &&
85− csym->c) {
86− ElfW(Sym) *esym;
87− esym = &((ElfW(Sym) *)symtab_section->data)[csym->c];
88− sym->c = csym->c;
89− sym->r = esym->st_shndx;
90− sym->jnext = esym->st_value;
91− /* XXX can't yet store st_size anywhere. */
92− sym->type.t = VT_VOID | (csym->type.t & VT_STATIC);
93− /* Mark that this asm symbol doesn't need to be fed back. */
94− sym->a.asmcsym = 1;
95− sym->a.asmexport = !(csym->type.t & VT_STATIC);
96− }
70+ sym = asm_label_push(name, 0);
71+ if (csym)
72+ sym->c = csym->c;
9773 }
9874 return sym;
9975 }
@@ -118,16 +94,15 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe) · 18 unmodified lines
11894 sym = asm_label_find(label);
11995 if (*p == 'b') {
12096 /* backward : find the last corresponding defined label */
121− if (sym && sym->r == 0)
97+ if (sym && (!sym->c || elfsym(sym)->st_shndx == SHN_UNDEF))
12298 sym = sym->prev_tok;
12399 if (!sym)
124100 tcc_error("local label '%d' not found backward", n);
125101 } else {
126102 /* forward */
127− if (!sym || sym->r) {
103+ if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) {
128104 /* if the last label is defined, then define a new one */
129− sym = asm_label_push(&s1->asm_labels, label);
130− sym->type.t = VT_STATIC | VT_VOID | VT_EXTERN;
105+ sym = asm_label_push(label, VT_STATIC);
131106 }
132107 }
133108 pe->v = 0;
@@ -175,17 +150,20 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe) · 41 unmodified lines
175150 pe->sym = &sym_dot;
176151 pe->pcrel = 0;
177152 sym_dot.type.t = VT_VOID | VT_STATIC;
178− sym_dot.r = cur_text_section->sh_num;
179− sym_dot.jnext = ind;
153+ sym_dot.c = -1;
154+ tcc_state->esym_dot.st_shndx = cur_text_section->sh_num;
155+ tcc_state->esym_dot.st_value = ind;
180156 next();
181157 break;
182158 default:
183159 if (tok >= TOK_IDENT) {
160+ ElfSym *esym;
184161 /* label case : if the label was not found, add one */
185162 sym = get_asm_sym(tok, NULL);
186− if (sym->r == SHN_ABS) {
163+ esym = elfsym(sym);
164+ if (esym && esym->st_shndx == SHN_ABS) {
187165 /* if absolute symbol, no need to put a symbol value */
188− pe->v = sym->jnext;
166+ pe->v = esym->st_value;
189167 pe->sym = NULL;
190168 pe->pcrel = 0;
191169 } else {
@@ -299,20 +277,26 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe) · 107 unmodified lines
299277 } else if (pe->sym == e2.sym) {
300278 /* OK */
301279 pe->sym = NULL; /* same symbols can be subtracted to NULL */
302− } else if (pe->sym && pe->sym->r == e2.sym->r && pe->sym->r != 0) {
303− /* we also accept defined symbols in the same section */
304− pe->v += pe->sym->jnext - e2.sym->jnext;
305− pe->sym = NULL;
306− } else if (e2.sym->r == cur_text_section->sh_num) {
307− /* When subtracting a defined symbol in current section
308− this actually makes the value PC-relative. */
309− pe->v -= e2.sym->jnext - ind - 4;
310− pe->pcrel = 1;
311− e2.sym = NULL;
312− } else {
313− cannot_relocate:
314− tcc_error("invalid operation with label");
315− }
280+ } else {
281+ ElfSym *esym1, *esym2;
282+ esym1 = elfsym(pe->sym);
283+ esym2 = elfsym(e2.sym);
284+ if (esym1 && esym1->st_shndx == esym2->st_shndx
285+ && esym1->st_shndx != SHN_UNDEF) {
286+ /* we also accept defined symbols in the same section */
287+ pe->v += esym1->st_value - esym2->st_value;
288+ pe->sym = NULL;
289+ } else if (esym2->st_shndx == cur_text_section->sh_num) {
290+ /* When subtracting a defined symbol in current section
291+ this actually makes the value PC-relative. */
292+ pe->v -= esym2->st_value - ind - 4;
293+ pe->pcrel = 1;
294+ e2.sym = NULL;
295+ } else {
296+cannot_relocate:
297+ tcc_error("invalid operation with label");
298+ }
299+ }
316300 }
317301 }
318302 }
@@ -377,13 +361,15 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local, · 58 unmodified lines
377361 int sh_num, int value)
378362 {
379363 Sym *sym;
364+ ElfSym *esym;
380365
381366 sym = asm_label_find(label);
382367 if (sym) {
368+ esym = elfsym(sym);
383369 /* A VT_EXTERN symbol, even if it has a section is considered
384370 overridable. This is how we "define" .set targets. Real
385371 definitions won't have VT_EXTERN set. */
386− if (sym->r && !(sym->type.t & VT_EXTERN)) {
372+ if (esym && esym->st_shndx != SHN_UNDEF && !(sym->type.t & VT_EXTERN)) {
387373 /* the label is already defined */
388374 if (!is_local) {
389375 tcc_error("assembler label '%s' already defined",
@@ -395,14 +381,13 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local, · 5 unmodified lines
395381 }
396382 } else {
397383 new_label:
398− sym = asm_label_push(&s1->asm_labels, label);
399− /* If we need a symbol to hold a value, mark it as
400− tentative only (for .set). If this is for a real label
401− we'll remove VT_EXTERN. */
402− sym->type.t = VT_VOID | (is_local ? VT_STATIC : 0) | VT_EXTERN;
384+ sym = asm_label_push(label, is_local ? VT_STATIC : 0);
403385 }
404− sym->r = sh_num;
405− sym->jnext = value;
386+ if (!sym->c)
387+ put_extern_sym2(sym, NULL, 0, 0, 0);
388+ esym = elfsym(sym);
389+ esym->st_shndx = sh_num;
390+ esym->st_value = value;
406391 return sym;
407392 }
408393
@@ -417,79 +402,41 @@ static Sym* set_symbol(TCCState *s1, int label) · 8 unmodified lines
417402 {
418403 long n;
419404 ExprValue e;
405+ Sym *sym;
406+ ElfSym *esym;
420407 next();
421408 asm_expr(s1, &e);
422409 n = e.v;
423− if (e.sym)
424− n += e.sym->jnext;
425− return asm_new_label1(s1, label, 0, e.sym ? e.sym->r : SHN_ABS, n);
426−}
427−
428−/* Patch ELF symbol associated with SYM based on the assemblers
429− understanding. */
430−static void patch_binding(Sym *sym)
431−{
432− ElfW(Sym) *esym;
433− if (0 == sym->c)
434− return;
435− esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
436− if (sym->a.visibility)
437− esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
438− | sym->a.visibility;
439−
440− esym->st_info = ELFW(ST_INFO)(sym->a.weak ? STB_WEAK
441− : (sym->type.t & VT_STATIC) ? STB_LOCAL
442− : STB_GLOBAL,
443− ELFW(ST_TYPE)(esym->st_info));
410+ esym = elfsym(e.sym);
411+ if (esym)
412+ n += esym->st_value;
413+ sym = asm_new_label1(s1, label, 0, esym ? esym->st_shndx : SHN_ABS, n);
414+ elfsym(sym)->st_other |= ST_ASM_SET;
415+ return sym;
444416 }
445417
446418 ST_FUNC void asm_free_labels(TCCState *st)
447419 {
448420 Sym *s, *s1;
449− Section *sec;
450421
451422 for(s = st->asm_labels; s != NULL; s = s1) {
452− int was_ext = s->type.t & VT_EXTERN;
423+ ElfSym *esym = elfsym(s);
453424 s1 = s->prev;
454− /* define symbol value in object file and care for updating
455− the C and asm symbols */
425+ /* Possibly update binding and visibility from asm directives. */
456426 s->type.t &= ~VT_EXTERN;
457− if (!s->a.asmcsym) {
458− Sym *csym = sym_find(s->v);
459− ElfW(Sym) *esym = NULL;
460− if (csym) {
461− s->a.asmexport |= !(csym->type.t & VT_STATIC);
462− if (csym->c) {
463− esym = &((ElfW(Sym) *)symtab_section->data)[csym->c];
464− if (s->c) {
465− /* We have generated code and possibly relocs
466− referencing the symtab entry s->c (the asm
467− ELF symbol). If that's undefined but the C
468− symbol is defined, copy over the info. */
469− ElfW(Sym) *asm_esym = &((ElfW(Sym) *)symtab_section->data)[s->c];
470− if (asm_esym->st_shndx == SHN_UNDEF) {
471− *asm_esym = *esym;
472− }
473− }
474− }
475− }
476− if (!s->a.asmexport)
477− s->type.t |= VT_STATIC;
478− if (s->r) {
479− if (s->r == SHN_ABS)
480− sec = SECTION_ABS;
481− else
482− sec = st->sections[s->r];
483− /* !was_ext so that we run into an multi-def error if
484− we defined it in C and in asm (non-tentatively) */
485− if (!esym || esym->st_shndx == SHN_UNDEF || !was_ext)
486− put_extern_sym2(s, sec, s->jnext, 0, 0);
487− } else /* undefined symbols are global */
488− s->type.t &= ~VT_STATIC, s->a.asmexport = 1;
489− patch_binding(s);
427+ if (esym) {
428+ if (!s->a.asmexport && esym->st_shndx != SHN_UNDEF)
429+ s->type.t |= VT_STATIC;
430+ if (s->a.visibility)
431+ esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
432+ | s->a.visibility;
433+ esym->st_info = ELFW(ST_INFO)(s->a.weak ? STB_WEAK
434+ : (s->type.t & VT_STATIC) ? STB_LOCAL
435+ : STB_GLOBAL,
436+ ELFW(ST_TYPE)(esym->st_info));
490437 }
491438 /* remove label */
492− table_ident[s->v - TOK_IDENT]->sym_asm_label = NULL;
439+ table_ident[s->v - TOK_IDENT]->sym_identifier = s->prev_tok;
493440 sym_free(s);
494441 }
495442 st->asm_labels = NULL;
@@ -715,13 +662,15 @@ static void asm_parse_directive(TCCState *s1, int global) · 219 unmodified lines
715662 {
716663 unsigned long n;
717664 ExprValue e;
665+ ElfSym *esym;
718666 next();
719667 asm_expr(s1, &e);
720668 n = e.v;
721− if (e.sym) {
722− if (e.sym->r != cur_text_section->sh_num)
669+ esym = elfsym(e.sym);
670+ if (esym) {
671+ if (esym->st_shndx != cur_text_section->sh_num)
723672 expect("constant or same-section symbol");
724− n += e.sym->jnext;
673+ n += esym->st_value;
725674 }
726675 if (n < ind)
727676 tcc_error("attempt to .org backwards");
@@ -978,7 +927,6 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global) · 250 unmodified lines
978927 int opcode;
979928 int saved_parse_flags = parse_flags;
980929
981− /* XXX: undefine C labels */
982930 parse_flags = PARSE_FLAG_ASM_FILE | PARSE_FLAG_TOK_STR;
983931 if (do_preprocess)
984932 parse_flags |= PARSE_FLAG_PREPROCESS;
@@ -1017,18 +965,8 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global) · 32 unmodified lines
1017965 opcode = tok;
1018966 next();
1019967 if (tok == ':') {
1020− /* handle "extern void vide(void); __asm__("vide: ret");" as
1021− "__asm__("globl vide\nvide: ret");" */
1022− Sym *sym = sym_find(opcode);
1023− if (sym && (sym->type.t & VT_EXTERN) && global) {
1024− sym = asm_label_find(opcode);
1025− if (!sym) {
1026− sym = asm_label_push(&s1->asm_labels, opcode);
1027− sym->type.t = VT_VOID | VT_EXTERN;
1028− }
1029− }
1030968 /* new label */
1031− sym = asm_new_label(s1, opcode, 0);
969+ Sym *sym = asm_new_label(s1, opcode, 0);
1032970 sym->type.t &= ~VT_EXTERN;
1033971 next();
1034972 goto redo;
tccelf.c+9−3
@@ -310,7 +310,8 @@ static void rebuild_hash(Section *s, unsigned int nb_buckets) · 309 unmodified lines
310310
311311 sym = (ElfW(Sym) *)s->data + 1;
312312 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
313− if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
313+ if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL
314+ || sym->st_shndx == SHN_UNDEF) {
314315 h = elf_hash(strtab + sym->st_name) % nb_buckets;
315316 *ptr = hash[h];
316317 hash[h] = sym_index;
@@ -349,8 +350,9 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, · 32 unmodified lines
349350 int *ptr, *base;
350351 ptr = section_ptr_add(hs, sizeof(int));
351352 base = (int *)hs->data;
352− /* only add global or weak symbols */
353− if (ELFW(ST_BIND)(info) != STB_LOCAL) {
353+ /* only add global, weak or undef symbols. The latter might
354+ become global late (from asm references). */
355+ if (ELFW(ST_BIND)(info) != STB_LOCAL || shndx == SHN_UNDEF) {
354356 /* add another hashing entry */
355357 nbuckets = base[0];
356358 h = elf_hash((unsigned char *) name) % nbuckets;
@@ -486,6 +488,10 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, · 129 unmodified lines
486488 /* data symbol keeps precedence over common/bss */
487489 } else if (s == tcc_state->dynsymtab_section) {
488490 /* we accept that two DLL define the same symbol */
491+ } else if (esym->st_other & ST_ASM_SET) {
492+ /* If the existing symbol came from an asm .set
493+ we can override. */
494+ goto do_patch;
489495 } else {
490496 #if 0
491497 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
tccgen.c+42−21
@@ -286,14 +286,23 @@ ST_FUNC int tccgen_compile(TCCState *s1) · 285 unmodified lines
286286 }
287287
288288 /* ------------------------------------------------------------------------- */
289+ST_FUNC ElfSym *elfsym(Sym *s)
290+{
291+ if (!s || !s->c)
292+ return NULL;
293+ if (s->c == -1)
294+ return &tcc_state->esym_dot;
295+ else
296+ return &((ElfSym *)symtab_section->data)[s->c];
297+}
298+
289299 /* apply storage attributes to Elf symbol */
290300
291301 static void update_storage(Sym *sym)
292302 {
293− ElfW(Sym) *esym;
294− if (0 == sym->c)
303+ ElfSym *esym = elfsym(sym);
304+ if (!esym)
295305 return;
296− esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
297306 if (sym->a.visibility)
298307 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
299308 | sym->a.visibility;
@@ -325,7 +334,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, · 25 unmodified lines
325334 int can_add_underscore)
326335 {
327336 int sym_type, sym_bind, sh_num, info, other, t;
328− ElfW(Sym) *esym;
337+ ElfSym *esym;
329338 const char *name;
330339 char buf1[256];
331340 #ifdef CONFIG_TCC_BCHECK
@@ -402,7 +411,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, · 70 unmodified lines
402411 info = ELFW(ST_INFO)(sym_bind, sym_type);
403412 sym->c = set_elf_sym(symtab_section, value, size, info, other, sh_num, name);
404413 } else {
405− esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
414+ esym = elfsym(sym);
406415 esym->st_value = value;
407416 esym->st_size = size;
408417 esym->st_shndx = sh_num;
@@ -569,23 +578,28 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c) · 160 unmodified lines
569578 }
570579
571580 /* push a global identifier */
572−ST_FUNC Sym *global_identifier_push(int v, int t, int c)
581+ST_FUNC Sym *global_identifier_push_1(Sym **ptop, int v, int t, int c)
573582 {
574583 Sym *s, **ps;
575− s = sym_push2(&global_stack, v, t, c);
584+ s = sym_push2(ptop, v, t, c);
576585 /* don't record anonymous symbol */
577586 if (v < SYM_FIRST_ANOM) {
578587 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
579588 /* modify the top most local identifier, so that
580589 sym_identifier will point to 's' when popped */
581− while (*ps != NULL)
590+ while (*ps != NULL && (*ps)->sym_scope)
582591 ps = &(*ps)->prev_tok;
583− s->prev_tok = NULL;
592+ s->prev_tok = *ps;
584593 *ps = s;
585594 }
586595 return s;
587596 }
588597
598+static Sym *global_identifier_push(int v, int t, int c)
599+{
600+ return global_identifier_push_1(&global_stack, v, t, c);
601+}
602+
589603 /* pop symbols until top reaches 'b'. If KEEP is non-zero don't really
590604 pop them yet from the list, but do remove them from the token array. */
591605 ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep)
@@ -834,9 +848,13 @@ ST_FUNC Sym *external_global_sym(int v, CType *type, int r) · 242 unmodified lines
834848 /* Merge some storage attributes. */
835849 static void patch_storage(Sym *sym, AttributeDef *ad, CType *type)
836850 {
837− if (type && !is_compatible_types(&sym->type, type))
838− tcc_error("incompatible types for redefinition of '%s'",
839− get_tok_str(sym->v, NULL));
851+ if (type) {
852+ if ((sym->type.t & VT_BTYPE) == VT_VOID) /* from asm */
853+ sym->type = *type;
854+ else if (!is_compatible_types(&sym->type, type))
855+ tcc_error("incompatible types for redefinition of '%s'",
856+ get_tok_str(sym->v, NULL));
857+ }
840858 #ifdef TCC_TARGET_PE
841859 if (sym->a.dllimport != ad->a.dllimport)
842860 tcc_error("incompatible dll linkage for redefinition of '%s'",
@@ -6426,9 +6444,9 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 5583 unmodified lines
64266444 (vtop->type.t & VT_BTYPE) != VT_PTR) {
64276445 /* These come from compound literals, memcpy stuff over. */
64286446 Section *ssec;
6429− ElfW(Sym) *esym;
6447+ ElfSym *esym;
64306448 ElfW_Rel *rel;
6431− esym = &((ElfW(Sym) *)symtab_section->data)[vtop->sym->c];
6449+ esym = elfsym(vtop->sym);
64326450 ssec = tcc_state->sections[esym->st_shndx];
64336451 memmove (ptr, ssec->data + esym->st_value, size);
64346452 if (ssec->reloc) {
@@ -6895,8 +6913,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 460 unmodified lines
68956913 /* no init data, we won't add more to the symbol */
68966914 goto no_alloc;
68976915 } else if (sym->c) {
6898− ElfW(Sym) *esym;
6899− esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
6916+ ElfSym *esym = elfsym(sym);
69006917 if (esym->st_shndx == data_section->sh_num)
69016918 tcc_error("redefinition of '%s'", get_tok_str(v, NULL));
69026919 }
@@ -7030,8 +7047,7 @@ static void gen_function(Sym *sym) · 127 unmodified lines
70307047 sym_pop(&local_stack, NULL, 0);
70317048 /* end of function */
70327049 /* patch symbol size */
7033− ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size =
7034− ind - func_ind;
7050+ elfsym(sym)->st_size = ind - func_ind;
70357051 tcc_debug_funcend(tcc_state, ind - func_ind);
70367052 /* It's better to crash than to generate wrong code */
70377053 cur_text_section = NULL;
@@ -7209,6 +7225,11 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) · 171 unmodified lines
72097225 sym = sym_find(v);
72107226 if (sym) {
72117227 Sym *ref;
7228+ /* If type is VT_VOID the symbol was created by tccasm
7229+ first, and we see the first reference from C now. */
7230+ if ((sym->type.t & VT_BTYPE) == VT_VOID)
7231+ sym->type = type;
7232+
72127233 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
72137234 goto func_error1;
72147235
@@ -7330,12 +7351,12 @@ found: · 115 unmodified lines
73307351 sym = external_sym(v, &type, r, &ad);
73317352 if (ad.alias_target) {
73327353 Section tsec;
7333− ElfW(Sym) *esym;
7354+ ElfSym *esym;
73347355 Sym *alias_target;
73357356 alias_target = sym_find(ad.alias_target);
7336− if (!alias_target || !alias_target->c)
7357+ esym = elfsym(alias_target);
7358+ if (!esym)
73377359 tcc_error("unsupported forward __alias__ attribute");
7338− esym = &((ElfW(Sym) *)symtab_section->data)[alias_target->c];
73397360 tsec.sh_num = esym->st_shndx;
73407361 /* Local statics have a scope until now (for
73417362 warnings), remove it here. */
tccpp.c+0−1
@@ -432,7 +432,6 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) · 431 unmodified lines
432432 ts->sym_label = NULL;
433433 ts->sym_struct = NULL;
434434 ts->sym_identifier = NULL;
435− ts->sym_asm_label = NULL;
436435 ts->len = len;
437436 ts->hash_next = NULL;
438437 memcpy(ts->str, str, len);
tests/asm-c-connect-1.c+7−0
@@ -14,11 +14,13 @@ static int x1_c(void) · 13 unmodified lines
1414
1515 asm(".text;"_"x1: call "_"x1_c; ret");
1616
17+void callx4(void);
1718 int main(int argc, char *argv[])
1819 {
1920 asm("call "_"x1");
2021 asm("call "_"x2");
2122 asm("call "_"x3");
23+ callx4();
2224 return 0;
2325 }
2426
@@ -30,3 +32,8 @@ int x2(void) · 5 unmodified lines
3032 }
3133
3234 extern int x3(void);
35+
36+void x4(void)
37+{
38+ printf("x4\n");
39+}
tests/asm-c-connect-2.c+3−0
@@ -5,3 +5,6 @@ int x3(void) · 4 unmodified lines
55 printf("x3\n");
66 return 3;
77 }
8+
9+void callx4(void);
10+__asm__("callx4: call x4; ret");

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t