mirror of
https://github.com/TinyCC/tinycc.git
synced 2025-11-16 04:24:45 +00:00
revert "Save registers around attribute cleanup" (almost)
In fact, we don't need to save registers. We need to
save the symbol if it is a SValue on vstack (the return
value in this case)
Replaces b6a16e3be4
This commit is contained in:
43
arm-gen.c
43
arm-gen.c
@@ -837,32 +837,6 @@ static void gcall_or_jmp(int is_jmp)
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC void save_return_reg(CType *func_type)
|
||||
{
|
||||
int freg = is_float(func_type->t & VT_BTYPE);
|
||||
int ireg = !freg;
|
||||
|
||||
if ((func_type->t & VT_BTYPE) == VT_STRUCT)
|
||||
ireg = freg = 1;
|
||||
if (ireg)
|
||||
o(0xe92d0003); /* push {r0,r1} */
|
||||
if (freg)
|
||||
o(0xed2d0b04); /* vpush {d0,d1} */
|
||||
}
|
||||
|
||||
ST_FUNC void restore_return_reg(CType *func_type)
|
||||
{
|
||||
int freg = is_float(func_type->t & VT_BTYPE);
|
||||
int ireg = !freg;
|
||||
|
||||
if ((func_type->t & VT_BTYPE) == VT_STRUCT)
|
||||
ireg = freg = 1;
|
||||
if (freg)
|
||||
o(0xecbd0b04); /* vpop {d0,d1} */
|
||||
if (ireg)
|
||||
o(0xe8bd0003); /* pop {r0,r1} */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
|
||||
static void gen_bounds_call(int v)
|
||||
@@ -886,13 +860,12 @@ static void gen_bounds_prolog(void)
|
||||
o(0xe1a00000); /* call __bound_local_new */
|
||||
}
|
||||
|
||||
static void gen_bounds_epilog(Sym *func_sym)
|
||||
static void gen_bounds_epilog(void)
|
||||
{
|
||||
addr_t saved_ind;
|
||||
addr_t *bounds_ptr;
|
||||
Sym *sym_data;
|
||||
int offset_modified = func_bound_offset != lbounds_section->data_offset;
|
||||
CType *func_type = &func_sym->type.ref->type;
|
||||
|
||||
if (!offset_modified && !func_bound_add_epilog)
|
||||
return;
|
||||
@@ -918,16 +891,16 @@ static void gen_bounds_epilog(Sym *func_sym)
|
||||
}
|
||||
|
||||
/* generate bound check local freeing */
|
||||
if (func_type->t != VT_VOID)
|
||||
save_return_reg(func_type);
|
||||
o(0xe92d0003); /* push {r0,r1} */
|
||||
o(0xed2d0b04); /* vpush {d0,d1} */
|
||||
o(0xe59f0000); /* ldr r0, [pc] */
|
||||
o(0xea000000); /* b $+4 */
|
||||
greloc(cur_text_section, sym_data, ind, R_ARM_REL32);
|
||||
o(-12); /* lbounds_section->data_offset */
|
||||
o(0xe080000f); /* add r0,r0,pc */
|
||||
gen_bounds_call(TOK___bound_local_delete);
|
||||
if (func_type->t != VT_VOID)
|
||||
restore_return_reg(func_type);
|
||||
o(0xecbd0b04); /* vpop {d0,d1} */
|
||||
o(0xe8bd0003); /* pop {r0,r1} */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1535,17 +1508,15 @@ from_stack:
|
||||
}
|
||||
|
||||
/* generate function epilog */
|
||||
void gfunc_epilog(Sym *func_sym)
|
||||
void gfunc_epilog(void)
|
||||
{
|
||||
uint32_t x;
|
||||
int diff;
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check)
|
||||
gen_bounds_epilog(func_sym);
|
||||
gen_bounds_epilog();
|
||||
#endif
|
||||
func_sym = NULL;
|
||||
|
||||
/* Copy float return value to core register if base standard is used and
|
||||
float computation is made with VFP */
|
||||
#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
|
||||
|
||||
42
arm64-gen.c
42
arm64-gen.c
@@ -674,32 +674,6 @@ static void arm64_gen_bl_or_b(int b)
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC void save_return_reg(CType *func_type)
|
||||
{
|
||||
int freg = is_float(func_type->t & VT_BTYPE);
|
||||
int ireg = !freg;
|
||||
|
||||
if ((func_type->t & VT_BTYPE) == VT_STRUCT)
|
||||
ireg = freg = 1;
|
||||
if (ireg)
|
||||
o(0xa9bf07e0); /* stp x0, x1, [sp, #-16]! */
|
||||
if (freg)
|
||||
o(0xadbf07e0); /* stp q0, q1, [sp, #-32]! */
|
||||
}
|
||||
|
||||
ST_FUNC void restore_return_reg(CType *func_type)
|
||||
{
|
||||
int freg = is_float(func_type->t & VT_BTYPE);
|
||||
int ireg = !freg;
|
||||
|
||||
if ((func_type->t & VT_BTYPE) == VT_STRUCT)
|
||||
ireg = freg = 1;
|
||||
if (freg)
|
||||
o(0xacc107e0); /* ldp q0, q1, [sp], #32 */
|
||||
if (ireg)
|
||||
o(0xa8c107e0); /* ldp x0, x1, [sp], #16 */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
|
||||
static void gen_bounds_call(int v)
|
||||
@@ -722,13 +696,12 @@ static void gen_bounds_prolog(void)
|
||||
o(0xd503201f); /* nop -> call __bound_local_new */
|
||||
}
|
||||
|
||||
static void gen_bounds_epilog(Sym *func_sym)
|
||||
static void gen_bounds_epilog(void)
|
||||
{
|
||||
addr_t saved_ind;
|
||||
addr_t *bounds_ptr;
|
||||
Sym *sym_data;
|
||||
int offset_modified = func_bound_offset != lbounds_section->data_offset;
|
||||
CType *func_type = &func_sym->type.ref->type;
|
||||
|
||||
if (!offset_modified && !func_bound_add_epilog)
|
||||
return;
|
||||
@@ -753,15 +726,15 @@ static void gen_bounds_epilog(Sym *func_sym)
|
||||
}
|
||||
|
||||
/* generate bound check local freeing */
|
||||
if (func_type->t != VT_VOID)
|
||||
save_return_reg(func_type);
|
||||
o(0xa9bf07e0); /* stp x0, x1, [sp, #-16]! */
|
||||
o(0x3c9f0fe0); /* str q0, [sp, #-16]! */
|
||||
greloca(cur_text_section, sym_data, ind, R_AARCH64_ADR_GOT_PAGE, 0);
|
||||
o(0x90000000 | 0); // adrp x0, #sym_data
|
||||
greloca(cur_text_section, sym_data, ind, R_AARCH64_LD64_GOT_LO12_NC, 0);
|
||||
o(0xf9400000 | 0 | (0 << 5)); // ld x0,[x0, #sym_data]
|
||||
gen_bounds_call(TOK___bound_local_delete);
|
||||
if (func_type->t != VT_VOID)
|
||||
restore_return_reg(func_type);
|
||||
o(0x3cc107e0); /* ldr q0, [sp], #16 */
|
||||
o(0xa8c107e0); /* ldp x0, x1, [sp], #16 */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1486,13 +1459,12 @@ ST_FUNC void gfunc_return(CType *func_type)
|
||||
vtop--;
|
||||
}
|
||||
|
||||
ST_FUNC void gfunc_epilog(Sym *func_sym)
|
||||
ST_FUNC void gfunc_epilog(void)
|
||||
{
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check)
|
||||
gen_bounds_epilog(func_sym);
|
||||
gen_bounds_epilog();
|
||||
#endif
|
||||
func_sym = NULL;
|
||||
|
||||
if (loc) {
|
||||
// Insert instructions to subtract size of stack frame from SP.
|
||||
|
||||
15
c67-gen.c
15
c67-gen.c
@@ -2019,22 +2019,9 @@ void gfunc_prolog(Sym *func_sym)
|
||||
C67_PUSH(C67_B3);
|
||||
}
|
||||
|
||||
ST_FUNC void save_return_reg(CType *func_type)
|
||||
{
|
||||
func_type = NULL;
|
||||
// TODO
|
||||
}
|
||||
|
||||
ST_FUNC void restore_return_reg(CType *func_type)
|
||||
{
|
||||
func_type = NULL;
|
||||
// TODO
|
||||
}
|
||||
|
||||
/* generate function epilog */
|
||||
void gfunc_epilog(Sym *func_sym)
|
||||
void gfunc_epilog(void)
|
||||
{
|
||||
func_sym = NULL;
|
||||
{
|
||||
int local = (-loc + 7) & -8; // stack must stay aligned to 8 bytes for LDDW instr
|
||||
C67_POP(C67_B3);
|
||||
|
||||
32
i386-gen.c
32
i386-gen.c
@@ -104,7 +104,7 @@ static addr_t func_bound_offset;
|
||||
static unsigned long func_bound_ind;
|
||||
ST_DATA int func_bound_add_epilog;
|
||||
static void gen_bounds_prolog(void);
|
||||
static void gen_bounds_epilog(Sym *func_sym);
|
||||
static void gen_bounds_epilog(void);
|
||||
#endif
|
||||
|
||||
/* XXX: make it faster ? */
|
||||
@@ -595,15 +595,14 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
}
|
||||
|
||||
/* generate function epilog */
|
||||
ST_FUNC void gfunc_epilog(Sym *func_sym)
|
||||
ST_FUNC void gfunc_epilog(void)
|
||||
{
|
||||
addr_t v, saved_ind;
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check)
|
||||
gen_bounds_epilog(func_sym);
|
||||
gen_bounds_epilog();
|
||||
#endif
|
||||
func_sym = NULL;
|
||||
|
||||
/* align local size to word & save local variables */
|
||||
v = (-loc + 3) & -4;
|
||||
@@ -1041,22 +1040,6 @@ ST_FUNC void ggoto(void)
|
||||
vtop--;
|
||||
}
|
||||
|
||||
ST_FUNC void save_return_reg(CType *func_type)
|
||||
{
|
||||
int ireg = !is_float(func_type->t & VT_BTYPE);
|
||||
|
||||
if (ireg)
|
||||
o(0x5250); /* push %rax; %push %rdx */
|
||||
}
|
||||
|
||||
ST_FUNC void restore_return_reg(CType *func_type)
|
||||
{
|
||||
int ireg = !is_float(func_type->t & VT_BTYPE);
|
||||
|
||||
if (ireg)
|
||||
o(0x585a); /* pop %rdx; pop %rax */
|
||||
}
|
||||
|
||||
/* bound check support functions */
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
|
||||
@@ -1070,13 +1053,12 @@ static void gen_bounds_prolog(void)
|
||||
oad(0xb8, 0); /* call to function */
|
||||
}
|
||||
|
||||
static void gen_bounds_epilog(Sym *func_sym)
|
||||
static void gen_bounds_epilog(void)
|
||||
{
|
||||
addr_t saved_ind;
|
||||
addr_t *bounds_ptr;
|
||||
Sym *sym_data;
|
||||
int offset_modified = func_bound_offset != lbounds_section->data_offset;
|
||||
CType *func_type = &func_sym->type.ref->type;
|
||||
|
||||
if (!offset_modified && !func_bound_add_epilog)
|
||||
return;
|
||||
@@ -1099,13 +1081,11 @@ static void gen_bounds_epilog(Sym *func_sym)
|
||||
}
|
||||
|
||||
/* generate bound check local freeing */
|
||||
if (func_type->t != VT_VOID)
|
||||
save_return_reg(func_type);
|
||||
o(0x5250); /* save returned value, if any */
|
||||
greloc(cur_text_section, sym_data, ind + 1, R_386_32);
|
||||
oad(0xb8, 0); /* mov %eax, xxx */
|
||||
gen_static_call(TOK___bound_local_delete);
|
||||
if (func_type->t != VT_VOID)
|
||||
restore_return_reg(func_type);
|
||||
o(0x585a); /* restore returned value, if any */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
13
il-gen.c
13
il-gen.c
@@ -457,20 +457,9 @@ void gfunc_prolog(int t)
|
||||
}
|
||||
}
|
||||
|
||||
void save_return_reg(CType *func_type)
|
||||
{
|
||||
func_type = NULL;
|
||||
}
|
||||
|
||||
void restore_return_reg(CType *func_type)
|
||||
{
|
||||
func_type = NULL;
|
||||
}
|
||||
|
||||
/* generate function epilog */
|
||||
void gfunc_epilog(Sym *func_sym)
|
||||
void gfunc_epilog(void)
|
||||
{
|
||||
func_sym = NULL;
|
||||
out_op(IL_OP_RET);
|
||||
fprintf(il_outfile, "}\n\n");
|
||||
}
|
||||
|
||||
@@ -436,46 +436,6 @@ static void gcall_or_jmp(int docall)
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC void save_return_reg(CType *func_type)
|
||||
{
|
||||
int freg = is_float(func_type->t & VT_BTYPE) &&
|
||||
(func_type->t & VT_BTYPE) != VT_LDOUBLE;
|
||||
int ireg = !freg;
|
||||
|
||||
if ((func_type->t & VT_BTYPE) == VT_STRUCT)
|
||||
ireg = freg = 1;
|
||||
if (ireg && freg) {
|
||||
o(0xe02a1101); /* addi sp,sp,-32 sd a0,0(sp) */
|
||||
o(0xa82ae42e); /* sd a1,8(sp) fsd fa0,16(sp) */
|
||||
}
|
||||
else if (ireg) {
|
||||
o(0xe02a1141); /* addi sp,sp,-16 sd a0,0(sp) */
|
||||
o(0x0001e42e); /* sd a1,8(sp) nop */
|
||||
}
|
||||
else if (freg)
|
||||
o(0xa02a1141); /* addi sp,sp,-16 fsd fa0,0(sp) */
|
||||
}
|
||||
|
||||
ST_FUNC void restore_return_reg(CType *func_type)
|
||||
{
|
||||
int freg = is_float(func_type->t & VT_BTYPE) &&
|
||||
(func_type->t & VT_BTYPE) != VT_LDOUBLE;
|
||||
int ireg = !freg;
|
||||
|
||||
if ((func_type->t & VT_BTYPE) == VT_STRUCT)
|
||||
ireg = freg = 1;
|
||||
if (ireg && freg) {
|
||||
o(0x65a26502); /* ld a0,0(sp) ld a1,8(sp) */
|
||||
o(0x61052542); /* fld fa0,16(sp) addi sp,sp,32 */
|
||||
}
|
||||
else if (ireg) {
|
||||
o(0x65a26502); /* ld a0,0(sp) ld a1,8(sp) */
|
||||
o(0x00010141); /* addi sp,sp,16 nop */
|
||||
}
|
||||
else if (freg)
|
||||
o(0x01412502); /* fld fa0,0(sp) addi sp,sp,16 */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
|
||||
static void gen_bounds_call(int v)
|
||||
@@ -499,14 +459,14 @@ static void gen_bounds_prolog(void)
|
||||
o(0x00000013);
|
||||
}
|
||||
|
||||
static void gen_bounds_epilog(Sym *func_sym)
|
||||
static void gen_bounds_epilog(void)
|
||||
{
|
||||
addr_t saved_ind;
|
||||
addr_t *bounds_ptr;
|
||||
Sym *sym_data;
|
||||
Sym label = {0};
|
||||
|
||||
int offset_modified = func_bound_offset != lbounds_section->data_offset;
|
||||
CType *func_type = &func_sym->type.ref->type;
|
||||
|
||||
if (!offset_modified && !func_bound_add_epilog)
|
||||
return;
|
||||
@@ -534,16 +494,16 @@ static void gen_bounds_epilog(Sym *func_sym)
|
||||
}
|
||||
|
||||
/* generate bound check local freeing */
|
||||
if (func_type->t != VT_VOID)
|
||||
save_return_reg(func_type);
|
||||
o(0xe02a1101); /* addi sp,sp,-32 sd a0,0(sp) */
|
||||
o(0xa82ae42e); /* sd a1,8(sp) fsd fa0,16(sp) */
|
||||
put_extern_sym(&label, cur_text_section, ind, 0);
|
||||
greloca(cur_text_section, sym_data, ind, R_RISCV_GOT_HI20, 0);
|
||||
o(0x17 | (10 << 7)); // auipc a0, 0 %pcrel_hi(sym)+addend
|
||||
greloca(cur_text_section, &label, ind, R_RISCV_PCREL_LO12_I, 0);
|
||||
EI(0x03, 3, 10, 10, 0); // ld a0, 0(a0)
|
||||
gen_bounds_call(TOK___bound_local_delete);
|
||||
if (func_type->t != VT_VOID)
|
||||
restore_return_reg(func_type);
|
||||
o(0x65a26502); /* ld a0,0(sp) ld a1,8(sp) */
|
||||
o(0x61052542); /* fld fa0,16(sp) addi sp,sp,32 */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -933,15 +893,14 @@ ST_FUNC void arch_transfer_ret_regs(int aftercall)
|
||||
vtop--;
|
||||
}
|
||||
|
||||
ST_FUNC void gfunc_epilog(Sym *func_sym)
|
||||
ST_FUNC void gfunc_epilog(void)
|
||||
{
|
||||
int v, saved_ind, d, large_ofs_ind;
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check)
|
||||
gen_bounds_epilog(func_sym);
|
||||
gen_bounds_epilog();
|
||||
#endif
|
||||
func_sym = NULL;
|
||||
|
||||
loc = (loc - num_va_regs * 8);
|
||||
d = v = (-loc + 15) & -16;
|
||||
|
||||
4
tcc.h
4
tcc.h
@@ -1607,9 +1607,7 @@ ST_FUNC void store(int r, SValue *v);
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize);
|
||||
ST_FUNC void gfunc_call(int nb_args);
|
||||
ST_FUNC void gfunc_prolog(Sym *func_sym);
|
||||
ST_FUNC void gfunc_epilog(Sym *func_sym);
|
||||
ST_FUNC void save_return_reg(CType *func_type);
|
||||
ST_FUNC void restore_return_reg(CType *func_type);
|
||||
ST_FUNC void gfunc_epilog(void);
|
||||
ST_FUNC void gen_fill_nops(int);
|
||||
ST_FUNC int gjmp(int t);
|
||||
ST_FUNC void gjmp_addr(int a);
|
||||
|
||||
46
tccgen.c
46
tccgen.c
@@ -6839,18 +6839,28 @@ static void end_switch(void)
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* __attribute__((cleanup(fn))) */
|
||||
|
||||
static void try_call_scope_cleanup(Sym *stop, CType *func_type)
|
||||
/* save SValue of symbol to local stack */
|
||||
static void save_cleanup_sym(Sym *s)
|
||||
{
|
||||
SValue *sv = vtop;
|
||||
while (sv >= vstack) {
|
||||
if (sv->sym == s) {
|
||||
int align, size = type_size(&sv->type, &align);
|
||||
loc = (loc - size) & -align;
|
||||
vset(&sv->type, VT_LOCAL | VT_LVAL, loc);
|
||||
vpushv(sv), *sv = vtop[-1], vstore(), --vtop;
|
||||
}
|
||||
--sv;
|
||||
}
|
||||
}
|
||||
|
||||
static void try_call_scope_cleanup(Sym *stop)
|
||||
{
|
||||
Sym *cls = cur_scope->cl.s;
|
||||
|
||||
if (cls == stop)
|
||||
func_type = NULL;
|
||||
if (func_type && func_type->t != VT_VOID)
|
||||
save_return_reg(func_type);
|
||||
for (; cls != stop; cls = cls->next) {
|
||||
Sym *fs = cls->cleanup_func;
|
||||
Sym *vs = cls->prev_tok;
|
||||
|
||||
save_cleanup_sym(vs);
|
||||
vpushsym(&fs->type, fs);
|
||||
vset(&vs->type, vs->r, vs->c);
|
||||
vtop->sym = vs;
|
||||
@@ -6858,8 +6868,6 @@ static void try_call_scope_cleanup(Sym *stop, CType *func_type)
|
||||
gaddrof();
|
||||
gfunc_call(1);
|
||||
}
|
||||
if (func_type && func_type->t != VT_VOID)
|
||||
restore_return_reg(func_type);
|
||||
}
|
||||
|
||||
static void try_call_cleanup_goto(Sym *cleanupstate)
|
||||
@@ -6879,7 +6887,7 @@ static void try_call_cleanup_goto(Sym *cleanupstate)
|
||||
for (; cc != oc; cc = cc->next, oc = oc->next, --ccd)
|
||||
;
|
||||
|
||||
try_call_scope_cleanup(cc, NULL);
|
||||
try_call_scope_cleanup(cc);
|
||||
}
|
||||
|
||||
/* call 'func' for each __attribute__((cleanup(func))) */
|
||||
@@ -6893,7 +6901,7 @@ static void block_cleanup(struct scope *o)
|
||||
if (!jmp)
|
||||
jmp = gjmp(0);
|
||||
gsym(pcl->jnext);
|
||||
try_call_scope_cleanup(o->cl.s, NULL);
|
||||
try_call_scope_cleanup(o->cl.s);
|
||||
pcl->jnext = gjmp(0);
|
||||
if (!o->cl.n)
|
||||
goto remove_pending;
|
||||
@@ -6906,7 +6914,7 @@ static void block_cleanup(struct scope *o)
|
||||
}
|
||||
}
|
||||
gsym(jmp);
|
||||
try_call_scope_cleanup(o->cl.s, NULL);
|
||||
try_call_scope_cleanup(o->cl.s);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
@@ -6970,11 +6978,11 @@ static void prev_scope(struct scope *o, int is_expr)
|
||||
}
|
||||
|
||||
/* leave a scope via break/continue(/goto) */
|
||||
static void leave_scope(struct scope *o, CType *func_type)
|
||||
static void leave_scope(struct scope *o)
|
||||
{
|
||||
if (!o)
|
||||
return;
|
||||
try_call_scope_cleanup(o->cl.s, func_type);
|
||||
try_call_scope_cleanup(o->cl.s);
|
||||
vla_leave(o);
|
||||
}
|
||||
|
||||
@@ -7116,9 +7124,9 @@ again:
|
||||
tcc_warning("'return' with no value");
|
||||
b = 0;
|
||||
}
|
||||
leave_scope(root_scope);
|
||||
if (b)
|
||||
gfunc_return(&func_vt);
|
||||
leave_scope(root_scope, &func_vt);
|
||||
skip(';');
|
||||
/* jump unless last stmt in top-level block */
|
||||
if (tok != '}' || local_scope != 1)
|
||||
@@ -7132,9 +7140,9 @@ again:
|
||||
if (!cur_scope->bsym)
|
||||
tcc_error("cannot break");
|
||||
if (cur_switch && cur_scope->bsym == cur_switch->bsym)
|
||||
leave_scope(cur_switch->scope, NULL);
|
||||
leave_scope(cur_switch->scope);
|
||||
else
|
||||
leave_scope(loop_scope, NULL);
|
||||
leave_scope(loop_scope);
|
||||
*cur_scope->bsym = gjmp(*cur_scope->bsym);
|
||||
skip(';');
|
||||
|
||||
@@ -7142,7 +7150,7 @@ again:
|
||||
/* compute jump */
|
||||
if (!cur_scope->csym)
|
||||
tcc_error("cannot continue");
|
||||
leave_scope(loop_scope, NULL);
|
||||
leave_scope(loop_scope);
|
||||
*cur_scope->csym = gjmp(*cur_scope->csym);
|
||||
skip(';');
|
||||
|
||||
@@ -8406,7 +8414,7 @@ static void gen_function(Sym *sym)
|
||||
/* reset local stack */
|
||||
pop_local_syms(NULL, 0);
|
||||
tcc_debug_prolog_epilog(tcc_state, 1);
|
||||
gfunc_epilog(sym);
|
||||
gfunc_epilog();
|
||||
|
||||
/* end of function */
|
||||
tcc_debug_funcend(tcc_state, ind - func_ind);
|
||||
|
||||
72
x86_64-gen.c
72
x86_64-gen.c
@@ -655,50 +655,6 @@ static void gcall_or_jmp(int is_jmp)
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC void save_return_reg(CType *func_type)
|
||||
{
|
||||
int freg = is_float(func_type->t & VT_BTYPE);
|
||||
int ireg = !freg;
|
||||
|
||||
if ((func_type->t & VT_BTYPE) == VT_STRUCT)
|
||||
ireg = freg = 1;
|
||||
if (ireg)
|
||||
o(0x5250); /* push %rax; %push %rdx */
|
||||
if (freg) {
|
||||
if ((func_type->t & VT_BTYPE) == VT_LDOUBLE ||
|
||||
(func_type->t & VT_BTYPE) == VT_STRUCT) {
|
||||
o(0x10ec8348); /* sub $16,%rsp */
|
||||
o(0x243cdb); /* fstpt (%rsp) */
|
||||
}
|
||||
o(0x20ec8348); /* sub $32,%rsp */
|
||||
o(0x290f); /* movaps %xmm0,0x10(%rsp) */
|
||||
o(0x102444);
|
||||
o(0x240c290f); /* movaps %xmm1,(%rsp) */
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC void restore_return_reg(CType *func_type)
|
||||
{
|
||||
int freg = is_float(func_type->t & VT_BTYPE);
|
||||
int ireg = !freg;
|
||||
|
||||
if ((func_type->t & VT_BTYPE) == VT_STRUCT)
|
||||
ireg = freg = 1;
|
||||
if (freg) {
|
||||
o(0x280f); /* movaps 0x10(%rsp),%xmm0 */
|
||||
o(0x102444);
|
||||
o(0x240c280f); /* movaps (%rsp),%xmm1 */
|
||||
o(0x20c48348); /* add $32,%rsp */
|
||||
if ((func_type->t & VT_BTYPE) == VT_LDOUBLE ||
|
||||
(func_type->t & VT_BTYPE) == VT_STRUCT) {
|
||||
o(0x242cdb); /* fldt (%rsp) */
|
||||
o(0x10c48348); /* add $16,%rsp */
|
||||
}
|
||||
}
|
||||
if (ireg)
|
||||
o(0x585a); /* pop %rdx; pop %rax */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
|
||||
static void gen_bounds_call(int v)
|
||||
@@ -725,13 +681,12 @@ static void gen_bounds_prolog(void)
|
||||
oad(0xb8, 0); /* call to function */
|
||||
}
|
||||
|
||||
static void gen_bounds_epilog(Sym *func_sym)
|
||||
static void gen_bounds_epilog(void)
|
||||
{
|
||||
addr_t saved_ind;
|
||||
addr_t *bounds_ptr;
|
||||
Sym *sym_data;
|
||||
int offset_modified = func_bound_offset != lbounds_section->data_offset;
|
||||
CType *func_type = &func_sym->type.ref->type;
|
||||
|
||||
if (!offset_modified && !func_bound_add_epilog)
|
||||
return;
|
||||
@@ -754,14 +709,20 @@ static void gen_bounds_epilog(Sym *func_sym)
|
||||
}
|
||||
|
||||
/* generate bound check local freeing */
|
||||
if (func_type->t != VT_VOID)
|
||||
save_return_reg(func_type);
|
||||
o(0x5250); /* save returned value, if any */
|
||||
o(0x20ec8348); /* sub $32,%rsp */
|
||||
o(0x290f); /* movaps %xmm0,0x10(%rsp) */
|
||||
o(0x102444);
|
||||
o(0x240c290f); /* movaps %xmm1,(%rsp) */
|
||||
greloca(cur_text_section, sym_data, ind + 3, R_X86_64_PC32, -4);
|
||||
o(0x0d8d48 + ((TREG_FASTCALL_1 == TREG_RDI) * 0x300000)); /* lea xxx(%rip), %rcx/rdi */
|
||||
gen_le32 (0);
|
||||
gen_bounds_call(TOK___bound_local_delete);
|
||||
if (func_type->t != VT_VOID)
|
||||
restore_return_reg(func_type);
|
||||
o(0x280f); /* movaps 0x10(%rsp),%xmm0 */
|
||||
o(0x102444);
|
||||
o(0x240c280f); /* movaps (%rsp),%xmm1 */
|
||||
o(0x20c48348); /* add $32,%rsp */
|
||||
o(0x585a); /* restore returned value, if any */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1044,7 +1005,7 @@ void gfunc_prolog(Sym *func_sym)
|
||||
}
|
||||
|
||||
/* generate function epilog */
|
||||
void gfunc_epilog(Sym *func_sym)
|
||||
void gfunc_epilog(void)
|
||||
{
|
||||
int v, start;
|
||||
|
||||
@@ -1054,9 +1015,8 @@ void gfunc_epilog(Sym *func_sym)
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check)
|
||||
gen_bounds_epilog(func_sym);
|
||||
gen_bounds_epilog();
|
||||
#endif
|
||||
func_sym = NULL;
|
||||
|
||||
o(0xc9); /* leave */
|
||||
if (func_ret_sub == 0) {
|
||||
@@ -1640,16 +1600,14 @@ void gfunc_prolog(Sym *func_sym)
|
||||
}
|
||||
|
||||
/* generate function epilog */
|
||||
void gfunc_epilog(Sym *func_sym)
|
||||
void gfunc_epilog(void)
|
||||
{
|
||||
int v, saved_ind;
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check)
|
||||
gen_bounds_epilog(func_sym);
|
||||
gen_bounds_epilog();
|
||||
#endif
|
||||
func_sym = NULL;
|
||||
|
||||
o(0xc9); /* leave */
|
||||
if (func_ret_sub == 0) {
|
||||
o(0xc3); /* ret */
|
||||
|
||||
Reference in New Issue
Block a user