mirror of
https://github.com/TinyCC/tinycc.git
synced 2025-11-16 12:34:45 +00:00
Save registers around attribute cleanup
This makes attribute cleanup code work the same as gcc and also makes bound checking a very little bit faster. tcc.h: Add save_return_reg(CType *) and restore_return_reg(CType *) Change gfunc_epilog() to gfunc_epilog(Sym *) arm-gen.c: arm64-gen.c: c67-gen.c: i386-gen.c: il-gen.c: riscv64-gen.c: x86_64-gen.c: Move save and restore register around bound_local_delete call to save_return_reg and restore_return_reg. Pass func_type from gfunc_epilog to gen_bounds_epilog. tccgen.c: Call save_return_reg/restore_return_reg in try_call_scope_cleanup when RETURN is found. tccrun.c: Fix warning when bound checking not used. tests/tests2/101_cleanup.c tests/tests2/101_cleanup.expect Extra checks attribute cleanup save/restore registers. tests/tests2/Makefile: Fix when bound checking not used.
This commit is contained in:
@@ -436,6 +436,46 @@ 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)
|
||||
@@ -459,14 +499,14 @@ static void gen_bounds_prolog(void)
|
||||
o(0x00000013);
|
||||
}
|
||||
|
||||
static void gen_bounds_epilog(void)
|
||||
static void gen_bounds_epilog(Sym *func_sym)
|
||||
{
|
||||
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;
|
||||
@@ -494,16 +534,16 @@ static void gen_bounds_epilog(void)
|
||||
}
|
||||
|
||||
/* generate bound check local freeing */
|
||||
o(0xe02a1101); /* addi sp,sp,-32 sd a0,0(sp) */
|
||||
o(0xa82ae42e); /* sd a1,8(sp) fsd fa0,16(sp) */
|
||||
if (func_type->t != VT_VOID)
|
||||
save_return_reg(func_type);
|
||||
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);
|
||||
o(0x65a26502); /* ld a0,0(sp) ld a1,8(sp) */
|
||||
o(0x61052542); /* fld fa0,16(sp) addi sp,sp,32 */
|
||||
if (func_type->t != VT_VOID)
|
||||
restore_return_reg(func_type);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -893,14 +933,15 @@ ST_FUNC void arch_transfer_ret_regs(int aftercall)
|
||||
vtop--;
|
||||
}
|
||||
|
||||
ST_FUNC void gfunc_epilog(void)
|
||||
ST_FUNC void gfunc_epilog(Sym *func_sym)
|
||||
{
|
||||
int v, saved_ind, d, large_ofs_ind;
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check)
|
||||
gen_bounds_epilog();
|
||||
gen_bounds_epilog(func_sym);
|
||||
#endif
|
||||
func_sym = NULL;
|
||||
|
||||
loc = (loc - num_va_regs * 8);
|
||||
d = v = (-loc + 15) & -16;
|
||||
|
||||
Reference in New Issue
Block a user