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:
parent
3cf7bec12f
commit
fbfe6209be
8 changed files with 69 additions and 9 deletions
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
40
tccasm.c
40
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_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;
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;"
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Add table
Reference in a new issue