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.
Unified · Split
| @@ -422,9 +422,10 @@ ST_FUNC void asm_free_labels(TCCState *st) · 421 unmodified lines | |||
| 422 | for(s = st->asm_labels; s != NULL; s = s1) { | 422 | for(s = st->asm_labels; s != NULL; s = s1) { |
| 423 | ElfSym *esym = elfsym(s); | 423 | ElfSym *esym = elfsym(s); |
| 424 | s1 = s->prev; | 424 | s1 = s->prev; |
| 425 | /* Possibly update binding and visibility from asm directives. */ | 425 | /* Possibly update binding and visibility from asm directives |
| 426 | if the symbol has no C decl (type is VT_VOID).*/ | ||
| 426 | s->type.t &= ~VT_EXTERN; | 427 | s->type.t &= ~VT_EXTERN; |
| 427 | if (esym) { | 428 | if (esym && s->type.t == VT_VOID) { |
| 428 | if (!s->a.asmexport && esym->st_shndx != SHN_UNDEF) | 429 | if (!s->a.asmexport && esym->st_shndx != SHN_UNDEF) |
| 429 | s->type.t |= VT_STATIC; | 430 | s->type.t |= VT_STATIC; |
| 430 | if (s->a.visibility) | 431 | if (s->a.visibility) |
| @@ -235,9 +235,16 @@ vla_test-run: vla_test$(EXESUF) · 234 unmodified lines | |||
| 235 | asm-c-connect$(EXESUF): asm-c-connect-1.c asm-c-connect-2.c | 235 | asm-c-connect$(EXESUF): asm-c-connect-1.c asm-c-connect-2.c |
| 236 | $(TCC) -o $@ $^ | 236 | $(TCC) -o $@ $^ |
| 237 | 237 | ||
| 238 | asm-c-connect-test: asm-c-connect$(EXESUF) | 238 | asm-c-connect-%.o: asm-c-connect-%.c |
| 239 | $(TCC) -c -o $@ $< | ||
| 240 | |||
| 241 | asm-c-connect-sep$(EXESUF): asm-c-connect-1.o asm-c-connect-2.o | ||
| 242 | $(TCC) -o $@ $^ | ||
| 243 | |||
| 244 | asm-c-connect-test: asm-c-connect$(EXESUF) asm-c-connect-sep$(EXESUF) | ||
| 239 | @echo ------------ $@ ------------ | 245 | @echo ------------ $@ ------------ |
| 240 | ./asm-c-connect$(EXESUF) | 246 | ./asm-c-connect$(EXESUF) |
| 247 | ./asm-c-connect-sep$(EXESUF) | ||
| 241 | 248 | ||
| 242 | cross-test : | 249 | cross-test : |
| 243 | @echo ------------ $@ ------------ | 250 | @echo ------------ $@ ------------ |
| @@ -15,12 +15,15 @@ static int x1_c(void) · 14 unmodified lines | |||
| 15 | asm(".text;"_"x1: call "_"x1_c; ret"); | 15 | asm(".text;"_"x1: call "_"x1_c; ret"); |
| 16 | 16 | ||
| 17 | void callx4(void); | 17 | void callx4(void); |
| 18 | void callx5_again(void); | ||
| 18 | int main(int argc, char *argv[]) | 19 | int main(int argc, char *argv[]) |
| 19 | { | 20 | { |
| 20 | asm("call "_"x1"); | 21 | asm("call "_"x1"); |
| 21 | asm("call "_"x2"); | 22 | asm("call "_"x2"); |
| 22 | asm("call "_"x3"); | 23 | asm("call "_"x3"); |
| 23 | callx4(); | 24 | callx4(); |
| 25 | asm("call "_"x5"); | ||
| 26 | callx5_again(); | ||
| 24 | return 0; | 27 | return 0; |
| 25 | } | 28 | } |
| 26 | 29 | ||
| @@ -37,3 +40,9 @@ void x4(void) · 10 unmodified lines | |||
| 37 | { | 40 | { |
| 38 | printf("x4\n"); | 41 | printf("x4\n"); |
| 39 | } | 42 | } |
| 43 | |||
| 44 | void x5(void); | ||
| 45 | void x5(void) | ||
| 46 | { | ||
| 47 | printf("x5\n"); | ||
| 48 | } | ||
| @@ -6,5 +6,14 @@ int x3(void) · 5 unmodified lines | |||
| 6 | return 3; | 6 | return 3; |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | /* That callx4 is defined globally (as if ".globl callx4") | ||
| 10 | is a TCC extension. GCC doesn't behave like this. */ | ||
| 9 | void callx4(void); | 11 | void callx4(void); |
| 10 | __asm__("callx4: call x4; ret"); | 12 | __asm__("callx4: call x4; ret"); |
| 13 | |||
| 14 | extern void x5(void); | ||
| 15 | void callx5_again(void); | ||
| 16 | void callx5_again(void) | ||
| 17 | { | ||
| 18 | x5(); | ||
| 19 | } | ||