diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2020-09-14 17:24:32 +0200 |
---|---|---|
committer | Eric Botcazou <ebotcazou@adacore.com> | 2020-09-14 17:38:39 +0200 |
commit | a7d8dcdf2f3cf9a801e655f2eec3967a3a3ba666 (patch) | |
tree | c8845d0fd0b213f1143e93ca46b864115f920cfb /gcc/function.c | |
parent | 863e8d53eb2940e2c8850e632afe427e164f53cf (diff) | |
download | gcc-a7d8dcdf2f3cf9a801e655f2eec3967a3a3ba666.tar.gz |
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/function.c')
-rw-r--r-- | gcc/function.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/gcc/function.c b/gcc/function.c index de5947937eb..c4c9930d725 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3322,13 +3322,15 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm, else emit_move_insn (parmreg, validated_mem); - /* If we were passed a pointer but the actual value can safely live - in a register, retrieve it and use it directly. */ + /* If we were passed a pointer but the actual value can live in a register, + retrieve it and use it directly. Note that we cannot use nominal_mode, + because it will have been set to Pmode above, we must use the actual mode + of the parameter instead. */ if (data->arg.pass_by_reference && TYPE_MODE (TREE_TYPE (parm)) != BLKmode) { - /* We can't use nominal_mode, because it will have been set to - Pmode above. We must use the actual mode of the parm. */ - if (use_register_for_decl (parm)) + /* Use a stack slot for debugging purposes, except if a tail call is + involved because this would create a dangling reference. */ + if (use_register_for_decl (parm) || cfun->tail_call_marked) { parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm))); mark_user_reg (parmreg); |