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
500static void gen_disp32(ExprValue *pe)500static void gen_disp32(ExprValue *pe)
501{501{
502 Sym *sym = pe->sym;502 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) {
504 /* same section: we can output an absolute value. Note505 /* same section: we can output an absolute value. Note
505 that the TCC compiler behaves differently here because506 that the TCC compiler behaves differently here because
506 it always outputs a relocation to ease (future) code507 it always outputs a relocation to ease (future) code
507 elimination in the linker */508 elimination in the linker */
508 gen_le32(pe->v + sym->jnext - ind - 4);509 gen_le32(pe->v + esym->st_value - ind - 4);
509 } else {510 } else {
510 if (sym && sym->type.t == VT_VOID) {511 if (sym && sym->type.t == VT_VOID) {
511 sym->type.t = VT_FUNC;512 sym->type.t = VT_FUNC;
@@ -1017,16 +1018,14 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 505 unmodified lines
1017 if (pa->instr_type & OPC_B)1018 if (pa->instr_type & OPC_B)
1018 v += s >= 1;1019 v += s >= 1;
1019 if (nb_ops == 1 && pa->op_type[0] == OPT_DISP8) {1020 if (nb_ops == 1 && pa->op_type[0] == OPT_DISP8) {
1020 Sym *sym;1021 ElfSym *esym;
1021 int jmp_disp;1022 int jmp_disp;
1022 1023
1023 /* see if we can really generate the jump with a byte offset */1024 /* see if we can really generate the jump with a byte offset */
1024 sym = ops[0].e.sym;1025 esym = elfsym(ops[0].e.sym);
1025 if (!sym)1026 if (!esym || esym->st_shndx != cur_text_section->sh_num)
1026 goto no_short_jump;1027 goto no_short_jump;
1027 if (sym->r != cur_text_section->sh_num)1028 jmp_disp = ops[0].e.v + esym->st_value - ind - 2 - (v >= 0xff);
1028 goto no_short_jump;
1029 jmp_disp = ops[0].e.v + sym->jnext - ind - 2 - (v >= 0xff);
1030 if (jmp_disp == (int8_t)jmp_disp) {1029 if (jmp_disp == (int8_t)jmp_disp) {
1031 /* OK to generate jump */1030 /* OK to generate jump */
1032 ops[0].e.sym = 0;1031 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
356#endif356#endif
357/* target address type */357/* target address type */
358#define addr_t ElfW(Addr)358#define addr_t ElfW(Addr)
359#define ElfSym ElfW(Sym)
359 360
360#if PTR_SIZE == 8 && !defined TCC_TARGET_PE361#if PTR_SIZE == 8 && !defined TCC_TARGET_PE
361# define LONG_SIZE 8362# define LONG_SIZE 8
@@ -383,7 +384,6 @@ typedef struct TokenSym { · 21 unmodified lines
383 struct Sym *sym_label; /* direct pointer to label */384 struct Sym *sym_label; /* direct pointer to label */
384 struct Sym *sym_struct; /* direct pointer to structure */385 struct Sym *sym_struct; /* direct pointer to structure */
385 struct Sym *sym_identifier; /* direct pointer to identifier */386 struct Sym *sym_identifier; /* direct pointer to identifier */
386 struct Sym *sym_asm_label; /* direct pointer to asm label */
387 int tok; /* token number */387 int tok; /* token number */
388 int len;388 int len;
389 char str[1];389 char str[1];
@@ -440,9 +440,8 @@ struct SymAttr { · 50 unmodified lines
440 visibility : 2,440 visibility : 2,
441 dllexport : 1,441 dllexport : 1,
442 dllimport : 1,442 dllimport : 1,
443 asmcsym : 1,
444 asmexport : 1,443 asmexport : 1,
445 unused : 3;444 unused : 4;
446};445};
447 446
448/* function attributes or temporary attributes for parsing */447/* function attributes or temporary attributes for parsing */
@@ -799,6 +798,7 @@ struct TCCState { · 350 unmodified lines
799 int nb_sym_attrs;798 int nb_sym_attrs;
800 /* tiny assembler state */799 /* tiny assembler state */
801 Sym *asm_labels;800 Sym *asm_labels;
801 ElfSym esym_dot;
802 802
803#ifdef TCC_TARGET_PE803#ifdef TCC_TARGET_PE
804 /* PE info */804 /* PE info */
@@ -1147,7 +1147,7 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c); · 342 unmodified lines
1147ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep);1147ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep);
1148ST_INLN Sym *struct_find(int v);1148ST_INLN Sym *struct_find(int v);
1149ST_INLN Sym *sym_find(int v);1149ST_INLN Sym *sym_find(int v);
1150ST_FUNC Sym *global_identifier_push(int v, int t, int c);1150ST_FUNC Sym *global_identifier_push_1(Sym **, int v, int t, int c);
1151 1151
1152ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);1152ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
1153ST_FUNC int tcc_open(TCCState *s1, const char *filename);1153ST_FUNC int tcc_open(TCCState *s1, const char *filename);
@@ -1316,6 +1316,7 @@ ST_INLN int is_float(int t); · 162 unmodified lines
1316ST_FUNC int ieee_finite(double d);1316ST_FUNC int ieee_finite(double d);
1317ST_FUNC void test_lvalue(void);1317ST_FUNC void test_lvalue(void);
1318ST_FUNC void vpushi(int v);1318ST_FUNC void vpushi(int v);
1319ST_FUNC ElfSym *elfsym(Sym *);
1319ST_FUNC Sym *external_global_sym(int v, CType *type, int r);1320ST_FUNC Sym *external_global_sym(int v, CType *type, int r);
1320ST_FUNC void vset(CType *type, int r, int v);1321ST_FUNC void vset(CType *type, int r, int v);
1321ST_FUNC void vswap(void);1322ST_FUNC void vswap(void);
@@ -1618,6 +1619,8 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp); · 296 unmodified lines
1618# define ST_PE_IMPORT 0x201619# define ST_PE_IMPORT 0x20
1619# define ST_PE_STDCALL 0x401620# define ST_PE_STDCALL 0x40
1620#endif1621#endif
1622#define ST_ASM_SET 0x04
1623
1621/* ------------ tccrun.c ----------------- */1624/* ------------ tccrun.c ----------------- */
1622#ifdef TCC_IS_NATIVE1625#ifdef TCC_IS_NATIVE
1623#ifdef CONFIG_TCC_STATIC1626#ifdef CONFIG_TCC_STATIC
tccasm.c+90−152
@@ -36,64 +36,40 @@ static Sym sym_dot; · 35 unmodified lines
36 36
37static Sym *asm_label_find(int v)37static Sym *asm_label_find(int v)
38{38{
39 v -= TOK_IDENT;39 Sym *sym = sym_find(v);
40 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))40 while (sym && sym->sym_scope)
41 return NULL;41 sym = sym->prev_tok;
42 return table_ident[v]->sym_asm_label;42 return sym;
43}43}
44 44
45static Sym *asm_label_push(Sym **ptop, int v)45static Sym *asm_label_push(int v, int t)
46{46{
47 Sym *s, **ps;47 Sym *sym = global_identifier_push_1(&tcc_state->asm_labels, v, t, 0);
48 s = sym_push2(ptop, v, 0, 0);48 /* We always add VT_EXTERN, for sym definition that's tentative
49 ps = &table_ident[v - TOK_IDENT]->sym_asm_label;49 (for .set, removed for real defs), for mere references it's correct
50 s->prev_tok = *ps;50 as is. */
51 *ps = s;51 sym->type.t |= VT_VOID | VT_EXTERN;
52 return s;52 sym->r = VT_CONST | VT_SYM;
53 return sym;
53}54}
54 55
55/* Return a symbol we can use inside the assembler, having name NAME.56/* Return a symbol we can use inside the assembler, having name NAME.
56 The assembler symbol table is different from the C symbol table57 Symbols from asm and C source share a namespace. If we generate
57 (and the Sym members are used differently). But we must be able58 an asm symbol it's also a (file-global) C symbol, but it's
58 to look up file-global C symbols from inside the assembler, e.g.59 either not accessible by name (like "L.123"), or its type information
59 for global asm blocks to be able to refer to defined C symbols.60 is such that it's not usable without a proper C declaration.
60 61
61 This routine gives back either an existing asm-internal62 Sometimes we need symbols accessible by name from asm, which
62 symbol, or a new one. In the latter case the new asm-internal63 are anonymous in C, in this case CSYM can be used to transfer
63 symbol is initialized with info from the C symbol table.64 all information from that symbol to the (possibly newly created)
64 65 asm symbol. */
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. */
67ST_FUNC Sym* get_asm_sym(int name, Sym *csym)66ST_FUNC Sym* get_asm_sym(int name, Sym *csym)
68{67{
69 Sym *sym = asm_label_find(name);68 Sym *sym = asm_label_find(name);
70 if (!sym) {69 if (!sym) {
71 sym = asm_label_push(&tcc_state->asm_labels, name);70 sym = asm_label_push(name, 0);
72 sym->type.t = VT_VOID | VT_EXTERN;71 if (csym)
73 if (!csym) {72 sym->c = csym->c;
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 }
97 }73 }
98 return sym;74 return sym;
99}75}
@@ -118,16 +94,15 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe) · 18 unmodified lines
118 sym = asm_label_find(label);94 sym = asm_label_find(label);
119 if (*p == 'b') {95 if (*p == 'b') {
120 /* backward : find the last corresponding defined label */96 /* backward : find the last corresponding defined label */
121 if (sym && sym->r == 0)97 if (sym && (!sym->c || elfsym(sym)->st_shndx == SHN_UNDEF))
122 sym = sym->prev_tok;98 sym = sym->prev_tok;
123 if (!sym)99 if (!sym)
124 tcc_error("local label '%d' not found backward", n);100 tcc_error("local label '%d' not found backward", n);
125 } else {101 } else {
126 /* forward */102 /* forward */
127 if (!sym || sym->r) {103 if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) {
128 /* if the last label is defined, then define a new one */104 /* if the last label is defined, then define a new one */
129 sym = asm_label_push(&s1->asm_labels, label);105 sym = asm_label_push(label, VT_STATIC);
130 sym->type.t = VT_STATIC | VT_VOID | VT_EXTERN;
131 }106 }
132 }107 }
133 pe->v = 0;108 pe->v = 0;
@@ -175,17 +150,20 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe) · 41 unmodified lines
175 pe->sym = &sym_dot;150 pe->sym = &sym_dot;
176 pe->pcrel = 0;151 pe->pcrel = 0;
177 sym_dot.type.t = VT_VOID | VT_STATIC;152 sym_dot.type.t = VT_VOID | VT_STATIC;
178 sym_dot.r = cur_text_section->sh_num;153 sym_dot.c = -1;
179 sym_dot.jnext = ind;154 tcc_state->esym_dot.st_shndx = cur_text_section->sh_num;
155 tcc_state->esym_dot.st_value = ind;
180 next();156 next();
181 break;157 break;
182 default:158 default:
183 if (tok >= TOK_IDENT) {159 if (tok >= TOK_IDENT) {
160 ElfSym *esym;
184 /* label case : if the label was not found, add one */161 /* label case : if the label was not found, add one */
185 sym = get_asm_sym(tok, NULL);162 sym = get_asm_sym(tok, NULL);
186 if (sym->r == SHN_ABS) {163 esym = elfsym(sym);
164 if (esym && esym->st_shndx == SHN_ABS) {
187 /* if absolute symbol, no need to put a symbol value */165 /* if absolute symbol, no need to put a symbol value */
188 pe->v = sym->jnext;166 pe->v = esym->st_value;
189 pe->sym = NULL;167 pe->sym = NULL;
190 pe->pcrel = 0;168 pe->pcrel = 0;
191 } else {169 } else {
@@ -299,20 +277,26 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe) · 107 unmodified lines
299 } else if (pe->sym == e2.sym) { 277 } else if (pe->sym == e2.sym) {
300 /* OK */278 /* OK */
301 pe->sym = NULL; /* same symbols can be subtracted to NULL */279 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) {280 } else {
303 /* we also accept defined symbols in the same section */281 ElfSym *esym1, *esym2;
304 pe->v += pe->sym->jnext - e2.sym->jnext;282 esym1 = elfsym(pe->sym);
305 pe->sym = NULL;283 esym2 = elfsym(e2.sym);
306 } else if (e2.sym->r == cur_text_section->sh_num) {284 if (esym1 && esym1->st_shndx == esym2->st_shndx
307 /* When subtracting a defined symbol in current section285 && esym1->st_shndx != SHN_UNDEF) {
308 this actually makes the value PC-relative. */286 /* we also accept defined symbols in the same section */
309 pe->v -= e2.sym->jnext - ind - 4;287 pe->v += esym1->st_value - esym2->st_value;
310 pe->pcrel = 1;288 pe->sym = NULL;
311 e2.sym = NULL;289 } else if (esym2->st_shndx == cur_text_section->sh_num) {
312 } else {290 /* When subtracting a defined symbol in current section
313 cannot_relocate:291 this actually makes the value PC-relative. */
314 tcc_error("invalid operation with label");292 pe->v -= esym2->st_value - ind - 4;
315 }293 pe->pcrel = 1;
294 e2.sym = NULL;
295 } else {
296cannot_relocate:
297 tcc_error("invalid operation with label");
298 }
299 }
316 }300 }
317 }301 }
318}302}
@@ -377,13 +361,15 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local, · 58 unmodified lines
377 int sh_num, int value)361 int sh_num, int value)
378{362{
379 Sym *sym;363 Sym *sym;
364 ElfSym *esym;
380 365
381 sym = asm_label_find(label);366 sym = asm_label_find(label);
382 if (sym) {367 if (sym) {
368 esym = elfsym(sym);
383 /* A VT_EXTERN symbol, even if it has a section is considered369 /* A VT_EXTERN symbol, even if it has a section is considered
384 overridable. This is how we "define" .set targets. Real370 overridable. This is how we "define" .set targets. Real
385 definitions won't have VT_EXTERN set. */371 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)) {
387 /* the label is already defined */373 /* the label is already defined */
388 if (!is_local) {374 if (!is_local) {
389 tcc_error("assembler label '%s' already defined", 375 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
395 }381 }
396 } else {382 } else {
397 new_label:383 new_label:
398 sym = asm_label_push(&s1->asm_labels, label);384 sym = asm_label_push(label, is_local ? VT_STATIC : 0);
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;
403 }385 }
404 sym->r = sh_num;386 if (!sym->c)
405 sym->jnext = value;387 put_extern_sym2(sym, NULL, 0, 0, 0);
388 esym = elfsym(sym);
389 esym->st_shndx = sh_num;
390 esym->st_value = value;
406 return sym;391 return sym;
407}392}
408 393
@@ -417,79 +402,41 @@ static Sym* set_symbol(TCCState *s1, int label) · 8 unmodified lines
417{402{
418 long n;403 long n;
419 ExprValue e;404 ExprValue e;
405 Sym *sym;
406 ElfSym *esym;
420 next();407 next();
421 asm_expr(s1, &e);408 asm_expr(s1, &e);
422 n = e.v;409 n = e.v;
423 if (e.sym)410 esym = elfsym(e.sym);
424 n += e.sym->jnext;411 if (esym)
425 return asm_new_label1(s1, label, 0, e.sym ? e.sym->r : SHN_ABS, n);412 n += esym->st_value;
426}413 sym = asm_new_label1(s1, label, 0, esym ? esym->st_shndx : SHN_ABS, n);
427 414 elfsym(sym)->st_other |= ST_ASM_SET;
428/* Patch ELF symbol associated with SYM based on the assemblers415 return sym;
429 understanding. */
430static 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));
444}416}
445 417
446ST_FUNC void asm_free_labels(TCCState *st)418ST_FUNC void asm_free_labels(TCCState *st)
447{419{
448 Sym *s, *s1;420 Sym *s, *s1;
449 Section *sec;
450 421
451 for(s = st->asm_labels; s != NULL; s = s1) {422 for(s = st->asm_labels; s != NULL; s = s1) {
452 int was_ext = s->type.t & VT_EXTERN;423 ElfSym *esym = elfsym(s);
453 s1 = s->prev;424 s1 = s->prev;
454 /* define symbol value in object file and care for updating425 /* Possibly update binding and visibility from asm directives. */
455 the C and asm symbols */
456 s->type.t &= ~VT_EXTERN;426 s->type.t &= ~VT_EXTERN;
457 if (!s->a.asmcsym) {427 if (esym) {
458 Sym *csym = sym_find(s->v);428 if (!s->a.asmexport && esym->st_shndx != SHN_UNDEF)
459 ElfW(Sym) *esym = NULL;429 s->type.t |= VT_STATIC;
460 if (csym) {430 if (s->a.visibility)
461 s->a.asmexport |= !(csym->type.t & VT_STATIC);431 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
462 if (csym->c) {432 | s->a.visibility;
463 esym = &((ElfW(Sym) *)symtab_section->data)[csym->c];433 esym->st_info = ELFW(ST_INFO)(s->a.weak ? STB_WEAK
464 if (s->c) {434 : (s->type.t & VT_STATIC) ? STB_LOCAL
465 /* We have generated code and possibly relocs435 : STB_GLOBAL,
466 referencing the symtab entry s->c (the asm436 ELFW(ST_TYPE)(esym->st_info));
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);
490 }437 }
491 /* remove label */438 /* 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;
493 sym_free(s);440 sym_free(s);
494 }441 }
495 st->asm_labels = NULL;442 st->asm_labels = NULL;
@@ -715,13 +662,15 @@ static void asm_parse_directive(TCCState *s1, int global) · 219 unmodified lines
715 {662 {
716 unsigned long n;663 unsigned long n;
717 ExprValue e;664 ExprValue e;
665 ElfSym *esym;
718 next();666 next();
719 asm_expr(s1, &e);667 asm_expr(s1, &e);
720 n = e.v;668 n = e.v;
721 if (e.sym) {669 esym = elfsym(e.sym);
722 if (e.sym->r != cur_text_section->sh_num)670 if (esym) {
671 if (esym->st_shndx != cur_text_section->sh_num)
723 expect("constant or same-section symbol");672 expect("constant or same-section symbol");
724 n += e.sym->jnext;673 n += esym->st_value;
725 }674 }
726 if (n < ind)675 if (n < ind)
727 tcc_error("attempt to .org backwards");676 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
978 int opcode;927 int opcode;
979 int saved_parse_flags = parse_flags;928 int saved_parse_flags = parse_flags;
980 929
981 /* XXX: undefine C labels */
982 parse_flags = PARSE_FLAG_ASM_FILE | PARSE_FLAG_TOK_STR;930 parse_flags = PARSE_FLAG_ASM_FILE | PARSE_FLAG_TOK_STR;
983 if (do_preprocess)931 if (do_preprocess)
984 parse_flags |= PARSE_FLAG_PREPROCESS;932 parse_flags |= PARSE_FLAG_PREPROCESS;
@@ -1017,18 +965,8 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global) · 32 unmodified lines
1017 opcode = tok;965 opcode = tok;
1018 next();966 next();
1019 if (tok == ':') {967 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 }
1030 /* new label */968 /* new label */
1031 sym = asm_new_label(s1, opcode, 0);969 Sym *sym = asm_new_label(s1, opcode, 0);
1032 sym->type.t &= ~VT_EXTERN;970 sym->type.t &= ~VT_EXTERN;
1033 next();971 next();
1034 goto redo;972 goto redo;
tccelf.c+9−3
@@ -310,7 +310,8 @@ static void rebuild_hash(Section *s, unsigned int nb_buckets) · 309 unmodified lines
310 310
311 sym = (ElfW(Sym) *)s->data + 1;311 sym = (ElfW(Sym) *)s->data + 1;
312 for(sym_index = 1; sym_index < nb_syms; sym_index++) {312 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) {
314 h = elf_hash(strtab + sym->st_name) % nb_buckets;315 h = elf_hash(strtab + sym->st_name) % nb_buckets;
315 *ptr = hash[h];316 *ptr = hash[h];
316 hash[h] = sym_index;317 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
349 int *ptr, *base;350 int *ptr, *base;
350 ptr = section_ptr_add(hs, sizeof(int));351 ptr = section_ptr_add(hs, sizeof(int));
351 base = (int *)hs->data;352 base = (int *)hs->data;
352 /* only add global or weak symbols */353 /* only add global, weak or undef symbols. The latter might
353 if (ELFW(ST_BIND)(info) != STB_LOCAL) {354 become global late (from asm references). */
355 if (ELFW(ST_BIND)(info) != STB_LOCAL || shndx == SHN_UNDEF) {
354 /* add another hashing entry */356 /* add another hashing entry */
355 nbuckets = base[0];357 nbuckets = base[0];
356 h = elf_hash((unsigned char *) name) % nbuckets;358 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
486 /* data symbol keeps precedence over common/bss */488 /* data symbol keeps precedence over common/bss */
487 } else if (s == tcc_state->dynsymtab_section) {489 } else if (s == tcc_state->dynsymtab_section) {
488 /* we accept that two DLL define the same symbol */490 /* 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;
489 } else {495 } else {
490#if 0496#if 0
491 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",497 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
286}286}
287 287
288/* ------------------------------------------------------------------------- */288/* ------------------------------------------------------------------------- */
289ST_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
289/* apply storage attributes to Elf symbol */299/* apply storage attributes to Elf symbol */
290 300
291static void update_storage(Sym *sym)301static void update_storage(Sym *sym)
292{302{
293 ElfW(Sym) *esym;303 ElfSym *esym = elfsym(sym);
294 if (0 == sym->c)304 if (!esym)
295 return;305 return;
296 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
297 if (sym->a.visibility)306 if (sym->a.visibility)
298 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))307 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
299 | sym->a.visibility;308 | sym->a.visibility;
@@ -325,7 +334,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, · 25 unmodified lines
325 int can_add_underscore)334 int can_add_underscore)
326{335{
327 int sym_type, sym_bind, sh_num, info, other, t;336 int sym_type, sym_bind, sh_num, info, other, t;
328 ElfW(Sym) *esym;337 ElfSym *esym;
329 const char *name;338 const char *name;
330 char buf1[256];339 char buf1[256];
331#ifdef CONFIG_TCC_BCHECK340#ifdef CONFIG_TCC_BCHECK
@@ -402,7 +411,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, · 70 unmodified lines
402 info = ELFW(ST_INFO)(sym_bind, sym_type);411 info = ELFW(ST_INFO)(sym_bind, sym_type);
403 sym->c = set_elf_sym(symtab_section, value, size, info, other, sh_num, name);412 sym->c = set_elf_sym(symtab_section, value, size, info, other, sh_num, name);
404 } else {413 } else {
405 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];414 esym = elfsym(sym);
406 esym->st_value = value;415 esym->st_value = value;
407 esym->st_size = size;416 esym->st_size = size;
408 esym->st_shndx = sh_num;417 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
569}578}
570 579
571/* push a global identifier */580/* push a global identifier */
572ST_FUNC Sym *global_identifier_push(int v, int t, int c)581ST_FUNC Sym *global_identifier_push_1(Sym **ptop, int v, int t, int c)
573{582{
574 Sym *s, **ps;583 Sym *s, **ps;
575 s = sym_push2(&global_stack, v, t, c);584 s = sym_push2(ptop, v, t, c);
576 /* don't record anonymous symbol */585 /* don't record anonymous symbol */
577 if (v < SYM_FIRST_ANOM) {586 if (v < SYM_FIRST_ANOM) {
578 ps = &table_ident[v - TOK_IDENT]->sym_identifier;587 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
579 /* modify the top most local identifier, so that588 /* modify the top most local identifier, so that
580 sym_identifier will point to 's' when popped */589 sym_identifier will point to 's' when popped */
581 while (*ps != NULL)590 while (*ps != NULL && (*ps)->sym_scope)
582 ps = &(*ps)->prev_tok;591 ps = &(*ps)->prev_tok;
583 s->prev_tok = NULL;592 s->prev_tok = *ps;
584 *ps = s;593 *ps = s;
585 }594 }
586 return s;595 return s;
587}596}
588 597
598static Sym *global_identifier_push(int v, int t, int c)
599{
600 return global_identifier_push_1(&global_stack, v, t, c);
601}
602
589/* pop symbols until top reaches 'b'. If KEEP is non-zero don't really603/* pop symbols until top reaches 'b'. If KEEP is non-zero don't really
590 pop them yet from the list, but do remove them from the token array. */604 pop them yet from the list, but do remove them from the token array. */
591ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep)605ST_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
834/* Merge some storage attributes. */848/* Merge some storage attributes. */
835static void patch_storage(Sym *sym, AttributeDef *ad, CType *type)849static void patch_storage(Sym *sym, AttributeDef *ad, CType *type)
836{850{
837 if (type && !is_compatible_types(&sym->type, type))851 if (type) {
838 tcc_error("incompatible types for redefinition of '%s'",852 if ((sym->type.t & VT_BTYPE) == VT_VOID) /* from asm */
839 get_tok_str(sym->v, NULL));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 }
840#ifdef TCC_TARGET_PE858#ifdef TCC_TARGET_PE
841 if (sym->a.dllimport != ad->a.dllimport)859 if (sym->a.dllimport != ad->a.dllimport)
842 tcc_error("incompatible dll linkage for redefinition of '%s'",860 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
6426 (vtop->type.t & VT_BTYPE) != VT_PTR) {6444 (vtop->type.t & VT_BTYPE) != VT_PTR) {
6427 /* These come from compound literals, memcpy stuff over. */6445 /* These come from compound literals, memcpy stuff over. */
6428 Section *ssec;6446 Section *ssec;
6429 ElfW(Sym) *esym;6447 ElfSym *esym;
6430 ElfW_Rel *rel;6448 ElfW_Rel *rel;
6431 esym = &((ElfW(Sym) *)symtab_section->data)[vtop->sym->c];6449 esym = elfsym(vtop->sym);
6432 ssec = tcc_state->sections[esym->st_shndx];6450 ssec = tcc_state->sections[esym->st_shndx];
6433 memmove (ptr, ssec->data + esym->st_value, size);6451 memmove (ptr, ssec->data + esym->st_value, size);
6434 if (ssec->reloc) {6452 if (ssec->reloc) {
@@ -6895,8 +6913,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 460 unmodified lines
6895 /* no init data, we won't add more to the symbol */6913 /* no init data, we won't add more to the symbol */
6896 goto no_alloc;6914 goto no_alloc;
6897 } else if (sym->c) {6915 } else if (sym->c) {
6898 ElfW(Sym) *esym;6916 ElfSym *esym = elfsym(sym);
6899 esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
6900 if (esym->st_shndx == data_section->sh_num)6917 if (esym->st_shndx == data_section->sh_num)
6901 tcc_error("redefinition of '%s'", get_tok_str(v, NULL));6918 tcc_error("redefinition of '%s'", get_tok_str(v, NULL));
6902 }6919 }
@@ -7030,8 +7047,7 @@ static void gen_function(Sym *sym) · 127 unmodified lines
7030 sym_pop(&local_stack, NULL, 0);7047 sym_pop(&local_stack, NULL, 0);
7031 /* end of function */7048 /* end of function */
7032 /* patch symbol size */7049 /* patch symbol size */
7033 ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size = 7050 elfsym(sym)->st_size = ind - func_ind;
7034 ind - func_ind;
7035 tcc_debug_funcend(tcc_state, ind - func_ind);7051 tcc_debug_funcend(tcc_state, ind - func_ind);
7036 /* It's better to crash than to generate wrong code */7052 /* It's better to crash than to generate wrong code */
7037 cur_text_section = NULL;7053 cur_text_section = NULL;
@@ -7209,6 +7225,11 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) · 171 unmodified lines
7209 sym = sym_find(v);7225 sym = sym_find(v);
7210 if (sym) {7226 if (sym) {
7211 Sym *ref;7227 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
7212 if ((sym->type.t & VT_BTYPE) != VT_FUNC)7233 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
7213 goto func_error1;7234 goto func_error1;
7214 7235
@@ -7330,12 +7351,12 @@ found: · 115 unmodified lines
7330 sym = external_sym(v, &type, r, &ad);7351 sym = external_sym(v, &type, r, &ad);
7331 if (ad.alias_target) {7352 if (ad.alias_target) {
7332 Section tsec;7353 Section tsec;
7333 ElfW(Sym) *esym;7354 ElfSym *esym;
7334 Sym *alias_target;7355 Sym *alias_target;
7335 alias_target = sym_find(ad.alias_target);7356 alias_target = sym_find(ad.alias_target);
7336 if (!alias_target || !alias_target->c)7357 esym = elfsym(alias_target);
7358 if (!esym)
7337 tcc_error("unsupported forward __alias__ attribute");7359 tcc_error("unsupported forward __alias__ attribute");
7338 esym = &((ElfW(Sym) *)symtab_section->data)[alias_target->c];
7339 tsec.sh_num = esym->st_shndx;7360 tsec.sh_num = esym->st_shndx;
7340 /* Local statics have a scope until now (for7361 /* Local statics have a scope until now (for
7341 warnings), remove it here. */7362 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
432 ts->sym_label = NULL;432 ts->sym_label = NULL;
433 ts->sym_struct = NULL;433 ts->sym_struct = NULL;
434 ts->sym_identifier = NULL;434 ts->sym_identifier = NULL;
435 ts->sym_asm_label = NULL;
436 ts->len = len;435 ts->len = len;
437 ts->hash_next = NULL;436 ts->hash_next = NULL;
438 memcpy(ts->str, str, len);437 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
14 14
15asm(".text;"_"x1: call "_"x1_c; ret");15asm(".text;"_"x1: call "_"x1_c; ret");
16 16
17void callx4(void);
17int main(int argc, char *argv[])18int main(int argc, char *argv[])
18{19{
19 asm("call "_"x1");20 asm("call "_"x1");
20 asm("call "_"x2");21 asm("call "_"x2");
21 asm("call "_"x3");22 asm("call "_"x3");
23 callx4();
22 return 0;24 return 0;
23}25}
24 26
@@ -30,3 +32,8 @@ int x2(void) · 5 unmodified lines
30}32}
31 33
32extern int x3(void);34extern int x3(void);
35
36void 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
5 printf("x3\n");5 printf("x3\n");
6 return 3;6 return 3;
7}7}
8
9void 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