Fix another corner case with C/asm symtable

See testcase (from grischka).  If the asm has no .globl,
but there's a (non-static) C definition the symbol should
be exported, even if the first reference comes from asm.
This commit is contained in:
Michael Matz 2017-12-04 03:51:14 +01:00
parent 529b44c0d5
commit cc6cb7f0e2
4 changed files with 29 additions and 3 deletions

View File

@ -422,9 +422,10 @@ ST_FUNC void asm_free_labels(TCCState *st)
for(s = st->asm_labels; s != NULL; s = s1) { for(s = st->asm_labels; s != NULL; s = s1) {
ElfSym *esym = elfsym(s); ElfSym *esym = elfsym(s);
s1 = s->prev; s1 = s->prev;
/* Possibly update binding and visibility from asm directives. */ /* Possibly update binding and visibility from asm directives
if the symbol has no C decl (type is VT_VOID).*/
s->type.t &= ~VT_EXTERN; s->type.t &= ~VT_EXTERN;
if (esym) { if (esym && s->type.t == VT_VOID) {
if (!s->a.asmexport && esym->st_shndx != SHN_UNDEF) if (!s->a.asmexport && esym->st_shndx != SHN_UNDEF)
s->type.t |= VT_STATIC; s->type.t |= VT_STATIC;
if (s->a.visibility) if (s->a.visibility)

View File

@ -235,9 +235,16 @@ vla_test-run: vla_test$(EXESUF)
asm-c-connect$(EXESUF): asm-c-connect-1.c asm-c-connect-2.c asm-c-connect$(EXESUF): asm-c-connect-1.c asm-c-connect-2.c
$(TCC) -o $@ $^ $(TCC) -o $@ $^
asm-c-connect-test: asm-c-connect$(EXESUF) asm-c-connect-%.o: asm-c-connect-%.c
$(TCC) -c -o $@ $<
asm-c-connect-sep$(EXESUF): asm-c-connect-1.o asm-c-connect-2.o
$(TCC) -o $@ $^
asm-c-connect-test: asm-c-connect$(EXESUF) asm-c-connect-sep$(EXESUF)
@echo ------------ $@ ------------ @echo ------------ $@ ------------
./asm-c-connect$(EXESUF) ./asm-c-connect$(EXESUF)
./asm-c-connect-sep$(EXESUF)
cross-test : cross-test :
@echo ------------ $@ ------------ @echo ------------ $@ ------------

View File

@ -15,12 +15,15 @@ static int x1_c(void)
asm(".text;"_"x1: call "_"x1_c; ret"); asm(".text;"_"x1: call "_"x1_c; ret");
void callx4(void); void callx4(void);
void callx5_again(void);
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
asm("call "_"x1"); asm("call "_"x1");
asm("call "_"x2"); asm("call "_"x2");
asm("call "_"x3"); asm("call "_"x3");
callx4(); callx4();
asm("call "_"x5");
callx5_again();
return 0; return 0;
} }
@ -37,3 +40,9 @@ void x4(void)
{ {
printf("x4\n"); printf("x4\n");
} }
void x5(void);
void x5(void)
{
printf("x5\n");
}

View File

@ -6,5 +6,14 @@ int x3(void)
return 3; return 3;
} }
/* That callx4 is defined globally (as if ".globl callx4")
is a TCC extension. GCC doesn't behave like this. */
void callx4(void); void callx4(void);
__asm__("callx4: call x4; ret"); __asm__("callx4: call x4; ret");
extern void x5(void);
void callx5_again(void);
void callx5_again(void)
{
x5();
}