macos: Fix asm-c-connect-test

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.
This commit is contained in:
Michael Matz 2020-05-23 03:46:32 +02:00
parent 3cf7bec12f
commit fbfe6209be
8 changed files with 69 additions and 9 deletions

View file

@ -1490,6 +1490,8 @@ ST_FUNC void subst_asm_operand(CString *add_str,
list when we still know the symbol. */ list when we still know the symbol. */
get_asm_sym(tok_alloc(name, strlen(name))->tok, sv->sym); 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); cstr_cat(add_str, name, -1);
if ((uint32_t)sv->c.i == 0) if ((uint32_t)sv->c.i == 0)
goto no_offset; goto no_offset;

View file

@ -4,6 +4,7 @@
#ifdef __APPLE__ #ifdef __APPLE__
#define __bound_alloca ___bound_alloca #define __bound_alloca ___bound_alloca
#define __bound_alloca_nr ___bound_alloca_nr #define __bound_alloca_nr ___bound_alloca_nr
#define __bound_new_region ___bound_new_region
#endif #endif
.globl __bound_alloca .globl __bound_alloca

View file

@ -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_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); 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) 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)) while (sym && sym->sym_scope && !(sym->type.t & VT_STATIC))
sym = sym->prev_tok; sym = sym->prev_tok;
return sym; return sym;
@ -48,10 +78,14 @@ static Sym *asm_label_find(int v)
static Sym *asm_label_push(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 /* We always add VT_EXTERN, for sym definition that's tentative
(for .set, removed for real defs), for mere references it's correct (for .set, removed for real defs), for mere references it's correct
as is. */ 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. /* 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); sym = asm_label_push(label);
} }
if (!sym->c) 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 = elfsym(sym);
esym->st_shndx = sh_num; esym->st_shndx = sh_num;
esym->st_value = value; esym->st_value = value;

View file

@ -46,7 +46,7 @@ ifeq ($(ARCH),riscv64)
endif endif
endif endif
ifdef CONFIG_OSX # some don't work yet 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 endif
ifeq (,$(filter arm64 i386 x86_64,$(ARCH))) ifeq (,$(filter arm64 i386 x86_64,$(ARCH)))
TESTS := $(filter-out vla_test-run,$(TESTS)) TESTS := $(filter-out vla_test-run,$(TESTS))

View file

@ -2,11 +2,20 @@
#if defined _WIN32 && !defined __TINYC__ #if defined _WIN32 && !defined __TINYC__
# define _ "_" # define _ "_"
#elif defined __APPLE__
# define _ "_"
#else #else
# define _ # define _
#endif #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"); printf(" x1");
return 1; return 1;
@ -37,7 +46,7 @@ int main(int argc, char *argv[])
} }
static static
int x2(void) int __USED x2(void)
{ {
printf(" x2"); printf(" x2");
return 2; return 2;

View file

@ -2,10 +2,19 @@
#if defined _WIN32 && !defined __TINYC__ #if defined _WIN32 && !defined __TINYC__
# define _ "_" # define _ "_"
#elif defined __APPLE__
# define _ "_"
#else #else
# define _ # define _
#endif #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) int x3(void)
{ {
printf(" x3"); printf(" x3");
@ -30,7 +39,7 @@ void callx5_again(void)
asm("call "_"x6"); asm("call "_"x6");
} }
static void x6() static void __USED x6()
{ {
printf(" x6-2"); printf(" x6-2");
} }

View file

@ -3650,7 +3650,7 @@ void test_asm_call(void)
asm volatile ("push %%rdi; push %%rdi; mov %0, %%rdi;" asm volatile ("push %%rdi; push %%rdi; mov %0, %%rdi;"
#if 1 && !defined(__TINYC__) && (defined(__PIC__) || defined(__PIE__)) && !defined(__APPLE__) #if 1 && !defined(__TINYC__) && (defined(__PIC__) || defined(__PIE__)) && !defined(__APPLE__)
"call getenv@plt;" "call getenv@plt;"
#elif defined(__APPLE__) && !defined(__TINYC__) #elif defined(__APPLE__)
"call _getenv;" "call _getenv;"
#else #else
"call getenv;" "call getenv;"

View file

@ -1,6 +1,11 @@
#ifdef __APPLE__
#define _ "_"
#else
#define _
#endif
extern int printf (const char *, ...); extern int printf (const char *, ...);
extern void vide(void); extern void vide(void);
__asm__("vide: ret"); __asm__(_"vide: ret");
int main() { int main() {
vide(); vide();