aboutsummaryrefslogtreecommitdiff
path: root/gcc/cgraphunit.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2020-09-14 17:24:32 +0200
committerEric Botcazou <ebotcazou@adacore.com>2020-09-14 17:38:39 +0200
commita7d8dcdf2f3cf9a801e655f2eec3967a3a3ba666 (patch)
treec8845d0fd0b213f1143e93ca46b864115f920cfb /gcc/cgraphunit.c
parent863e8d53eb2940e2c8850e632afe427e164f53cf (diff)
downloadgcc-a7d8dcdf2f3cf9a801e655f2eec3967a3a3ba666.zip
gcc-a7d8dcdf2f3cf9a801e655f2eec3967a3a3ba666.tar.gz
gcc-a7d8dcdf2f3cf9a801e655f2eec3967a3a3ba666.tar.bz2
Fix dangling references in thunks at -O0
When a thunk cannot be emitted in assembly directly, expand_thunk generates regular GIMPLE code but unconditionally forces a tail call to the target of the thunk. That's theoretically OK because the thunk essentially forwards its parameters to the target, but in practice the RTL expander can spill parameters passed by reference on the stack in assign_parm_setup_reg. gcc/ChangeLog: * cgraphunit.c (cgraph_node::expand_thunk): Make sure to set cfun->tail_call_marked when forcing a tail call. * function.c (assign_parm_setup_reg): Always use a register to load a parameter passed by reference if cfun->tail_call_marked. gcc/testsuite/ChangeLog: * gnat.dg/thunk1.adb: New test. * gnat.dg/thunk1_pkg1.ads: New helper. * gnat.dg/thunk1_pkg2.ads: Likewise. * gnat.dg/thunk1_pkg2.adb: Likewise.
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r--gcc/cgraphunit.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 26d3995..bedb6e2 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -2171,7 +2171,10 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
}
}
else
- gimple_call_set_tail (call, true);
+ {
+ gimple_call_set_tail (call, true);
+ cfun->tail_call_marked = true;
+ }
/* Build return value. */
if (!DECL_BY_REFERENCE (resdecl))
@@ -2184,6 +2187,7 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
else
{
gimple_call_set_tail (call, true);
+ cfun->tail_call_marked = true;
remove_edge (single_succ_edge (bb));
}