tidy support for helper function such as memmove

tcc.h, tccgen.c: Introduce Sym *external_helper_sym(int v);
  to create an external reference with no specific type. This
  avoids type conflicts if the symbol is used from C too.
the other files: use it.
This commit is contained in:
grischka 2020-11-23 20:15:16 +01:00
parent 2f78f54924
commit 4a42b0d95e
8 changed files with 59 additions and 58 deletions

View file

@ -785,7 +785,7 @@ static void gcall_or_jmp(int is_jmp)
static void gen_bounds_call(int v) static void gen_bounds_call(int v)
{ {
Sym *sym = external_global_sym(v, &func_old_type); Sym *sym = external_helper_sym(v);
greloc(cur_text_section, sym, ind, R_ARM_PC24); greloc(cur_text_section, sym, ind, R_ARM_PC24);
o(0xebfffffe); o(0xebfffffe);
@ -1717,7 +1717,7 @@ done:
vtop--; vtop--;
break; break;
case 3: case 3:
vpush_global_sym(&func_old_type, func); vpush_helper_func(func);
vrott(3); vrott(3);
gfunc_call(2); gfunc_call(2);
vpushi(0); vpushi(0);
@ -2137,7 +2137,7 @@ ST_FUNC void gen_cvt_itof(int t)
func=TOK___floatdidf; func=TOK___floatdidf;
} }
if(func_type) { if(func_type) {
vpush_global_sym(func_type, func); vpushsym(func_type, external_helper_sym(func));
vswap(); vswap();
gfunc_call(1); gfunc_call(1);
vpushi(0); vpushi(0);
@ -2196,7 +2196,7 @@ void gen_cvt_ftoi(int t)
func=TOK___fixdfdi; func=TOK___fixdfdi;
} }
if(func) { if(func) {
vpush_global_sym(&func_old_type, func); vpush_helper_func(func);
vswap(); vswap();
gfunc_call(1); gfunc_call(1);
vpushi(0); vpushi(0);
@ -2277,7 +2277,7 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) {
vtop->r = TREG_R0; vtop->r = TREG_R0;
o(0xe1a0000d | (vtop->r << 12)); // mov r0,sp o(0xe1a0000d | (vtop->r << 12)); // mov r0,sp
vswap(); vswap();
vpush_global_sym(&func_old_type, TOK___bound_new_region); vpush_helper_func(TOK___bound_new_region);
vrott(3); vrott(3);
gfunc_call(2); gfunc_call(2);
func_bound_add_epilog = 1; func_bound_add_epilog = 1;

View file

@ -662,7 +662,7 @@ static void arm64_gen_bl_or_b(int b)
static void gen_bounds_call(int v) static void gen_bounds_call(int v)
{ {
Sym *sym = external_global_sym(v, &func_old_type); Sym *sym = external_helper_sym(v);
greloca(cur_text_section, sym, ind, R_AARCH64_CALL26, 0); greloca(cur_text_section, sym, ind, R_AARCH64_CALL26, 0);
o(0x94000000); // bl o(0x94000000); // bl
@ -1782,7 +1782,7 @@ ST_FUNC void gen_opf(int op)
case TOK_GT: func = TOK___gttf2; cond = 13; break; case TOK_GT: func = TOK___gttf2; cond = 13; break;
default: assert(0); break; default: assert(0); break;
} }
vpush_global_sym(&func_old_type, func); vpush_helper_func(func);
vrott(3); vrott(3);
gfunc_call(2); gfunc_call(2);
vpushi(0); vpushi(0);
@ -1885,7 +1885,7 @@ ST_FUNC void gen_cvt_itof(int t)
int func = (f & VT_BTYPE) == VT_LLONG ? int func = (f & VT_BTYPE) == VT_LLONG ?
(f & VT_UNSIGNED ? TOK___floatunditf : TOK___floatditf) : (f & VT_UNSIGNED ? TOK___floatunditf : TOK___floatditf) :
(f & VT_UNSIGNED ? TOK___floatunsitf : TOK___floatsitf); (f & VT_UNSIGNED ? TOK___floatunsitf : TOK___floatsitf);
vpush_global_sym(&func_old_type, func); vpush_helper_func(func);
vrott(2); vrott(2);
gfunc_call(1); gfunc_call(1);
vpushi(0); vpushi(0);
@ -1913,7 +1913,7 @@ ST_FUNC void gen_cvt_ftoi(int t)
int func = (t & VT_BTYPE) == VT_LLONG ? int func = (t & VT_BTYPE) == VT_LLONG ?
(t & VT_UNSIGNED ? TOK___fixunstfdi : TOK___fixtfdi) : (t & VT_UNSIGNED ? TOK___fixunstfdi : TOK___fixtfdi) :
(t & VT_UNSIGNED ? TOK___fixunstfsi : TOK___fixtfsi); (t & VT_UNSIGNED ? TOK___fixunstfsi : TOK___fixtfsi);
vpush_global_sym(&func_old_type, func); vpush_helper_func(func);
vrott(2); vrott(2);
gfunc_call(1); gfunc_call(1);
vpushi(0); vpushi(0);
@ -1947,7 +1947,7 @@ ST_FUNC void gen_cvt_ftof(int t)
int func = (t == VT_LDOUBLE) ? int func = (t == VT_LDOUBLE) ?
(f == VT_FLOAT ? TOK___extendsftf2 : TOK___extenddftf2) : (f == VT_FLOAT ? TOK___extendsftf2 : TOK___extenddftf2) :
(t == VT_FLOAT ? TOK___trunctfsf2 : TOK___trunctfdf2); (t == VT_FLOAT ? TOK___trunctfsf2 : TOK___trunctfdf2);
vpush_global_sym(&func_old_type, func); vpush_helper_func(func);
vrott(2); vrott(2);
gfunc_call(1); gfunc_call(1);
vpushi(0); vpushi(0);
@ -2061,7 +2061,7 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) {
vtop->r = TREG_R(0); vtop->r = TREG_R(0);
o(0x910003e0 | vtop->r); // mov r0,sp o(0x910003e0 | vtop->r); // mov r0,sp
vswap(); vswap();
vpush_global_sym(&func_old_type, TOK___bound_new_region); vpush_helper_func(TOK___bound_new_region);
vrott(3); vrott(3);
gfunc_call(2); gfunc_call(2);
func_bound_add_epilog = 1; func_bound_add_epilog = 1;

View file

@ -2254,7 +2254,7 @@ void gen_opi(int op)
call_func: call_func:
vswap(); vswap();
/* call generic idiv function */ /* call generic idiv function */
vpush_global_sym(&func_old_type, t); vpush_helper_func(t);
vrott(3); vrott(3);
gfunc_call(2); gfunc_call(2);
vpushi(0); vpushi(0);
@ -2385,7 +2385,7 @@ void gen_opf(int op)
// must call intrinsic DP floating point divide // must call intrinsic DP floating point divide
vswap(); vswap();
/* call generic idiv function */ /* call generic idiv function */
vpush_global_sym(&func_old_type, TOK__divd); vpush_helper_func(TOK__divd);
vrott(3); vrott(3);
gfunc_call(2); gfunc_call(2);
vpushi(0); vpushi(0);
@ -2396,7 +2396,7 @@ void gen_opf(int op)
// must call intrinsic SP floating point divide // must call intrinsic SP floating point divide
vswap(); vswap();
/* call generic idiv function */ /* call generic idiv function */
vpush_global_sym(&func_old_type, TOK__divf); vpush_helper_func(TOK__divf);
vrott(3); vrott(3);
gfunc_call(2); gfunc_call(2);
vpushi(0); vpushi(0);

View file

@ -345,7 +345,7 @@ static void gen_static_call(int v)
{ {
Sym *sym; Sym *sym;
sym = external_global_sym(v, &func_old_type); sym = external_helper_sym(v);
oad(0xe8, -4); oad(0xe8, -4);
greloc(cur_text_section, sym, ind-4, R_386_PC32); greloc(cur_text_section, sym, ind-4, R_386_PC32);
} }
@ -985,11 +985,11 @@ ST_FUNC void gen_cvt_ftoi(int t)
{ {
int bt = vtop->type.t & VT_BTYPE; int bt = vtop->type.t & VT_BTYPE;
if (bt == VT_FLOAT) if (bt == VT_FLOAT)
vpush_global_sym(&func_old_type, TOK___fixsfdi); vpush_helper_func(TOK___fixsfdi);
else if (bt == VT_LDOUBLE) else if (bt == VT_LDOUBLE)
vpush_global_sym(&func_old_type, TOK___fixxfdi); vpush_helper_func(TOK___fixxfdi);
else else
vpush_global_sym(&func_old_type, TOK___fixdfdi); vpush_helper_func(TOK___fixdfdi);
vswap(); vswap();
gfunc_call(1); gfunc_call(1);
vpushi(0); vpushi(0);
@ -1099,7 +1099,7 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) {
#endif #endif
if (use_call) if (use_call)
{ {
vpush_global_sym(&func_old_type, TOK_alloca); vpush_helper_func(TOK_alloca);
vswap(); /* Move alloca ref past allocation size */ vswap(); /* Move alloca ref past allocation size */
gfunc_call(1); gfunc_call(1);
} }

View file

@ -402,7 +402,7 @@ static void gcall_or_jmp(int docall)
static void gen_bounds_call(int v) static void gen_bounds_call(int v)
{ {
Sym *sym = external_global_sym(v, &func_old_type); Sym *sym = external_helper_sym(v);
greloca(cur_text_section, sym, ind, R_RISCV_CALL_PLT, 0); greloca(cur_text_section, sym, ind, R_RISCV_CALL_PLT, 0);
o(0x17 | (1 << 7)); // auipc TR, 0 %call(func) o(0x17 | (1 << 7)); // auipc TR, 0 %call(func)
@ -1125,7 +1125,7 @@ ST_FUNC void gen_opf(int op)
case TOK_GT: func = TOK___gttf2; cond = 13; break; case TOK_GT: func = TOK___gttf2; cond = 13; break;
default: assert(0); break; default: assert(0); break;
} }
vpush_global_sym(&func_old_type, func); vpush_helper_func(func);
vrott(3); vrott(3);
gfunc_call(2); gfunc_call(2);
vpushi(0); vpushi(0);
@ -1213,7 +1213,7 @@ ST_FUNC void gen_cvt_itof(int t)
int func = l ? int func = l ?
(u ? TOK___floatunditf : TOK___floatditf) : (u ? TOK___floatunditf : TOK___floatditf) :
(u ? TOK___floatunsitf : TOK___floatsitf); (u ? TOK___floatunsitf : TOK___floatsitf);
vpush_global_sym(&func_old_type, func); vpush_helper_func(func);
vrott(2); vrott(2);
gfunc_call(1); gfunc_call(1);
vpushi(0); vpushi(0);
@ -1239,7 +1239,7 @@ ST_FUNC void gen_cvt_ftoi(int t)
int func = l ? int func = l ?
(u ? TOK___fixunstfdi : TOK___fixtfdi) : (u ? TOK___fixunstfdi : TOK___fixtfdi) :
(u ? TOK___fixunstfsi : TOK___fixtfsi); (u ? TOK___fixunstfsi : TOK___fixtfsi);
vpush_global_sym(&func_old_type, func); vpush_helper_func(func);
vrott(2); vrott(2);
gfunc_call(1); gfunc_call(1);
vpushi(0); vpushi(0);
@ -1281,7 +1281,7 @@ ST_FUNC void gen_cvt_ftof(int dt)
vtop->r2 = 1 + vtop->r; vtop->r2 = 1 + vtop->r;
} }
} }
vpush_global_sym(&func_old_type, func); vpush_helper_func(func);
gcall_or_jmp(1); gcall_or_jmp(1);
vtop -= 2; vtop -= 2;
vpushi(0); vpushi(0);
@ -1342,7 +1342,7 @@ ST_FUNC void gen_vla_alloc(CType *type, int align)
vtop->r = TREG_R(0); vtop->r = TREG_R(0);
o(0x00010513); /* mv a0,sp */ o(0x00010513); /* mv a0,sp */
vswap(); vswap();
vpush_global_sym(&func_old_type, TOK___bound_new_region); vpush_helper_func(TOK___bound_new_region);
vrott(3); vrott(3);
gfunc_call(2); gfunc_call(2);
func_bound_add_epilog = 1; func_bound_add_epilog = 1;

3
tcc.h
View file

@ -1437,10 +1437,11 @@ ST_FUNC void vpushi(int v);
ST_FUNC ElfSym *elfsym(Sym *); ST_FUNC ElfSym *elfsym(Sym *);
ST_FUNC void update_storage(Sym *sym); ST_FUNC void update_storage(Sym *sym);
ST_FUNC Sym *external_global_sym(int v, CType *type); ST_FUNC Sym *external_global_sym(int v, CType *type);
ST_FUNC Sym *external_helper_sym(int v);
ST_FUNC void vpush_helper_func(int v);
ST_FUNC void vset(CType *type, int r, int v); ST_FUNC void vset(CType *type, int r, int v);
ST_FUNC void vset_VT_CMP(int op); ST_FUNC void vset_VT_CMP(int op);
ST_FUNC void vswap(void); ST_FUNC void vswap(void);
ST_FUNC void vpush_global_sym(CType *type, int v);
ST_FUNC void vrote(SValue *e, int n); ST_FUNC void vrote(SValue *e, int n);
ST_FUNC void vrott(int n); ST_FUNC void vrott(int n);
ST_FUNC void vrotb(int n); ST_FUNC void vrotb(int n);

View file

@ -80,7 +80,7 @@ ST_DATA int func_var; /* true if current function is variadic (used by return in
ST_DATA int func_vc; ST_DATA int func_vc;
static int last_line_num, new_file, func_ind; /* debug info control */ static int last_line_num, new_file, func_ind; /* debug info control */
ST_DATA const char *funcname; ST_DATA const char *funcname;
ST_DATA CType int_type, func_old_type, char_type, char_pointer_type, func_mem_move, void_type, void_ptr_type; ST_DATA CType int_type, func_old_type, char_type, char_pointer_type;
static CString initstr; static CString initstr;
#if PTR_SIZE == 4 #if PTR_SIZE == 4
@ -800,14 +800,6 @@ ST_FUNC void tccgen_init(TCCState *s1)
char_pointer_type = char_type; char_pointer_type = char_type;
mk_pointer(&char_pointer_type); mk_pointer(&char_pointer_type);
void_type.t = VT_VOID;
void_ptr_type = void_type;
mk_pointer(&void_ptr_type);
func_mem_move.t = VT_FUNC;
func_mem_move.ref = sym_push(SYM_FIELD, &void_ptr_type, 0, 0);
func_mem_move.ref->f.func_call = FUNC_CDECL;
func_mem_move.ref->f.func_type = FUNC_OLD;
func_old_type.t = VT_FUNC; func_old_type.t = VT_FUNC;
func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0); func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0);
func_old_type.ref->f.func_call = FUNC_CDECL; func_old_type.ref->f.func_call = FUNC_CDECL;
@ -1493,6 +1485,20 @@ ST_FUNC Sym *external_global_sym(int v, CType *type)
return s; return s;
} }
/* create an external reference with no specific type similar to asm labels.
This avoids type conflicts if the symbol is used from C too */
ST_FUNC Sym *external_helper_sym(int v)
{
CType ct = { VT_ASM, NULL };
return external_global_sym(v, &ct);
}
/* push a reference to an helper function (such as memmove) */
ST_FUNC void vpush_helper_func(int v)
{
vpushsym(&func_old_type, external_helper_sym(v));
}
/* Merge symbol attributes. */ /* Merge symbol attributes. */
static void merge_symattr(struct SymAttr *sa, struct SymAttr *sa1) static void merge_symattr(struct SymAttr *sa, struct SymAttr *sa1)
{ {
@ -1681,12 +1687,6 @@ static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad)
return s; return s;
} }
/* push a reference to global symbol v */
ST_FUNC void vpush_global_sym(CType *type, int v)
{
vpushsym(type, external_global_sym(v, type));
}
/* save registers up to (vtop - n) stack entry */ /* save registers up to (vtop - n) stack entry */
ST_FUNC void save_regs(int n) ST_FUNC void save_regs(int n)
{ {
@ -1904,7 +1904,7 @@ static void gen_bounded_ptr_add(void)
vpushv(&vtop[-1]); vpushv(&vtop[-1]);
vrott(3); vrott(3);
} }
vpush_global_sym(&func_old_type, TOK___bound_ptr_add); vpush_helper_func(TOK___bound_ptr_add);
vrott(3); vrott(3);
gfunc_call(2); gfunc_call(2);
vtop -= save; vtop -= save;
@ -1941,7 +1941,7 @@ static void gen_bounded_ptr_deref(void)
/* may happen with struct member access */ /* may happen with struct member access */
return; return;
} }
sym = external_global_sym(func, &func_old_type); sym = external_helper_sym(func);
if (!sym->c) if (!sym->c)
put_extern_sym(sym, NULL, 0, 0); put_extern_sym(sym, NULL, 0, 0);
/* patch relocation */ /* patch relocation */
@ -1998,7 +1998,7 @@ ST_FUNC void gbound_args(int nb_args)
|| v == TOK___sigsetjmp || v == TOK___sigsetjmp
#endif #endif
) { ) {
vpush_global_sym(&func_old_type, TOK___bound_setjmp); vpush_helper_func(TOK___bound_setjmp);
vpushv(sv + 1); vpushv(sv + 1);
gfunc_call(1); gfunc_call(1);
func_bound_add_epilog = 1; func_bound_add_epilog = 1;
@ -2415,7 +2415,7 @@ static void gen_opl(int op)
#endif #endif
gen_func: gen_func:
/* call generic long long function */ /* call generic long long function */
vpush_global_sym(&func_old_type, func); vpush_helper_func(func);
vrott(3); vrott(3);
gfunc_call(2); gfunc_call(2);
vpushi(0); vpushi(0);
@ -3379,13 +3379,13 @@ static void gen_cvt_itof1(int t)
(VT_LLONG | VT_UNSIGNED)) { (VT_LLONG | VT_UNSIGNED)) {
if (t == VT_FLOAT) if (t == VT_FLOAT)
vpush_global_sym(&func_old_type, TOK___floatundisf); vpush_helper_func(TOK___floatundisf);
#if LDOUBLE_SIZE != 8 #if LDOUBLE_SIZE != 8
else if (t == VT_LDOUBLE) else if (t == VT_LDOUBLE)
vpush_global_sym(&func_old_type, TOK___floatundixf); vpush_helper_func(TOK___floatundixf);
#endif #endif
else else
vpush_global_sym(&func_old_type, TOK___floatundidf); vpush_helper_func(TOK___floatundidf);
vrott(2); vrott(2);
gfunc_call(1); gfunc_call(1);
vpushi(0); vpushi(0);
@ -3407,13 +3407,13 @@ static void gen_cvt_ftoi1(int t)
/* not handled natively */ /* not handled natively */
st = vtop->type.t & VT_BTYPE; st = vtop->type.t & VT_BTYPE;
if (st == VT_FLOAT) if (st == VT_FLOAT)
vpush_global_sym(&func_old_type, TOK___fixunssfdi); vpush_helper_func(TOK___fixunssfdi);
#if LDOUBLE_SIZE != 8 #if LDOUBLE_SIZE != 8
else if (st == VT_LDOUBLE) else if (st == VT_LDOUBLE)
vpush_global_sym(&func_old_type, TOK___fixunsxfdi); vpush_helper_func(TOK___fixunsxfdi);
#endif #endif
else else
vpush_global_sym(&func_old_type, TOK___fixunsdfdi); vpush_helper_func(TOK___fixunsdfdi);
vrott(2); vrott(2);
gfunc_call(1); gfunc_call(1);
vpushi(0); vpushi(0);
@ -3904,13 +3904,13 @@ ST_FUNC void vstore(void)
/* address of memcpy() */ /* address of memcpy() */
#ifdef TCC_ARM_EABI #ifdef TCC_ARM_EABI
if(!(align & 7)) if(!(align & 7))
vpush_global_sym(&func_old_type, TOK_memmove8); vpush_helper_func(TOK_memmove8);
else if(!(align & 3)) else if(!(align & 3))
vpush_global_sym(&func_old_type, TOK_memmove4); vpush_helper_func(TOK_memmove4);
else else
#endif #endif
/* Use memmove, rather than memcpy, as dest and src may be same: */ /* Use memmove, rather than memcpy, as dest and src may be same: */
vpush_global_sym(&func_mem_move, TOK_memmove); vpush_helper_func(TOK_memmove);
vswap(); vswap();
/* source */ /* source */
@ -7363,7 +7363,7 @@ static void init_putz(init_params *p, unsigned long c, int size)
if (p->sec) { if (p->sec) {
/* nothing to do because globals are already set to zero */ /* nothing to do because globals are already set to zero */
} else { } else {
vpush_global_sym(&func_old_type, TOK_memset); vpush_helper_func(TOK_memset);
vseti(VT_LOCAL, c); vseti(VT_LOCAL, c);
#ifdef TCC_TARGET_ARM #ifdef TCC_TARGET_ARM
vpushs(size); vpushs(size);

View file

@ -653,7 +653,7 @@ static void gcall_or_jmp(int is_jmp)
static void gen_bounds_call(int v) static void gen_bounds_call(int v)
{ {
Sym *sym = external_global_sym(v, &func_old_type); Sym *sym = external_helper_sym(v);
oad(0xe8, 0); oad(0xe8, 0);
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4); greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4);
@ -1022,7 +1022,7 @@ void gfunc_epilog(void)
v = -loc; v = -loc;
if (v >= 4096) { if (v >= 4096) {
Sym *sym = external_global_sym(TOK___chkstk, &func_old_type); Sym *sym = external_helper_sym(TOK___chkstk);
oad(0xb8, v); /* mov stacksize, %eax */ oad(0xb8, v); /* mov stacksize, %eax */
oad(0xe8, 0); /* call __chkstk, (does the stackframe too) */ oad(0xe8, 0); /* call __chkstk, (does the stackframe too) */
greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4); greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4);
@ -2209,7 +2209,7 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) {
#endif #endif
if (use_call) if (use_call)
{ {
vpush_global_sym(&func_old_type, TOK_alloca); vpush_helper_func(TOK_alloca);
vswap(); /* Move alloca ref past allocation size */ vswap(); /* Move alloca ref past allocation size */
gfunc_call(1); gfunc_call(1);
} }