aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2017-11-27 04:03:03 +0100
committerMichael Matz <matz@suse.de>2017-11-27 04:59:29 +0100
commit9e0d23cc47359149a39eafffdbb133963980b6ed (patch)
tree84ca4bd202768b2c71d3ed4f09abcd3e1a729e7d /tccgen.c
parent3494e5de3a03d021845666f55340d35af44e3bfc (diff)
downloadtinycc-9e0d23cc47359149a39eafffdbb133963980b6ed.tar.gz
tinycc-9e0d23cc47359149a39eafffdbb133963980b6ed.tar.bz2
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.
Diffstat (limited to 'tccgen.c')
-rw-r--r--tccgen.c63
1 files changed, 42 insertions, 21 deletions
diff --git a/tccgen.c b/tccgen.c
index a86103c..2d3f2d0 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -286,14 +286,23 @@ ST_FUNC int tccgen_compile(TCCState *s1)
}
/* ------------------------------------------------------------------------- */
+ST_FUNC ElfSym *elfsym(Sym *s)
+{
+ if (!s || !s->c)
+ return NULL;
+ if (s->c == -1)
+ return &tcc_state->esym_dot;
+ else
+ return &((ElfSym *)symtab_section->data)[s->c];
+}
+
/* apply storage attributes to Elf symbol */
static void update_storage(Sym *sym)
{
- ElfW(Sym) *esym;
- if (0 == sym->c)
+ ElfSym *esym = elfsym(sym);
+ if (!esym)
return;
- esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
if (sym->a.visibility)
esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
| sym->a.visibility;
@@ -325,7 +334,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
int can_add_underscore)
{
int sym_type, sym_bind, sh_num, info, other, t;
- ElfW(Sym) *esym;
+ ElfSym *esym;
const char *name;
char buf1[256];
#ifdef CONFIG_TCC_BCHECK
@@ -402,7 +411,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
info = ELFW(ST_INFO)(sym_bind, sym_type);
sym->c = set_elf_sym(symtab_section, value, size, info, other, sh_num, name);
} else {
- esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
+ esym = elfsym(sym);
esym->st_value = value;
esym->st_size = size;
esym->st_shndx = sh_num;
@@ -569,23 +578,28 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c)
}
/* push a global identifier */
-ST_FUNC Sym *global_identifier_push(int v, int t, int c)
+ST_FUNC Sym *global_identifier_push_1(Sym **ptop, int v, int t, int c)
{
Sym *s, **ps;
- s = sym_push2(&global_stack, v, t, c);
+ s = sym_push2(ptop, v, t, c);
/* don't record anonymous symbol */
if (v < SYM_FIRST_ANOM) {
ps = &table_ident[v - TOK_IDENT]->sym_identifier;
/* modify the top most local identifier, so that
sym_identifier will point to 's' when popped */
- while (*ps != NULL)
+ while (*ps != NULL && (*ps)->sym_scope)
ps = &(*ps)->prev_tok;
- s->prev_tok = NULL;
+ s->prev_tok = *ps;
*ps = s;
}
return s;
}
+static Sym *global_identifier_push(int v, int t, int c)
+{
+ return global_identifier_push_1(&global_stack, v, t, c);
+}
+
/* pop symbols until top reaches 'b'. If KEEP is non-zero don't really
pop them yet from the list, but do remove them from the token array. */
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)
/* Merge some storage attributes. */
static void patch_storage(Sym *sym, AttributeDef *ad, CType *type)
{
- if (type && !is_compatible_types(&sym->type, type))
- tcc_error("incompatible types for redefinition of '%s'",
- get_tok_str(sym->v, NULL));
+ if (type) {
+ if ((sym->type.t & VT_BTYPE) == VT_VOID) /* from asm */
+ sym->type = *type;
+ else if (!is_compatible_types(&sym->type, type))
+ tcc_error("incompatible types for redefinition of '%s'",
+ get_tok_str(sym->v, NULL));
+ }
#ifdef TCC_TARGET_PE
if (sym->a.dllimport != ad->a.dllimport)
tcc_error("incompatible dll linkage for redefinition of '%s'",
@@ -6426,9 +6444,9 @@ static void init_putv(CType *type, Section *sec, unsigned long c)
(vtop->type.t & VT_BTYPE) != VT_PTR) {
/* These come from compound literals, memcpy stuff over. */
Section *ssec;
- ElfW(Sym) *esym;
+ ElfSym *esym;
ElfW_Rel *rel;
- esym = &((ElfW(Sym) *)symtab_section->data)[vtop->sym->c];
+ esym = elfsym(vtop->sym);
ssec = tcc_state->sections[esym->st_shndx];
memmove (ptr, ssec->data + esym->st_value, size);
if (ssec->reloc) {
@@ -6895,8 +6913,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
/* no init data, we won't add more to the symbol */
goto no_alloc;
} else if (sym->c) {
- ElfW(Sym) *esym;
- esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
+ ElfSym *esym = elfsym(sym);
if (esym->st_shndx == data_section->sh_num)
tcc_error("redefinition of '%s'", get_tok_str(v, NULL));
}
@@ -7030,8 +7047,7 @@ static void gen_function(Sym *sym)
sym_pop(&local_stack, NULL, 0);
/* end of function */
/* patch symbol size */
- ((ElfW(Sym) *)symtab_section->data)[sym->c].st_size =
- ind - func_ind;
+ elfsym(sym)->st_size = ind - func_ind;
tcc_debug_funcend(tcc_state, ind - func_ind);
/* It's better to crash than to generate wrong code */
cur_text_section = NULL;
@@ -7209,6 +7225,11 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
sym = sym_find(v);
if (sym) {
Sym *ref;
+ /* If type is VT_VOID the symbol was created by tccasm
+ first, and we see the first reference from C now. */
+ if ((sym->type.t & VT_BTYPE) == VT_VOID)
+ sym->type = type;
+
if ((sym->type.t & VT_BTYPE) != VT_FUNC)
goto func_error1;
@@ -7330,12 +7351,12 @@ found:
sym = external_sym(v, &type, r, &ad);
if (ad.alias_target) {
Section tsec;
- ElfW(Sym) *esym;
+ ElfSym *esym;
Sym *alias_target;
alias_target = sym_find(ad.alias_target);
- if (!alias_target || !alias_target->c)
+ esym = elfsym(alias_target);
+ if (!esym)
tcc_error("unsupported forward __alias__ attribute");
- esym = &((ElfW(Sym) *)symtab_section->data)[alias_target->c];
tsec.sh_num = esym->st_shndx;
/* Local statics have a scope until now (for
warnings), remove it here. */