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 | 1490 | list when we still know the symbol. */ |
| 1491 | 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 | 1495 | cstr_cat(add_str, name, -1); |
| 1494 | 1496 | if ((uint32_t)sv->c.i == 0) |
| 1495 | 1497 | goto no_offset; |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | #ifdef __APPLE__ |
| 5 | 5 | #define __bound_alloca ___bound_alloca |
| 6 | 6 | #define __bound_alloca_nr ___bound_alloca_nr |
| 7 | +#define __bound_new_region ___bound_new_region | |
| 7 | 8 | #endif |
| 8 | 9 | |
| 9 | 10 | .globl __bound_alloca |
| @@ -38,9 +38,39 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global); · 37 unmodified lines | ||
| 38 | 38 | static Sym* asm_new_label(TCCState *s1, int label, int is_local); |
| 39 | 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 | 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 | 74 | while (sym && sym->sym_scope && !(sym->type.t & VT_STATIC)) |
| 45 | 75 | sym = sym->prev_tok; |
| 46 | 76 | return sym; |
| @@ -48,10 +78,14 @@ static Sym *asm_label_find(int v) · 1 unmodified line | ||
| 48 | 78 | |
| 49 | 79 | static Sym *asm_label_push(int v) |
| 50 | 80 | { |
| 81 | + int addeddot, v2 = asm2cname(v, &addeddot); | |
| 51 | 82 | /* We always add VT_EXTERN, for sym definition that's tentative |
| 52 | 83 | (for .set, removed for real defs), for mere references it's correct |
| 53 | 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 | 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 | 424 | sym = asm_label_push(label); |
| 391 | 425 | } |
| 392 | 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 | 428 | esym = elfsym(sym); |
| 395 | 429 | esym->st_shndx = sh_num; |
| 396 | 430 | esym->st_value = value; |
| @@ -46,7 +46,7 @@ ifeq ($(ARCH),riscv64) · 45 unmodified lines | ||
| 46 | 46 | endif |
| 47 | 47 | endif |
| 48 | 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 | 50 | endif |
| 51 | 51 | ifeq (,$(filter arm64 i386 x86_64,$(ARCH))) |
| 52 | 52 | TESTS := $(filter-out vla_test-run,$(TESTS)) |
| @@ -2,11 +2,20 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | #if defined _WIN32 && !defined __TINYC__ |
| 4 | 4 | # define _ "_" |
| 5 | +#elif defined __APPLE__ | |
| 6 | +# define _ "_" | |
| 5 | 7 | #else |
| 6 | 8 | # define _ |
| 7 | 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 | 20 | printf(" x1"); |
| 12 | 21 | return 1; |
| @@ -37,7 +46,7 @@ int main(int argc, char *argv[]) · 24 unmodified lines | ||
| 37 | 46 | } |
| 38 | 47 | |
| 39 | 48 | static |
| 40 | −int x2(void) | |
| 49 | +int __USED x2(void) | |
| 41 | 50 | { |
| 42 | 51 | printf(" x2"); |
| 43 | 52 | return 2; |
| @@ -2,10 +2,19 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | #if defined _WIN32 && !defined __TINYC__ |
| 4 | 4 | # define _ "_" |
| 5 | +#elif defined __APPLE__ | |
| 6 | +# define _ "_" | |
| 5 | 7 | #else |
| 6 | 8 | # define _ |
| 7 | 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 | 18 | int x3(void) |
| 10 | 19 | { |
| 11 | 20 | printf(" x3"); |
| @@ -30,7 +39,7 @@ void callx5_again(void) · 18 unmodified lines | ||
| 30 | 39 | asm("call "_"x6"); |
| 31 | 40 | } |
| 32 | 41 | |
| 33 | −static void x6() | |
| 42 | +static void __USED x6() | |
| 34 | 43 | { |
| 35 | 44 | printf(" x6-2"); |
| 36 | 45 | } |
| @@ -3650,7 +3650,7 @@ void test_asm_call(void) · 3649 unmodified lines | ||
| 3650 | 3650 | asm volatile ("push %%rdi; push %%rdi; mov %0, %%rdi;" |
| 3651 | 3651 | #if 1 && !defined(__TINYC__) && (defined(__PIC__) || defined(__PIE__)) && !defined(__APPLE__) |
| 3652 | 3652 | "call getenv@plt;" |
| 3653 | −#elif defined(__APPLE__) && !defined(__TINYC__) | |
| 3653 | +#elif defined(__APPLE__) | |
| 3654 | 3654 | "call _getenv;" |
| 3655 | 3655 | #else |
| 3656 | 3656 | "call getenv;" |
| @@ -1,6 +1,11 @@ | ||
| 1 | +#ifdef __APPLE__ | |
| 2 | +#define _ "_" | |
| 3 | +#else | |
| 4 | +#define _ | |
| 5 | +#endif | |
| 1 | 6 | extern int printf (const char *, ...); |
| 2 | 7 | extern void vide(void); |
| 3 | −__asm__("vide: ret"); | |
| 8 | +__asm__(_"vide: ret"); | |
| 4 | 9 | |
| 5 | 10 | int main() { |
| 6 | 11 | vide(); |