History

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.

herman ten brugge committed 1 year ago

Commit b6a16e31 parent 6ca228313 files · +344 −57Browse files

Unified · Split

13 files
  1. arm-gen.c +36 −7
  2. arm64-gen.c +35 −7
  3. c67-gen.c +14 −1
  4. i386-gen.c +26 −6
  5. il-gen.c +12 −1
  6. riscv64-gen.c +49 −8
  7. tcc.h +3 −1
  8. tccgen.c +17 −11
  9. tccrun.c +2 −0
  10. tests/tests2/101_cleanup.c +82 −0
  11. tests/tests2/101_cleanup.expect +10 −0
  12. tests/tests2/Makefile +1 −0
  13. x86_64-gen.c +57 −15
arm-gen.c+36−7
@@ -837,6 +837,32 @@ static void gcall_or_jmp(int is_jmp) · 836 unmodified lines
837837 }
838838 }
839839
840+ST_FUNC void save_return_reg(CType *func_type)
841+{
842+ int freg = is_float(func_type->t & VT_BTYPE);
843+ int ireg = !freg;
844+
845+ if ((func_type->t & VT_BTYPE) == VT_STRUCT)
846+ ireg = freg = 1;
847+ if (ireg)
848+ o(0xe92d0003); /* push {r0,r1} */
849+ if (freg)
850+ o(0xed2d0b04); /* vpush {d0,d1} */
851+}
852+
853+ST_FUNC void restore_return_reg(CType *func_type)
854+{
855+ int freg = is_float(func_type->t & VT_BTYPE);
856+ int ireg = !freg;
857+
858+ if ((func_type->t & VT_BTYPE) == VT_STRUCT)
859+ ireg = freg = 1;
860+ if (freg)
861+ o(0xecbd0b04); /* vpop {d0,d1} */
862+ if (ireg)
863+ o(0xe8bd0003); /* pop {r0,r1} */
864+}
865+
840866 #if defined(CONFIG_TCC_BCHECK)
841867
842868 static void gen_bounds_call(int v)
@@ -860,12 +886,13 @@ static void gen_bounds_prolog(void) · 17 unmodified lines
860886 o(0xe1a00000); /* call __bound_local_new */
861887 }
862888
863−static void gen_bounds_epilog(void)
889+static void gen_bounds_epilog(Sym *func_sym)
864890 {
865891 addr_t saved_ind;
866892 addr_t *bounds_ptr;
867893 Sym *sym_data;
868894 int offset_modified = func_bound_offset != lbounds_section->data_offset;
895+ CType *func_type = &func_sym->type.ref->type;
869896
870897 if (!offset_modified && !func_bound_add_epilog)
871898 return;
@@ -891,16 +918,16 @@ static void gen_bounds_epilog(void) · 19 unmodified lines
891918 }
892919
893920 /* generate bound check local freeing */
894− o(0xe92d0003); /* push {r0,r1} */
895− o(0xed2d0b04); /* vpush {d0,d1} */
921+ if (func_type->t != VT_VOID)
922+ save_return_reg(func_type);
896923 o(0xe59f0000); /* ldr r0, [pc] */
897924 o(0xea000000); /* b $+4 */
898925 greloc(cur_text_section, sym_data, ind, R_ARM_REL32);
899926 o(-12); /* lbounds_section->data_offset */
900927 o(0xe080000f); /* add r0,r0,pc */
901928 gen_bounds_call(TOK___bound_local_delete);
902− o(0xecbd0b04); /* vpop {d0,d1} */
903− o(0xe8bd0003); /* pop {r0,r1} */
929+ if (func_type->t != VT_VOID)
930+ restore_return_reg(func_type);
904931 }
905932 #endif
906933
@@ -1508,15 +1535,17 @@ from_stack: · 601 unmodified lines
15081535 }
15091536
15101537 /* generate function epilog */
1511−void gfunc_epilog(void)
1538+void gfunc_epilog(Sym *func_sym)
15121539 {
15131540 uint32_t x;
15141541 int diff;
15151542
15161543 #ifdef CONFIG_TCC_BCHECK
15171544 if (tcc_state->do_bounds_check)
1518− gen_bounds_epilog();
1545+ gen_bounds_epilog(func_sym);
15191546 #endif
1547+ func_sym = NULL;
1548+
15201549 /* Copy float return value to core register if base standard is used and
15211550 float computation is made with VFP */
15221551 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
arm64-gen.c+35−7
@@ -674,6 +674,32 @@ static void arm64_gen_bl_or_b(int b) · 673 unmodified lines
674674 }
675675 }
676676
677+ST_FUNC void save_return_reg(CType *func_type)
678+{
679+ int freg = is_float(func_type->t & VT_BTYPE);
680+ int ireg = !freg;
681+
682+ if ((func_type->t & VT_BTYPE) == VT_STRUCT)
683+ ireg = freg = 1;
684+ if (ireg)
685+ o(0xa9bf07e0); /* stp x0, x1, [sp, #-16]! */
686+ if (freg)
687+ o(0xadbf07e0); /* stp q0, q1, [sp, #-32]! */
688+}
689+
690+ST_FUNC void restore_return_reg(CType *func_type)
691+{
692+ int freg = is_float(func_type->t & VT_BTYPE);
693+ int ireg = !freg;
694+
695+ if ((func_type->t & VT_BTYPE) == VT_STRUCT)
696+ ireg = freg = 1;
697+ if (freg)
698+ o(0xacc107e0); /* ldp q0, q1, [sp], #32 */
699+ if (ireg)
700+ o(0xa8c107e0); /* ldp x0, x1, [sp], #16 */
701+}
702+
677703 #if defined(CONFIG_TCC_BCHECK)
678704
679705 static void gen_bounds_call(int v)
@@ -696,12 +722,13 @@ static void gen_bounds_prolog(void) · 16 unmodified lines
696722 o(0xd503201f); /* nop -> call __bound_local_new */
697723 }
698724
699−static void gen_bounds_epilog(void)
725+static void gen_bounds_epilog(Sym *func_sym)
700726 {
701727 addr_t saved_ind;
702728 addr_t *bounds_ptr;
703729 Sym *sym_data;
704730 int offset_modified = func_bound_offset != lbounds_section->data_offset;
731+ CType *func_type = &func_sym->type.ref->type;
705732
706733 if (!offset_modified && !func_bound_add_epilog)
707734 return;
@@ -726,15 +753,15 @@ static void gen_bounds_epilog(void) · 18 unmodified lines
726753 }
727754
728755 /* generate bound check local freeing */
729− o(0xa9bf07e0); /* stp x0, x1, [sp, #-16]! */
730− o(0x3c9f0fe0); /* str q0, [sp, #-16]! */
756+ if (func_type->t != VT_VOID)
757+ save_return_reg(func_type);
731758 greloca(cur_text_section, sym_data, ind, R_AARCH64_ADR_GOT_PAGE, 0);
732759 o(0x90000000 | 0); // adrp x0, #sym_data
733760 greloca(cur_text_section, sym_data, ind, R_AARCH64_LD64_GOT_LO12_NC, 0);
734761 o(0xf9400000 | 0 | (0 << 5)); // ld x0,[x0, #sym_data]
735762 gen_bounds_call(TOK___bound_local_delete);
736− o(0x3cc107e0); /* ldr q0, [sp], #16 */
737− o(0xa8c107e0); /* ldp x0, x1, [sp], #16 */
763+ if (func_type->t != VT_VOID)
764+ restore_return_reg(func_type);
738765 }
739766 #endif
740767
@@ -1459,12 +1486,13 @@ ST_FUNC void gfunc_return(CType *func_type) · 718 unmodified lines
14591486 vtop--;
14601487 }
14611488
1462−ST_FUNC void gfunc_epilog(void)
1489+ST_FUNC void gfunc_epilog(Sym *func_sym)
14631490 {
14641491 #ifdef CONFIG_TCC_BCHECK
14651492 if (tcc_state->do_bounds_check)
1466− gen_bounds_epilog();
1493+ gen_bounds_epilog(func_sym);
14671494 #endif
1495+ func_sym = NULL;
14681496
14691497 if (loc) {
14701498 // Insert instructions to subtract size of stack frame from SP.
c67-gen.c+14−1
@@ -2019,9 +2019,22 @@ void gfunc_prolog(Sym *func_sym) · 2018 unmodified lines
20192019 C67_PUSH(C67_B3);
20202020 }
20212021
2022+ST_FUNC void save_return_reg(CType *func_type)
2023+{
2024+ func_type = NULL;
2025+ // TODO
2026+}
2027+
2028+ST_FUNC void restore_return_reg(CType *func_type)
2029+{
2030+ func_type = NULL;
2031+ // TODO
2032+}
2033+
20222034 /* generate function epilog */
2023−void gfunc_epilog(void)
2035+void gfunc_epilog(Sym *func_sym)
20242036 {
2037+ func_sym = NULL;
20252038 {
20262039 int local = (-loc + 7) & -8; // stack must stay aligned to 8 bytes for LDDW instr
20272040 C67_POP(C67_B3);
i386-gen.c+26−6
@@ -104,7 +104,7 @@ static addr_t func_bound_offset; · 103 unmodified lines
104104 static unsigned long func_bound_ind;
105105 ST_DATA int func_bound_add_epilog;
106106 static void gen_bounds_prolog(void);
107−static void gen_bounds_epilog(void);
107+static void gen_bounds_epilog(Sym *func_sym);
108108 #endif
109109
110110 /* XXX: make it faster ? */
@@ -595,14 +595,15 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 484 unmodified lines
595595 }
596596
597597 /* generate function epilog */
598−ST_FUNC void gfunc_epilog(void)
598+ST_FUNC void gfunc_epilog(Sym *func_sym)
599599 {
600600 addr_t v, saved_ind;
601601
602602 #ifdef CONFIG_TCC_BCHECK
603603 if (tcc_state->do_bounds_check)
604− gen_bounds_epilog();
604+ gen_bounds_epilog(func_sym);
605605 #endif
606+ func_sym = NULL;
606607
607608 /* align local size to word & save local variables */
608609 v = (-loc + 3) & -4;
@@ -1040,6 +1041,22 @@ ST_FUNC void ggoto(void) · 431 unmodified lines
10401041 vtop--;
10411042 }
10421043
1044+ST_FUNC void save_return_reg(CType *func_type)
1045+{
1046+ int ireg = !is_float(func_type->t & VT_BTYPE);
1047+
1048+ if (ireg)
1049+ o(0x5250); /* push %rax; %push %rdx */
1050+}
1051+
1052+ST_FUNC void restore_return_reg(CType *func_type)
1053+{
1054+ int ireg = !is_float(func_type->t & VT_BTYPE);
1055+
1056+ if (ireg)
1057+ o(0x585a); /* pop %rdx; pop %rax */
1058+}
1059+
10431060 /* bound check support functions */
10441061 #ifdef CONFIG_TCC_BCHECK
10451062
@@ -1053,12 +1070,13 @@ static void gen_bounds_prolog(void) · 7 unmodified lines
10531070 oad(0xb8, 0); /* call to function */
10541071 }
10551072
1056−static void gen_bounds_epilog(void)
1073+static void gen_bounds_epilog(Sym *func_sym)
10571074 {
10581075 addr_t saved_ind;
10591076 addr_t *bounds_ptr;
10601077 Sym *sym_data;
10611078 int offset_modified = func_bound_offset != lbounds_section->data_offset;
1079+ CType *func_type = &func_sym->type.ref->type;
10621080
10631081 if (!offset_modified && !func_bound_add_epilog)
10641082 return;
@@ -1081,11 +1099,13 @@ static void gen_bounds_epilog(void) · 16 unmodified lines
10811099 }
10821100
10831101 /* generate bound check local freeing */
1084− o(0x5250); /* save returned value, if any */
1102+ if (func_type->t != VT_VOID)
1103+ save_return_reg(func_type);
10851104 greloc(cur_text_section, sym_data, ind + 1, R_386_32);
10861105 oad(0xb8, 0); /* mov %eax, xxx */
10871106 gen_static_call(TOK___bound_local_delete);
1088− o(0x585a); /* restore returned value, if any */
1107+ if (func_type->t != VT_VOID)
1108+ restore_return_reg(func_type);
10891109 }
10901110 #endif
10911111
il-gen.c+12−1
@@ -457,9 +457,20 @@ void gfunc_prolog(int t) · 456 unmodified lines
457457 }
458458 }
459459
460+void save_return_reg(CType *func_type)
461+{
462+ func_type = NULL;
463+}
464+
465+void restore_return_reg(CType *func_type)
466+{
467+ func_type = NULL;
468+}
469+
460470 /* generate function epilog */
461−void gfunc_epilog(void)
471+void gfunc_epilog(Sym *func_sym)
462472 {
473+ func_sym = NULL;
463474 out_op(IL_OP_RET);
464475 fprintf(il_outfile, "}\n\n");
465476 }
riscv64-gen.c+49−8
@@ -436,6 +436,46 @@ static void gcall_or_jmp(int docall) · 435 unmodified lines
436436 }
437437 }
438438
439+ST_FUNC void save_return_reg(CType *func_type)
440+{
441+ int freg = is_float(func_type->t & VT_BTYPE) &&
442+ (func_type->t & VT_BTYPE) != VT_LDOUBLE;
443+ int ireg = !freg;
444+
445+ if ((func_type->t & VT_BTYPE) == VT_STRUCT)
446+ ireg = freg = 1;
447+ if (ireg && freg) {
448+ o(0xe02a1101); /* addi sp,sp,-32 sd a0,0(sp) */
449+ o(0xa82ae42e); /* sd a1,8(sp) fsd fa0,16(sp) */
450+ }
451+ else if (ireg) {
452+ o(0xe02a1141); /* addi sp,sp,-16 sd a0,0(sp) */
453+ o(0x0001e42e); /* sd a1,8(sp) nop */
454+ }
455+ else if (freg)
456+ o(0xa02a1141); /* addi sp,sp,-16 fsd fa0,0(sp) */
457+}
458+
459+ST_FUNC void restore_return_reg(CType *func_type)
460+{
461+ int freg = is_float(func_type->t & VT_BTYPE) &&
462+ (func_type->t & VT_BTYPE) != VT_LDOUBLE;
463+ int ireg = !freg;
464+
465+ if ((func_type->t & VT_BTYPE) == VT_STRUCT)
466+ ireg = freg = 1;
467+ if (ireg && freg) {
468+ o(0x65a26502); /* ld a0,0(sp) ld a1,8(sp) */
469+ o(0x61052542); /* fld fa0,16(sp) addi sp,sp,32 */
470+ }
471+ else if (ireg) {
472+ o(0x65a26502); /* ld a0,0(sp) ld a1,8(sp) */
473+ o(0x00010141); /* addi sp,sp,16 nop */
474+ }
475+ else if (freg)
476+ o(0x01412502); /* fld fa0,0(sp) addi sp,sp,16 */
477+}
478+
439479 #if defined(CONFIG_TCC_BCHECK)
440480
441481 static void gen_bounds_call(int v)
@@ -459,14 +499,14 @@ static void gen_bounds_prolog(void) · 17 unmodified lines
459499 o(0x00000013);
460500 }
461501
462−static void gen_bounds_epilog(void)
502+static void gen_bounds_epilog(Sym *func_sym)
463503 {
464504 addr_t saved_ind;
465505 addr_t *bounds_ptr;
466506 Sym *sym_data;
467507 Sym label = {0};
468−
469508 int offset_modified = func_bound_offset != lbounds_section->data_offset;
509+ CType *func_type = &func_sym->type.ref->type;
470510
471511 if (!offset_modified && !func_bound_add_epilog)
472512 return;
@@ -494,16 +534,16 @@ static void gen_bounds_epilog(void) · 21 unmodified lines
494534 }
495535
496536 /* generate bound check local freeing */
497− o(0xe02a1101); /* addi sp,sp,-32 sd a0,0(sp) */
498− o(0xa82ae42e); /* sd a1,8(sp) fsd fa0,16(sp) */
537+ if (func_type->t != VT_VOID)
538+ save_return_reg(func_type);
499539 put_extern_sym(&label, cur_text_section, ind, 0);
500540 greloca(cur_text_section, sym_data, ind, R_RISCV_GOT_HI20, 0);
501541 o(0x17 | (10 << 7)); // auipc a0, 0 %pcrel_hi(sym)+addend
502542 greloca(cur_text_section, &label, ind, R_RISCV_PCREL_LO12_I, 0);
503543 EI(0x03, 3, 10, 10, 0); // ld a0, 0(a0)
504544 gen_bounds_call(TOK___bound_local_delete);
505− o(0x65a26502); /* ld a0,0(sp) ld a1,8(sp) */
506− o(0x61052542); /* fld fa0,16(sp) addi sp,sp,32 */
545+ if (func_type->t != VT_VOID)
546+ restore_return_reg(func_type);
507547 }
508548 #endif
509549
@@ -893,14 +933,15 @@ ST_FUNC void arch_transfer_ret_regs(int aftercall) · 383 unmodified lines
893933 vtop--;
894934 }
895935
896−ST_FUNC void gfunc_epilog(void)
936+ST_FUNC void gfunc_epilog(Sym *func_sym)
897937 {
898938 int v, saved_ind, d, large_ofs_ind;
899939
900940 #ifdef CONFIG_TCC_BCHECK
901941 if (tcc_state->do_bounds_check)
902− gen_bounds_epilog();
942+ gen_bounds_epilog(func_sym);
903943 #endif
944+ func_sym = NULL;
904945
905946 loc = (loc - num_va_regs * 8);
906947 d = v = (-loc + 15) & -16;
tcc.h+3−1
@@ -1607,7 +1607,9 @@ ST_FUNC void store(int r, SValue *v); · 1606 unmodified lines
16071607 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize);
16081608 ST_FUNC void gfunc_call(int nb_args);
16091609 ST_FUNC void gfunc_prolog(Sym *func_sym);
1610−ST_FUNC void gfunc_epilog(void);
1610+ST_FUNC void gfunc_epilog(Sym *func_sym);
1611+ST_FUNC void save_return_reg(CType *func_type);
1612+ST_FUNC void restore_return_reg(CType *func_type);
16111613 ST_FUNC void gen_fill_nops(int);
16121614 ST_FUNC int gjmp(int t);
16131615 ST_FUNC void gjmp_addr(int a);
tccgen.c+17−11
@@ -6839,10 +6839,14 @@ static void end_switch(void) · 6838 unmodified lines
68396839 /* ------------------------------------------------------------------------- */
68406840 /* __attribute__((cleanup(fn))) */
68416841
6842−static void try_call_scope_cleanup(Sym *stop)
6842+static void try_call_scope_cleanup(Sym *stop, CType *func_type)
68436843 {
68446844 Sym *cls = cur_scope->cl.s;
68456845
6846+ if (cls == stop)
6847+ func_type = NULL;
6848+ if (func_type && func_type->t != VT_VOID)
6849+ save_return_reg(func_type);
68466850 for (; cls != stop; cls = cls->next) {
68476851 Sym *fs = cls->cleanup_func;
68486852 Sym *vs = cls->prev_tok;
@@ -6854,6 +6858,8 @@ static void try_call_scope_cleanup(Sym *stop) · 5 unmodified lines
68546858 gaddrof();
68556859 gfunc_call(1);
68566860 }
6861+ if (func_type && func_type->t != VT_VOID)
6862+ restore_return_reg(func_type);
68576863 }
68586864
68596865 static void try_call_cleanup_goto(Sym *cleanupstate)
@@ -6873,7 +6879,7 @@ static void try_call_cleanup_goto(Sym *cleanupstate) · 13 unmodified lines
68736879 for (; cc != oc; cc = cc->next, oc = oc->next, --ccd)
68746880 ;
68756881
6876− try_call_scope_cleanup(cc);
6882+ try_call_scope_cleanup(cc, NULL);
68776883 }
68786884
68796885 /* call 'func' for each __attribute__((cleanup(func))) */
@@ -6887,7 +6893,7 @@ static void block_cleanup(struct scope *o) · 7 unmodified lines
68876893 if (!jmp)
68886894 jmp = gjmp(0);
68896895 gsym(pcl->jnext);
6890− try_call_scope_cleanup(o->cl.s);
6896+ try_call_scope_cleanup(o->cl.s, NULL);
68916897 pcl->jnext = gjmp(0);
68926898 if (!o->cl.n)
68936899 goto remove_pending;
@@ -6900,7 +6906,7 @@ static void block_cleanup(struct scope *o) · 6 unmodified lines
69006906 }
69016907 }
69026908 gsym(jmp);
6903− try_call_scope_cleanup(o->cl.s);
6909+ try_call_scope_cleanup(o->cl.s, NULL);
69046910 }
69056911
69066912 /* ------------------------------------------------------------------------- */
@@ -6964,11 +6970,11 @@ static void prev_scope(struct scope *o, int is_expr) · 57 unmodified lines
69646970 }
69656971
69666972 /* leave a scope via break/continue(/goto) */
6967−static void leave_scope(struct scope *o)
6973+static void leave_scope(struct scope *o, CType *func_type)
69686974 {
69696975 if (!o)
69706976 return;
6971− try_call_scope_cleanup(o->cl.s);
6977+ try_call_scope_cleanup(o->cl.s, func_type);
69726978 vla_leave(o);
69736979 }
69746980
@@ -7110,9 +7116,9 @@ again: · 135 unmodified lines
71107116 tcc_warning("'return' with no value");
71117117 b = 0;
71127118 }
7113− leave_scope(root_scope);
71147119 if (b)
71157120 gfunc_return(&func_vt);
7121+ leave_scope(root_scope, &func_vt);
71167122 skip(';');
71177123 /* jump unless last stmt in top-level block */
71187124 if (tok != '}' || local_scope != 1)
@@ -7126,9 +7132,9 @@ again: · 7 unmodified lines
71267132 if (!cur_scope->bsym)
71277133 tcc_error("cannot break");
71287134 if (cur_switch && cur_scope->bsym == cur_switch->bsym)
7129− leave_scope(cur_switch->scope);
7135+ leave_scope(cur_switch->scope, NULL);
71307136 else
7131− leave_scope(loop_scope);
7137+ leave_scope(loop_scope, NULL);
71327138 *cur_scope->bsym = gjmp(*cur_scope->bsym);
71337139 skip(';');
71347140
@@ -7136,7 +7142,7 @@ again: · 1 unmodified line
71367142 /* compute jump */
71377143 if (!cur_scope->csym)
71387144 tcc_error("cannot continue");
7139− leave_scope(loop_scope);
7145+ leave_scope(loop_scope, NULL);
71407146 *cur_scope->csym = gjmp(*cur_scope->csym);
71417147 skip(';');
71427148
@@ -8400,7 +8406,7 @@ static void gen_function(Sym *sym) · 1257 unmodified lines
84008406 /* reset local stack */
84018407 pop_local_syms(NULL, 0);
84028408 tcc_debug_prolog_epilog(tcc_state, 1);
8403− gfunc_epilog();
8409+ gfunc_epilog(sym);
84048410
84058411 /* end of function */
84068412 tcc_debug_funcend(tcc_state, ind - func_ind);
tccrun.c+2−0
@@ -495,7 +495,9 @@ static void bt_link(TCCState *s1) · 494 unmodified lines
495495 {
496496 #ifdef CONFIG_TCC_BACKTRACE
497497 rt_context *rc;
498+#ifdef CONFIG_TCC_BCHECK
498499 void *p;
500+#endif
499501
500502 if (!s1->do_backtrace)
501503 return;
tests/tests2/101_cleanup.c+82−0
@@ -1,9 +1,15 @@
11 extern int printf(const char*, ...);
22 static int glob_i = 0;
33
4+typedef struct { int a; int b; int c; int d; int e; int f; int g; int h; } tstl;
5+typedef struct { int a; int b; int c; int d; } tsti;
6+typedef struct { double a; double b; } tstd;
7+typedef struct { long double a; } tstld;
8+
49 void incr_glob_i(int *i)
510 {
611 glob_i += *i;
12+ *i = -1;
713 }
814
915 #define INCR_GI { \
@@ -71,17 +77,20 @@ void check(int *j) · 61 unmodified lines
7177 goto out;
7278 }
7379 }
80+ *j = -1;
7481 return;
7582 }
7683
7784 void check_oh_i(char *oh_i)
7885 {
7986 printf("c: %c\n", *oh_i);
87+ *oh_i = '0';
8088 }
8189
8290 void goto_hell(double *f)
8391 {
8492 printf("oo: %f\n", *f);
93+ *f = -1.0;
8594 }
8695
8796 char *test()
@@ -152,6 +161,7 @@ int test3(void) { · 64 unmodified lines
152161 void cl(int *ip)
153162 {
154163 printf("%d\n", *ip);
164+ *ip = -1;
155165 }
156166
157167 void loop_cleanups(void)
@@ -191,11 +201,72 @@ void loop_cleanups(void) · 33 unmodified lines
191201 printf("after break\n");
192202 }
193203
204+void my_cleanup1(int *p) {
205+ printf("%d\n", *p);
206+ *p = 0x90;
207+}
208+
209+int test_cleanup1(void) {
210+ int __attribute__((cleanup(my_cleanup1))) n = 42;
211+ return n;
212+}
213+
214+void my_cleanup2(tstl *p) {
215+ printf("%d %d %d %d %d %d %d %d\n", p->a, p->b, p->c, p->d,
216+ p->e, p->f, p->g, p->h);
217+ p->a = 0x90; p->b = 0x91; p->c = 0x92; p->d = 0x93;
218+ p->e = 0x94; p->f = 0x95; p->g = 0x96; p->h = 0x97;
219+}
220+
221+tstl test_cleanup2(void) {
222+ tstl __attribute__((cleanup(my_cleanup2))) n;
223+ n.a = 42; n.b = 43; n.c = 44; n.d = 45;
224+ n.e = 46; n.f = 47; n.g = 48; n.h = 49;
225+ return n;
226+}
227+
228+void my_cleanup3(tsti *p) {
229+ printf("%d %d %d %d\n", p->a, p->b, p->c, p->d);
230+ p->a = 0x90; p->b = 0x91; p->c = 0x92; p->d = 0x93;
231+}
232+
233+tsti test_cleanup3(void) {
234+ tsti __attribute__((cleanup(my_cleanup3))) n;
235+ n.a = 42; n.b = 43; n.c = 44; n.d = 45;
236+ return n;
237+}
238+
239+void my_cleanup4(tstd *p) {
240+ printf("%g %g\n", p->a, p->b);
241+ p->a = 90.0; p->b = 91.0;
242+}
243+
244+tstd test_cleanup4(void) {
245+ tstd __attribute__((cleanup(my_cleanup4))) n;
246+ n.a = 42.0; n.b = 43.0;
247+ return n;
248+}
249+
250+void my_cleanup5(tstld *p) {
251+ printf("%Lf\n", p->a);
252+ p->a = 90.0;
253+}
254+
255+tstld test_cleanup5(void) {
256+ tstld __attribute__((cleanup(my_cleanup5))) n;
257+ n.a = 42.0;
258+ return n;
259+}
260+
194261 int main()
195262 {
196263 int i __attribute__ ((__cleanup__(check))) = 0, not_i;
197264 int chk = 0;
198265 (void)not_i;
266+ tstl tl;
267+ tsti ti;
268+ tstd td;
269+ tstld tld;
199270
200271 {
201272 __attribute__ ((__cleanup__(check_oh_i))) char oh_i = 'o', o = 'a';
@@ -218,10 +289,21 @@ int main() · 16 unmodified lines
218289 test2();
219290 test3();
220291 loop_cleanups();
292+ printf("%d\n", test_cleanup1());
293+ tl = test_cleanup2();
294+ printf("%d %d %d %d %d %d %d %d\n", tl.a, tl.b, tl.c, tl.d,
295+ tl.e, tl.f, tl.g, tl.h);
296+ ti = test_cleanup3();
297+ printf("%d %d %d %d\n", ti.a, ti.b, ti.c, ti.d);
298+ td = test_cleanup4();
299+ printf("%g %g\n", td.a, td.b);
300+ tld = test_cleanup5();
301+ printf("%Lf\n", tld.a);
221302 return i;
222303 }
223304
224305 void check2(char **hum)
225306 {
226307 printf("str: %s\n", *hum);
308+ *hum = "fail";
227309 }
tests/tests2/101_cleanup.expect+10−0
@@ -48,6 +48,16 @@ str: three · 47 unmodified lines
4848 400
4949 after break
5050 1000
51+42
52+42
53+42 43 44 45 46 47 48 49
54+42 43 44 45 46 47 48 49
55+42 43 44 45
56+42 43 44 45
57+42 43
58+42 43
59+42.000000
60+42.000000
5161 ---- 0
5262 ---- 1
5363 str: plop
tests/tests2/Makefile+1−0
@@ -31,6 +31,7 @@ ifeq ($(CONFIG_bcheck),no) · 30 unmodified lines
3131 SKIP += 116_bound_setjmp2.test
3232 SKIP += 117_builtins.test
3333 SKIP += 126_bound_global.test
34+ SKIP += 132_bound_test.test
3435 endif
3536 ifeq ($(CONFIG_dll),no)
3637 SKIP += 113_btdll.test # no shared lib support yet
x86_64-gen.c+57−15
@@ -655,6 +655,50 @@ static void gcall_or_jmp(int is_jmp) · 654 unmodified lines
655655 }
656656 }
657657
658+ST_FUNC void save_return_reg(CType *func_type)
659+{
660+ int freg = is_float(func_type->t & VT_BTYPE);
661+ int ireg = !freg;
662+
663+ if ((func_type->t & VT_BTYPE) == VT_STRUCT)
664+ ireg = freg = 1;
665+ if (ireg)
666+ o(0x5250); /* push %rax; %push %rdx */
667+ if (freg) {
668+ if ((func_type->t & VT_BTYPE) == VT_LDOUBLE ||
669+ (func_type->t & VT_BTYPE) == VT_STRUCT) {
670+ o(0x10ec8348); /* sub $16,%rsp */
671+ o(0x243cdb); /* fstpt (%rsp) */
672+ }
673+ o(0x20ec8348); /* sub $32,%rsp */
674+ o(0x290f); /* movaps %xmm0,0x10(%rsp) */
675+ o(0x102444);
676+ o(0x240c290f); /* movaps %xmm1,(%rsp) */
677+ }
678+}
679+
680+ST_FUNC void restore_return_reg(CType *func_type)
681+{
682+ int freg = is_float(func_type->t & VT_BTYPE);
683+ int ireg = !freg;
684+
685+ if ((func_type->t & VT_BTYPE) == VT_STRUCT)
686+ ireg = freg = 1;
687+ if (freg) {
688+ o(0x280f); /* movaps 0x10(%rsp),%xmm0 */
689+ o(0x102444);
690+ o(0x240c280f); /* movaps (%rsp),%xmm1 */
691+ o(0x20c48348); /* add $32,%rsp */
692+ if ((func_type->t & VT_BTYPE) == VT_LDOUBLE ||
693+ (func_type->t & VT_BTYPE) == VT_STRUCT) {
694+ o(0x242cdb); /* fldt (%rsp) */
695+ o(0x10c48348); /* add $16,%rsp */
696+ }
697+ }
698+ if (ireg)
699+ o(0x585a); /* pop %rdx; pop %rax */
700+}
701+
658702 #if defined(CONFIG_TCC_BCHECK)
659703
660704 static void gen_bounds_call(int v)
@@ -681,12 +725,13 @@ static void gen_bounds_prolog(void) · 20 unmodified lines
681725 oad(0xb8, 0); /* call to function */
682726 }
683727
684−static void gen_bounds_epilog(void)
728+static void gen_bounds_epilog(Sym *func_sym)
685729 {
686730 addr_t saved_ind;
687731 addr_t *bounds_ptr;
688732 Sym *sym_data;
689733 int offset_modified = func_bound_offset != lbounds_section->data_offset;
734+ CType *func_type = &func_sym->type.ref->type;
690735
691736 if (!offset_modified && !func_bound_add_epilog)
692737 return;
@@ -709,20 +754,14 @@ static void gen_bounds_epilog(void) · 16 unmodified lines
709754 }
710755
711756 /* generate bound check local freeing */
712− o(0x5250); /* save returned value, if any */
713− o(0x20ec8348); /* sub $32,%rsp */
714− o(0x290f); /* movaps %xmm0,0x10(%rsp) */
715− o(0x102444);
716− o(0x240c290f); /* movaps %xmm1,(%rsp) */
757+ if (func_type->t != VT_VOID)
758+ save_return_reg(func_type);
717759 greloca(cur_text_section, sym_data, ind + 3, R_X86_64_PC32, -4);
718760 o(0x0d8d48 + ((TREG_FASTCALL_1 == TREG_RDI) * 0x300000)); /* lea xxx(%rip), %rcx/rdi */
719761 gen_le32 (0);
720762 gen_bounds_call(TOK___bound_local_delete);
721− o(0x280f); /* movaps 0x10(%rsp),%xmm0 */
722− o(0x102444);
723− o(0x240c280f); /* movaps (%rsp),%xmm1 */
724− o(0x20c48348); /* add $32,%rsp */
725− o(0x585a); /* restore returned value, if any */
763+ if (func_type->t != VT_VOID)
764+ restore_return_reg(func_type);
726765 }
727766 #endif
728767
@@ -1005,7 +1044,7 @@ void gfunc_prolog(Sym *func_sym) · 276 unmodified lines
10051044 }
10061045
10071046 /* generate function epilog */
1008−void gfunc_epilog(void)
1047+void gfunc_epilog(Sym *func_sym)
10091048 {
10101049 int v, start;
10111050
@@ -1015,8 +1054,9 @@ void gfunc_epilog(void) · 3 unmodified lines
10151054
10161055 #ifdef CONFIG_TCC_BCHECK
10171056 if (tcc_state->do_bounds_check)
1018− gen_bounds_epilog();
1057+ gen_bounds_epilog(func_sym);
10191058 #endif
1059+ func_sym = NULL;
10201060
10211061 o(0xc9); /* leave */
10221062 if (func_ret_sub == 0) {
@@ -1600,14 +1640,16 @@ void gfunc_prolog(Sym *func_sym) · 577 unmodified lines
16001640 }
16011641
16021642 /* generate function epilog */
1603−void gfunc_epilog(void)
1643+void gfunc_epilog(Sym *func_sym)
16041644 {
16051645 int v, saved_ind;
16061646
16071647 #ifdef CONFIG_TCC_BCHECK
16081648 if (tcc_state->do_bounds_check)
1609− gen_bounds_epilog();
1649+ gen_bounds_epilog(func_sym);
16101650 #endif
1651+ func_sym = NULL;
1652+
16111653 o(0xc9); /* leave */
16121654 if (func_ret_sub == 0) {
16131655 o(0xc3); /* ret */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t