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.
master
Michael Matz 2017-11-27 04:03:03 +01:00
parent 3494e5de3a
commit 9e0d23cc47
8 changed files with 164 additions and 188 deletions

View File

@ -500,12 +500,13 @@ ST_FUNC void gen_expr64(ExprValue *pe)
static void gen_disp32(ExprValue *pe)
{
Sym *sym = pe->sym;
if (sym && sym->r == cur_text_section->sh_num) {
ElfSym *esym = elfsym(sym);
if (esym && esym->st_shndx == cur_text_section->sh_num) {
/* same section: we can output an absolute value. Note
that the TCC compiler behaves differently here because
it always outputs a relocation to ease (future) code
elimination in the linker */
gen_le32(pe->v + sym->jnext - ind - 4);
gen_le32(pe->v + esym->st_value - ind - 4);
} else {
if (sym && sym->type.t == VT_VOID) {
sym->type.t = VT_FUNC;
@ -1017,16 +1018,14 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
if (pa->instr_type & OPC_B)
v += s >= 1;
if (nb_ops == 1 && pa->op_type[0] == OPT_DISP8) {
Sym *sym;
ElfSym *esym;
int jmp_disp;
/* see if we can really generate the jump with a byte offset */
sym = ops[0].e.sym;
if (!sym)
esym = elfsym(ops[0].e.sym);
if (!esym || esym->st_shndx != cur_text_section->sh_num)
goto no_short_jump;
if (sym->r != cur_text_section->sh_num)
goto no_short_jump;
jmp_disp = ops[0].e.v + sym->jnext - ind - 2 - (v >= 0xff);
jmp_disp = ops[0].e.v + esym->st_value - ind - 2 - (v >= 0xff);
if (jmp_disp == (int8_t)jmp_disp) {
/* OK to generate jump */
ops[0].e.sym = 0;

11
tcc.h
View File

@ -356,6 +356,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
#endif
/* target address type */
#define addr_t ElfW(Addr)
#define ElfSym ElfW(Sym)
#if PTR_SIZE == 8 && !defined TCC_TARGET_PE
# define LONG_SIZE 8
@ -383,7 +384,6 @@ typedef struct TokenSym {
struct Sym *sym_label; /* direct pointer to label */
struct Sym *sym_struct; /* direct pointer to structure */
struct Sym *sym_identifier; /* direct pointer to identifier */
struct Sym *sym_asm_label; /* direct pointer to asm label */
int tok; /* token number */
int len;
char str[1];
@ -440,9 +440,8 @@ struct SymAttr {
visibility : 2,
dllexport : 1,
dllimport : 1,
asmcsym : 1,
asmexport : 1,
unused : 3;
unused : 4;
};
/* function attributes or temporary attributes for parsing */
@ -799,6 +798,7 @@ struct TCCState {
int nb_sym_attrs;
/* tiny assembler state */
Sym *asm_labels;
ElfSym esym_dot;
#ifdef TCC_TARGET_PE
/* PE info */
@ -1147,7 +1147,7 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c);
ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep);
ST_INLN Sym *struct_find(int v);
ST_INLN Sym *sym_find(int v);
ST_FUNC Sym *global_identifier_push(int v, int t, int c);
ST_FUNC Sym *global_identifier_push_1(Sym **, int v, int t, int c);
ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
ST_FUNC int tcc_open(TCCState *s1, const char *filename);
@ -1316,6 +1316,7 @@ ST_INLN int is_float(int t);
ST_FUNC int ieee_finite(double d);
ST_FUNC void test_lvalue(void);
ST_FUNC void vpushi(int v);
ST_FUNC ElfSym *elfsym(Sym *);
ST_FUNC Sym *external_global_sym(int v, CType *type, int r);
ST_FUNC void vset(CType *type, int r, int v);
ST_FUNC void vswap(void);
@ -1618,6 +1619,8 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp);
# define ST_PE_IMPORT 0x20
# define ST_PE_STDCALL 0x40
#endif
#define ST_ASM_SET 0x04
/* ------------ tccrun.c ----------------- */
#ifdef TCC_IS_NATIVE
#ifdef CONFIG_TCC_STATIC

240
tccasm.c
View File

@ -36,64 +36,40 @@ static Sym sym_dot;
static Sym *asm_label_find(int v)
{
v -= TOK_IDENT;
if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
return NULL;
return table_ident[v]->sym_asm_label;
Sym *sym = sym_find(v);
while (sym && sym->sym_scope)
sym = sym->prev_tok;
return sym;
}
static Sym *asm_label_push(Sym **ptop, int v)
static Sym *asm_label_push(int v, int t)
{
Sym *s, **ps;
s = sym_push2(ptop, v, 0, 0);
ps = &table_ident[v - TOK_IDENT]->sym_asm_label;
s->prev_tok = *ps;
*ps = s;
return s;
Sym *sym = global_identifier_push_1(&tcc_state->asm_labels, v, t, 0);
/* We always add VT_EXTERN, for sym definition that's tentative
(for .set, removed for real defs), for mere references it's correct
as is. */
sym->type.t |= VT_VOID | VT_EXTERN;
sym->r = VT_CONST | VT_SYM;
return sym;
}
/* Return a symbol we can use inside the assembler, having name NAME.
The assembler symbol table is different from the C symbol table
(and the Sym members are used differently). But we must be able
to look up file-global C symbols from inside the assembler, e.g.
for global asm blocks to be able to refer to defined C symbols.
Symbols from asm and C source share a namespace. If we generate
an asm symbol it's also a (file-global) C symbol, but it's
either not accessible by name (like "L.123"), or its type information
is such that it's not usable without a proper C declaration.
This routine gives back either an existing asm-internal
symbol, or a new one. In the latter case the new asm-internal
symbol is initialized with info from the C symbol table.
If CSYM is non-null we take symbol info from it, otherwise
we look up NAME in the C symbol table and use that. */
Sometimes we need symbols accessible by name from asm, which
are anonymous in C, in this case CSYM can be used to transfer
all information from that symbol to the (possibly newly created)
asm symbol. */
ST_FUNC Sym* get_asm_sym(int name, Sym *csym)
{
Sym *sym = asm_label_find(name);
if (!sym) {
sym = asm_label_push(&tcc_state->asm_labels, name);
sym->type.t = VT_VOID | VT_EXTERN;
if (!csym) {
csym = sym_find(name);
/* We might be called for an asm block from inside a C routine
and so might have local decls on the identifier stack. Search
for the first global one. */
while (csym && csym->sym_scope)
csym = csym->prev_tok;
}
/* Now, if we have a defined global symbol copy over
section and offset. */
if (csym &&
((csym->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST)) &&
csym->c) {
ElfW(Sym) *esym;
esym = &((ElfW(Sym) *)symtab_section->data)[csym->c];
sym->c = csym->c;
sym->r = esym->st_shndx;
sym->jnext = esym->st_value;
/* XXX can't yet store st_size anywhere. */
sym->type.t = VT_VOID | (csym->type.t & VT_STATIC);
/* Mark that this asm symbol doesn't need to be fed back. */
sym->a.asmcsym = 1;
sym->a.asmexport = !(csym->type.t & VT_STATIC);
}
sym = asm_label_push(name, 0);
if (csym)
sym->c = csym->c;
}
return sym;
}
@ -118,16 +94,15 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
sym = asm_label_find(label);
if (*p == 'b') {
/* backward : find the last corresponding defined label */
if (sym && sym->r == 0)
if (sym && (!sym->c || elfsym(sym)->st_shndx == SHN_UNDEF))
sym = sym->prev_tok;
if (!sym)
tcc_error("local label '%d' not found backward", n);
} else {
/* forward */
if (!sym || sym->r) {
if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) {
/* if the last label is defined, then define a new one */
sym = asm_label_push(&s1->asm_labels, label);
sym->type.t = VT_STATIC | VT_VOID | VT_EXTERN;
sym = asm_label_push(label, VT_STATIC);
}
}
pe->v = 0;
@ -175,17 +150,20 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
pe->sym = &sym_dot;
pe->pcrel = 0;
sym_dot.type.t = VT_VOID | VT_STATIC;
sym_dot.r = cur_text_section->sh_num;
sym_dot.jnext = ind;
sym_dot.c = -1;
tcc_state->esym_dot.st_shndx = cur_text_section->sh_num;
tcc_state->esym_dot.st_value = ind;
next();
break;
default:
if (tok >= TOK_IDENT) {
ElfSym *esym;
/* label case : if the label was not found, add one */
sym = get_asm_sym(tok, NULL);
if (sym->r == SHN_ABS) {
esym = elfsym(sym);
if (esym && esym->st_shndx == SHN_ABS) {
/* if absolute symbol, no need to put a symbol value */
pe->v = sym->jnext;
pe->v = esym->st_value;
pe->sym = NULL;
pe->pcrel = 0;
} else {
@ -299,20 +277,26 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
} else if (pe->sym == e2.sym) {
/* OK */
pe->sym = NULL; /* same symbols can be subtracted to NULL */
} else if (pe->sym && pe->sym->r == e2.sym->r && pe->sym->r != 0) {
/* we also accept defined symbols in the same section */
pe->v += pe->sym->jnext - e2.sym->jnext;
pe->sym = NULL;
} else if (e2.sym->r == cur_text_section->sh_num) {
/* When subtracting a defined symbol in current section
this actually makes the value PC-relative. */
pe->v -= e2.sym->jnext - ind - 4;
pe->pcrel = 1;
e2.sym = NULL;
} else {
cannot_relocate:
tcc_error("invalid operation with label");
}
} else {
ElfSym *esym1, *esym2;
esym1 = elfsym(pe->sym);
esym2 = elfsym(e2.sym);
if (esym1 && esym1->st_shndx == esym2->st_shndx
&& esym1->st_shndx != SHN_UNDEF) {
/* we also accept defined symbols in the same section */
pe->v += esym1->st_value - esym2->st_value;
pe->sym = NULL;
} else if (esym2->st_shndx == cur_text_section->sh_num) {
/* When subtracting a defined symbol in current section
this actually makes the value PC-relative. */
pe->v -= esym2->st_value - ind - 4;
pe->pcrel = 1;
e2.sym = NULL;
} else {
cannot_relocate:
tcc_error("invalid operation with label");
}
}
}
}
}
@ -377,13 +361,15 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local,
int sh_num, int value)
{
Sym *sym;
ElfSym *esym;
sym = asm_label_find(label);
if (sym) {
esym = elfsym(sym);
/* A VT_EXTERN symbol, even if it has a section is considered
overridable. This is how we "define" .set targets. Real
definitions won't have VT_EXTERN set. */
if (sym->r && !(sym->type.t & VT_EXTERN)) {
if (esym && esym->st_shndx != SHN_UNDEF && !(sym->type.t & VT_EXTERN)) {
/* the label is already defined */
if (!is_local) {
tcc_error("assembler label '%s' already defined",
@ -395,14 +381,13 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local,
}
} else {
new_label:
sym = asm_label_push(&s1->asm_labels, label);
/* If we need a symbol to hold a value, mark it as
tentative only (for .set). If this is for a real label
we'll remove VT_EXTERN. */
sym->type.t = VT_VOID | (is_local ? VT_STATIC : 0) | VT_EXTERN;
sym = asm_label_push(label, is_local ? VT_STATIC : 0);
}
sym->r = sh_num;
sym->jnext = value;
if (!sym->c)
put_extern_sym2(sym, NULL, 0, 0, 0);
esym = elfsym(sym);
esym->st_shndx = sh_num;
esym->st_value = value;
return sym;
}
@ -417,79 +402,41 @@ static Sym* set_symbol(TCCState *s1, int label)
{
long n;
ExprValue e;
Sym *sym;
ElfSym *esym;
next();
asm_expr(s1, &e);
n = e.v;
if (e.sym)
n += e.sym->jnext;
return asm_new_label1(s1, label, 0, e.sym ? e.sym->r : SHN_ABS, n);
}
/* Patch ELF symbol associated with SYM based on the assemblers
understanding. */
static void patch_binding(Sym *sym)
{
ElfW(Sym) *esym;
if (0 == sym->c)
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;
esym->st_info = ELFW(ST_INFO)(sym->a.weak ? STB_WEAK
: (sym->type.t & VT_STATIC) ? STB_LOCAL
: STB_GLOBAL,
ELFW(ST_TYPE)(esym->st_info));
esym = elfsym(e.sym);
if (esym)
n += esym->st_value;
sym = asm_new_label1(s1, label, 0, esym ? esym->st_shndx : SHN_ABS, n);
elfsym(sym)->st_other |= ST_ASM_SET;
return sym;
}
ST_FUNC void asm_free_labels(TCCState *st)
{
Sym *s, *s1;
Section *sec;
for(s = st->asm_labels; s != NULL; s = s1) {
int was_ext = s->type.t & VT_EXTERN;
ElfSym *esym = elfsym(s);
s1 = s->prev;
/* define symbol value in object file and care for updating
the C and asm symbols */
/* Possibly update binding and visibility from asm directives. */
s->type.t &= ~VT_EXTERN;
if (!s->a.asmcsym) {
Sym *csym = sym_find(s->v);
ElfW(Sym) *esym = NULL;
if (csym) {
s->a.asmexport |= !(csym->type.t & VT_STATIC);
if (csym->c) {
esym = &((ElfW(Sym) *)symtab_section->data)[csym->c];
if (s->c) {
/* We have generated code and possibly relocs
referencing the symtab entry s->c (the asm
ELF symbol). If that's undefined but the C
symbol is defined, copy over the info. */
ElfW(Sym) *asm_esym = &((ElfW(Sym) *)symtab_section->data)[s->c];
if (asm_esym->st_shndx == SHN_UNDEF) {
*asm_esym = *esym;
}
}
}
}
if (!s->a.asmexport)
s->type.t |= VT_STATIC;
if (s->r) {
if (s->r == SHN_ABS)
sec = SECTION_ABS;
else
sec = st->sections[s->r];
/* !was_ext so that we run into an multi-def error if
we defined it in C and in asm (non-tentatively) */
if (!esym || esym->st_shndx == SHN_UNDEF || !was_ext)
put_extern_sym2(s, sec, s->jnext, 0, 0);
} else /* undefined symbols are global */
s->type.t &= ~VT_STATIC, s->a.asmexport = 1;
patch_binding(s);
if (esym) {
if (!s->a.asmexport && esym->st_shndx != SHN_UNDEF)
s->type.t |= VT_STATIC;
if (s->a.visibility)
esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
| s->a.visibility;
esym->st_info = ELFW(ST_INFO)(s->a.weak ? STB_WEAK
: (s->type.t & VT_STATIC) ? STB_LOCAL
: STB_GLOBAL,
ELFW(ST_TYPE)(esym->st_info));
}
/* remove label */
table_ident[s->v - TOK_IDENT]->sym_asm_label = NULL;
table_ident[s->v - TOK_IDENT]->sym_identifier = s->prev_tok;
sym_free(s);
}
st->asm_labels = NULL;
@ -715,13 +662,15 @@ static void asm_parse_directive(TCCState *s1, int global)
{
unsigned long n;
ExprValue e;
ElfSym *esym;
next();
asm_expr(s1, &e);
n = e.v;
if (e.sym) {
if (e.sym->r != cur_text_section->sh_num)
esym = elfsym(e.sym);
if (esym) {
if (esym->st_shndx != cur_text_section->sh_num)
expect("constant or same-section symbol");
n += e.sym->jnext;
n += esym->st_value;
}
if (n < ind)
tcc_error("attempt to .org backwards");
@ -978,7 +927,6 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global)
int opcode;
int saved_parse_flags = parse_flags;
/* XXX: undefine C labels */
parse_flags = PARSE_FLAG_ASM_FILE | PARSE_FLAG_TOK_STR;
if (do_preprocess)
parse_flags |= PARSE_FLAG_PREPROCESS;
@ -1017,18 +965,8 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global)
opcode = tok;
next();
if (tok == ':') {
/* handle "extern void vide(void); __asm__("vide: ret");" as
"__asm__("globl vide\nvide: ret");" */
Sym *sym = sym_find(opcode);
if (sym && (sym->type.t & VT_EXTERN) && global) {
sym = asm_label_find(opcode);
if (!sym) {
sym = asm_label_push(&s1->asm_labels, opcode);
sym->type.t = VT_VOID | VT_EXTERN;
}
}
/* new label */
sym = asm_new_label(s1, opcode, 0);
Sym *sym = asm_new_label(s1, opcode, 0);
sym->type.t &= ~VT_EXTERN;
next();
goto redo;

View File

@ -310,7 +310,8 @@ static void rebuild_hash(Section *s, unsigned int nb_buckets)
sym = (ElfW(Sym) *)s->data + 1;
for(sym_index = 1; sym_index < nb_syms; sym_index++) {
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL
|| sym->st_shndx == SHN_UNDEF) {
h = elf_hash(strtab + sym->st_name) % nb_buckets;
*ptr = hash[h];
hash[h] = sym_index;
@ -349,8 +350,9 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
int *ptr, *base;
ptr = section_ptr_add(hs, sizeof(int));
base = (int *)hs->data;
/* only add global or weak symbols */
if (ELFW(ST_BIND)(info) != STB_LOCAL) {
/* only add global, weak or undef symbols. The latter might
become global late (from asm references). */
if (ELFW(ST_BIND)(info) != STB_LOCAL || shndx == SHN_UNDEF) {
/* add another hashing entry */
nbuckets = base[0];
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,
/* data symbol keeps precedence over common/bss */
} else if (s == tcc_state->dynsymtab_section) {
/* we accept that two DLL define the same symbol */
} else if (esym->st_other & ST_ASM_SET) {
/* If the existing symbol came from an asm .set
we can override. */
goto do_patch;
} else {
#if 0
printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",

View File

@ -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. */

View File

@ -432,7 +432,6 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
ts->sym_label = NULL;
ts->sym_struct = NULL;
ts->sym_identifier = NULL;
ts->sym_asm_label = NULL;
ts->len = len;
ts->hash_next = NULL;
memcpy(ts->str, str, len);

View File

@ -14,11 +14,13 @@ static int x1_c(void)
asm(".text;"_"x1: call "_"x1_c; ret");
void callx4(void);
int main(int argc, char *argv[])
{
asm("call "_"x1");
asm("call "_"x2");
asm("call "_"x3");
callx4();
return 0;
}
@ -30,3 +32,8 @@ int x2(void)
}
extern int x3(void);
void x4(void)
{
printf("x4\n");
}

View File

@ -5,3 +5,6 @@ int x3(void)
printf("x3\n");
return 3;
}
void callx4(void);
__asm__("callx4: call x4; ret");