diff --git a/i386-asm.c b/i386-asm.c index 43d09da8..4e62c3c8 100644 --- a/i386-asm.c +++ b/i386-asm.c @@ -1490,6 +1490,8 @@ ST_FUNC void subst_asm_operand(CString *add_str, list when we still know the symbol. */ get_asm_sym(tok_alloc(name, strlen(name))->tok, sv->sym); } + if (tcc_state->leading_underscore) + cstr_ccat(add_str, '_'); cstr_cat(add_str, name, -1); if ((uint32_t)sv->c.i == 0) goto no_offset; diff --git a/lib/alloca86_64-bt.S b/lib/alloca86_64-bt.S index 34ab0e77..c3f4e54c 100644 --- a/lib/alloca86_64-bt.S +++ b/lib/alloca86_64-bt.S @@ -4,6 +4,7 @@ #ifdef __APPLE__ #define __bound_alloca ___bound_alloca #define __bound_alloca_nr ___bound_alloca_nr +#define __bound_new_region ___bound_new_region #endif .globl __bound_alloca diff --git a/tccasm.c b/tccasm.c index c89cdc67..93ae95b3 100644 --- a/tccasm.c +++ b/tccasm.c @@ -38,9 +38,39 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global); static Sym* asm_new_label(TCCState *s1, int label, int is_local); static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value); +/* If a C name has an _ prepended then only asm labels that start + with _ are representable in C, by removing the first _. ASM names + without _ at the beginning don't correspond to C names, but we use + the global C symbol table to track ASM names as well, so we need to + transform those into ones that don't conflict with a C name, + so prepend a '.' for them, but force the ELF asm name to be set. */ +static int asm2cname(int v, int *addeddot) +{ + const char *name; + *addeddot = 0; + if (!tcc_state->leading_underscore) + return v; + name = get_tok_str(v, NULL); + if (!name) + return v; + if (name[0] == '_') { + v = tok_alloc(name + 1, strlen(name) - 1)->tok; + } else if (!strchr(name, '.')) { + int n = strlen(name) + 2; + char newname[n]; + snprintf(newname, n, ".%s", name); + v = tok_alloc(newname, n - 1)->tok; + *addeddot = 1; + } + return v; +} + static Sym *asm_label_find(int v) { - Sym *sym = sym_find(v); + Sym *sym; + int addeddot; + v = asm2cname(v, &addeddot); + sym = sym_find(v); while (sym && sym->sym_scope && !(sym->type.t & VT_STATIC)) sym = sym->prev_tok; return sym; @@ -48,10 +78,14 @@ static Sym *asm_label_find(int v) static Sym *asm_label_push(int v) { + int addeddot, v2 = asm2cname(v, &addeddot); /* 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. */ - return global_identifier_push(v, VT_ASM | VT_EXTERN | VT_STATIC, 0); + Sym *sym = global_identifier_push(v2, VT_ASM | VT_EXTERN | VT_STATIC, 0); + if (addeddot) + sym->asm_label = v; + return sym; } /* 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, sym = asm_label_push(label); } if (!sym->c) - put_extern_sym2(sym, SHN_UNDEF, 0, 0, 0); + put_extern_sym2(sym, SHN_UNDEF, 0, 0, 1); esym = elfsym(sym); esym->st_shndx = sh_num; esym->st_value = value; diff --git a/tests/Makefile b/tests/Makefile index 03a74218..a8f4d343 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -46,7 +46,7 @@ ifeq ($(ARCH),riscv64) endif endif ifdef CONFIG_OSX # some don't work yet - TESTS := $(filter-out memtest dlltest asm-c-connect-test, $(TESTS)) + TESTS := $(filter-out memtest dlltest, $(TESTS)) endif ifeq (,$(filter arm64 i386 x86_64,$(ARCH))) TESTS := $(filter-out vla_test-run,$(TESTS)) diff --git a/tests/asm-c-connect-1.c b/tests/asm-c-connect-1.c index 8a28d781..c515c8d9 100644 --- a/tests/asm-c-connect-1.c +++ b/tests/asm-c-connect-1.c @@ -2,11 +2,20 @@ #if defined _WIN32 && !defined __TINYC__ # define _ "_" +#elif defined __APPLE__ +# define _ "_" #else # define _ #endif -static int x1_c(void) +#ifdef __clang__ +/* clang needs some help tp not throw functions away even at -O0 */ +#define __USED __attribute__((__used__)) +#else +#define __USED +#endif + +static int __USED x1_c (void) { printf(" x1"); return 1; @@ -37,7 +46,7 @@ int main(int argc, char *argv[]) } static -int x2(void) +int __USED x2(void) { printf(" x2"); return 2; diff --git a/tests/asm-c-connect-2.c b/tests/asm-c-connect-2.c index 3440b40b..4c00c713 100644 --- a/tests/asm-c-connect-2.c +++ b/tests/asm-c-connect-2.c @@ -2,10 +2,19 @@ #if defined _WIN32 && !defined __TINYC__ # define _ "_" +#elif defined __APPLE__ +# define _ "_" #else # define _ #endif +#ifdef __clang__ +/* clang needs some help tp not throw functions away even at -O0 */ +#define __USED __attribute__((__used__)) +#else +#define __USED +#endif + int x3(void) { printf(" x3"); @@ -30,7 +39,7 @@ void callx5_again(void) asm("call "_"x6"); } -static void x6() +static void __USED x6() { printf(" x6-2"); } diff --git a/tests/tcctest.c b/tests/tcctest.c index d83c740b..73a90ca7 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -3650,7 +3650,7 @@ void test_asm_call(void) asm volatile ("push %%rdi; push %%rdi; mov %0, %%rdi;" #if 1 && !defined(__TINYC__) && (defined(__PIC__) || defined(__PIE__)) && !defined(__APPLE__) "call getenv@plt;" -#elif defined(__APPLE__) && !defined(__TINYC__) +#elif defined(__APPLE__) "call _getenv;" #else "call getenv;" diff --git a/tests/tests2/85_asm-outside-function.c b/tests/tests2/85_asm-outside-function.c index dc5639a4..a7bd5b95 100644 --- a/tests/tests2/85_asm-outside-function.c +++ b/tests/tests2/85_asm-outside-function.c @@ -1,6 +1,11 @@ +#ifdef __APPLE__ +#define _ "_" +#else +#define _ +#endif extern int printf (const char *, ...); extern void vide(void); -__asm__("vide: ret"); +__asm__(_"vide: ret"); int main() { vide();