via some heavy-handed hackery in the ASM symbol handling in case C symbols get a leading underscore (but ASM symbols do not). But this is now like clang and GCC on Darwin work: asm symbols are undecorated, C symbols get a _ prepended, so to connect both some trickery is involved for the ASM symbols that don't have a _ prepended. They must be included in the C symbol table (because that's what we use to lookup also ASM labels), but they also must not disturb the normal C symbol (which don't have the _ prepended), so they need some mangling. A bit unsatisfying, but well. So, add asm-c-connect-test to the working ones for Darwin as well.
Unified · Split
| @@ -1490,6 +1490,8 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 1489 unmodified lines | |||
| 1490 | list when we still know the symbol. */ | 1490 | list when we still know the symbol. */ |
| 1491 | get_asm_sym(tok_alloc(name, strlen(name))->tok, sv->sym); | 1491 | get_asm_sym(tok_alloc(name, strlen(name))->tok, sv->sym); |
| 1492 | } | 1492 | } |
| 1493 | if (tcc_state->leading_underscore) | ||
| 1494 | cstr_ccat(add_str, '_'); | ||
| 1493 | cstr_cat(add_str, name, -1); | 1495 | cstr_cat(add_str, name, -1); |
| 1494 | if ((uint32_t)sv->c.i == 0) | 1496 | if ((uint32_t)sv->c.i == 0) |
| 1495 | goto no_offset; | 1497 | goto no_offset; |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | #ifdef __APPLE__ | 4 | #ifdef __APPLE__ |
| 5 | #define __bound_alloca ___bound_alloca | 5 | #define __bound_alloca ___bound_alloca |
| 6 | #define __bound_alloca_nr ___bound_alloca_nr | 6 | #define __bound_alloca_nr ___bound_alloca_nr |
| 7 | #define __bound_new_region ___bound_new_region | ||
| 7 | #endif | 8 | #endif |
| 8 | 9 | ||
| 9 | .globl __bound_alloca | 10 | .globl __bound_alloca |
| @@ -38,9 +38,39 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global); · 37 unmodified lines | |||
| 38 | static Sym* asm_new_label(TCCState *s1, int label, int is_local); | 38 | static Sym* asm_new_label(TCCState *s1, int label, int is_local); |
| 39 | static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value); | 39 | static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value); |
| 40 | 40 | ||
| 41 | /* If a C name has an _ prepended then only asm labels that start | ||
| 42 | with _ are representable in C, by removing the first _. ASM names | ||
| 43 | without _ at the beginning don't correspond to C names, but we use | ||
| 44 | the global C symbol table to track ASM names as well, so we need to | ||
| 45 | transform those into ones that don't conflict with a C name, | ||
| 46 | so prepend a '.' for them, but force the ELF asm name to be set. */ | ||
| 47 | static int asm2cname(int v, int *addeddot) | ||
| 48 | { | ||
| 49 | const char *name; | ||
| 50 | *addeddot = 0; | ||
| 51 | if (!tcc_state->leading_underscore) | ||
| 52 | return v; | ||
| 53 | name = get_tok_str(v, NULL); | ||
| 54 | if (!name) | ||
| 55 | return v; | ||
| 56 | if (name[0] == '_') { | ||
| 57 | v = tok_alloc(name + 1, strlen(name) - 1)->tok; | ||
| 58 | } else if (!strchr(name, '.')) { | ||
| 59 | int n = strlen(name) + 2; | ||
| 60 | char newname[n]; | ||
| 61 | snprintf(newname, n, ".%s", name); | ||
| 62 | v = tok_alloc(newname, n - 1)->tok; | ||
| 63 | *addeddot = 1; | ||
| 64 | } | ||
| 65 | return v; | ||
| 66 | } | ||
| 67 | |||
| 41 | static Sym *asm_label_find(int v) | 68 | static Sym *asm_label_find(int v) |
| 42 | { | 69 | { |
| 43 | Sym *sym = sym_find(v); | 70 | Sym *sym; |
| 71 | int addeddot; | ||
| 72 | v = asm2cname(v, &addeddot); | ||
| 73 | sym = sym_find(v); | ||
| 44 | while (sym && sym->sym_scope && !(sym->type.t & VT_STATIC)) | 74 | while (sym && sym->sym_scope && !(sym->type.t & VT_STATIC)) |
| 45 | sym = sym->prev_tok; | 75 | sym = sym->prev_tok; |
| 46 | return sym; | 76 | return sym; |
| @@ -48,10 +78,14 @@ static Sym *asm_label_find(int v) · 1 unmodified line | |||
| 48 | 78 | ||
| 49 | static Sym *asm_label_push(int v) | 79 | static Sym *asm_label_push(int v) |
| 50 | { | 80 | { |
| 81 | int addeddot, v2 = asm2cname(v, &addeddot); | ||
| 51 | /* We always add VT_EXTERN, for sym definition that's tentative | 82 | /* We always add VT_EXTERN, for sym definition that's tentative |
| 52 | (for .set, removed for real defs), for mere references it's correct | 83 | (for .set, removed for real defs), for mere references it's correct |
| 53 | as is. */ | 84 | as is. */ |
| 54 | return global_identifier_push(v, VT_ASM | VT_EXTERN | VT_STATIC, 0); | 85 | Sym *sym = global_identifier_push(v2, VT_ASM | VT_EXTERN | VT_STATIC, 0); |
| 86 | if (addeddot) | ||
| 87 | sym->asm_label = v; | ||
| 88 | return sym; | ||
| 55 | } | 89 | } |
| 56 | 90 | ||
| 57 | /* Return a symbol we can use inside the assembler, having name NAME. | 91 | /* Return a symbol we can use inside the assembler, having name NAME. |
| @@ -390,7 +424,7 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local, · 332 unmodified lines | |||
| 390 | sym = asm_label_push(label); | 424 | sym = asm_label_push(label); |
| 391 | } | 425 | } |
| 392 | if (!sym->c) | 426 | if (!sym->c) |
| 393 | put_extern_sym2(sym, SHN_UNDEF, 0, 0, 0); | 427 | put_extern_sym2(sym, SHN_UNDEF, 0, 0, 1); |
| 394 | esym = elfsym(sym); | 428 | esym = elfsym(sym); |
| 395 | esym->st_shndx = sh_num; | 429 | esym->st_shndx = sh_num; |
| 396 | esym->st_value = value; | 430 | esym->st_value = value; |
| @@ -46,7 +46,7 @@ ifeq ($(ARCH),riscv64) · 45 unmodified lines | |||
| 46 | endif | 46 | endif |
| 47 | endif | 47 | endif |
| 48 | ifdef CONFIG_OSX # some don't work yet | 48 | ifdef CONFIG_OSX # some don't work yet |
| 49 | TESTS := $(filter-out memtest dlltest asm-c-connect-test, $(TESTS)) | 49 | TESTS := $(filter-out memtest dlltest, $(TESTS)) |
| 50 | endif | 50 | endif |
| 51 | ifeq (,$(filter arm64 i386 x86_64,$(ARCH))) | 51 | ifeq (,$(filter arm64 i386 x86_64,$(ARCH))) |
| 52 | TESTS := $(filter-out vla_test-run,$(TESTS)) | 52 | TESTS := $(filter-out vla_test-run,$(TESTS)) |
| @@ -2,11 +2,20 @@ · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | #if defined _WIN32 && !defined __TINYC__ | 3 | #if defined _WIN32 && !defined __TINYC__ |
| 4 | # define _ "_" | 4 | # define _ "_" |
| 5 | #elif defined __APPLE__ | ||
| 6 | # define _ "_" | ||
| 5 | #else | 7 | #else |
| 6 | # define _ | 8 | # define _ |
| 7 | #endif | 9 | #endif |
| 8 | 10 | ||
| 9 | static int x1_c(void) | 11 | #ifdef __clang__ |
| 12 | /* clang needs some help tp not throw functions away even at -O0 */ | ||
| 13 | #define __USED __attribute__((__used__)) | ||
| 14 | #else | ||
| 15 | #define __USED | ||
| 16 | #endif | ||
| 17 | |||
| 18 | static int __USED x1_c (void) | ||
| 10 | { | 19 | { |
| 11 | printf(" x1"); | 20 | printf(" x1"); |
| 12 | return 1; | 21 | return 1; |
| @@ -37,7 +46,7 @@ int main(int argc, char *argv[]) · 24 unmodified lines | |||
| 37 | } | 46 | } |
| 38 | 47 | ||
| 39 | static | 48 | static |
| 40 | int x2(void) | 49 | int __USED x2(void) |
| 41 | { | 50 | { |
| 42 | printf(" x2"); | 51 | printf(" x2"); |
| 43 | return 2; | 52 | return 2; |
| @@ -2,10 +2,19 @@ · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | #if defined _WIN32 && !defined __TINYC__ | 3 | #if defined _WIN32 && !defined __TINYC__ |
| 4 | # define _ "_" | 4 | # define _ "_" |
| 5 | #elif defined __APPLE__ | ||
| 6 | # define _ "_" | ||
| 5 | #else | 7 | #else |
| 6 | # define _ | 8 | # define _ |
| 7 | #endif | 9 | #endif |
| 8 | 10 | ||
| 11 | #ifdef __clang__ | ||
| 12 | /* clang needs some help tp not throw functions away even at -O0 */ | ||
| 13 | #define __USED __attribute__((__used__)) | ||
| 14 | #else | ||
| 15 | #define __USED | ||
| 16 | #endif | ||
| 17 | |||
| 9 | int x3(void) | 18 | int x3(void) |
| 10 | { | 19 | { |
| 11 | printf(" x3"); | 20 | printf(" x3"); |
| @@ -30,7 +39,7 @@ void callx5_again(void) · 18 unmodified lines | |||
| 30 | asm("call "_"x6"); | 39 | asm("call "_"x6"); |
| 31 | } | 40 | } |
| 32 | 41 | ||
| 33 | static void x6() | 42 | static void __USED x6() |
| 34 | { | 43 | { |
| 35 | printf(" x6-2"); | 44 | printf(" x6-2"); |
| 36 | } | 45 | } |
| @@ -3650,7 +3650,7 @@ void test_asm_call(void) · 3649 unmodified lines | |||
| 3650 | asm volatile ("push %%rdi; push %%rdi; mov %0, %%rdi;" | 3650 | asm volatile ("push %%rdi; push %%rdi; mov %0, %%rdi;" |
| 3651 | #if 1 && !defined(__TINYC__) && (defined(__PIC__) || defined(__PIE__)) && !defined(__APPLE__) | 3651 | #if 1 && !defined(__TINYC__) && (defined(__PIC__) || defined(__PIE__)) && !defined(__APPLE__) |
| 3652 | "call getenv@plt;" | 3652 | "call getenv@plt;" |
| 3653 | #elif defined(__APPLE__) && !defined(__TINYC__) | 3653 | #elif defined(__APPLE__) |
| 3654 | "call _getenv;" | 3654 | "call _getenv;" |
| 3655 | #else | 3655 | #else |
| 3656 | "call getenv;" | 3656 | "call getenv;" |
| @@ -1,6 +1,11 @@ | |||
| 1 | #ifdef __APPLE__ | ||
| 2 | #define _ "_" | ||
| 3 | #else | ||
| 4 | #define _ | ||
| 5 | #endif | ||
| 1 | extern int printf (const char *, ...); | 6 | extern int printf (const char *, ...); |
| 2 | extern void vide(void); | 7 | extern void vide(void); |
| 3 | __asm__("vide: ret"); | 8 | __asm__(_"vide: ret"); |
| 4 | 9 | ||
| 5 | int main() { | 10 | int main() { |
| 6 | vide(); | 11 | vide(); |