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. */
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;

View File

@ -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

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_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;

View File

@ -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))

View File

@ -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;

View File

@ -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");
}

View File

@ -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;"

View File

@ -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();