c - What is the difference between assembler generated for functions with and without returns_twice and noreturn? -
i understand noreturn should used functions expected doesn't return control caller, can't find difference in generated assembler codes. know examples generate different codes?
edit: noreturn not generate cleanup code after it.
returns_twice
disables gcc optimizations.
as example, in old gcc version have laying around: tail call optimization, global common subexpression elimination, jump bypassing.
returns_twice
uses calls_setjmp
machinery (all around source tree):
if (flags & ecf_returns_twice) cfun->calls_setjmp = true;
tco (gcc/tree-tailcall.c
):
static bool suitable_for_tail_call_opt_p (void) { [...] /* function calls setjmp might have longjmp called called function. ??? should represent in cfg needn't special cased. */ if (cfun->calls_setjmp) return false;
gcse (gcc/gcse.c
):
static int gcse_main (rtx f attribute_unused) { [...] /* not construct accurate cfg in functions call setjmp, punt safe. */ if (cfun->calls_setjmp) return 0;
jump-bypassing (gcc/gcse.c
):
static int bypass_jumps (void) { [...] /* not construct accurate cfg in functions call setjmp, punt safe. */ if (cfun->calls_setjmp) return 0;
the function can neither pure nor const (gcc/ipa-pure-const.c
):
/* check parameters of function call call_expr see if there references in parameters not allowed pure or const functions. check see if either indirect call, call outside compilation unit, or has special attributes may effect purity. call_expr node entire call expression. */ static void check_call (funct_state local, gimple call) { [...] /* when bad things happen bad functions, cannot const or pure. */ if (setjmp_call_p (callee_t)) { local->pure_const_state = ipa_neither; local->looping = false; }
the function cannot inlined (gcc/tree-inline.c
):
/* callback walk_gimple_seq handle statements. returns non-null iff function can not inlined. sets reason why. */ static tree inline_forbidden_p_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, struct walk_stmt_info *wip) { [...] /* cannot inline functions call setjmp. */ if (setjmp_call_p (t)) { inline_forbidden_reason = g_("function %q+f can never inlined because uses setjmp"); *handled_ops_p = true; return t; }
it affects register save area in function's stack frame.
example(tco):
func.c:
int func(void) { return 0; }
tco.c:
extern int func(void) /*__attribute__((returns_twice))*/; int main() { return func(); }
doesn't return twice:
00000000004003a0 <main>: 4003a0: e9 0b 01 00 00 jmpq 4004b0 <func> 4003a5: 90 nop 4003a6: 90 nop 4003a7: 90 nop
returns twice:
00000000004003a0 <main>: 4003a0: 48 83 ec 08 sub $0x8,%rsp 4003a4: e8 17 01 00 00 callq 4004c0 <func> 4003a9: 48 83 c4 08 add $0x8,%rsp 4003ad: c3 retq 4003ae: 90 nop 4003af: 90 nop
Comments
Post a Comment