From a7d8dcdf2f3cf9a801e655f2eec3967a3a3ba666 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 14 Sep 2020 17:24:32 +0200 Subject: [PATCH] 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. --- gcc/cgraphunit.c | 6 +++++- gcc/function.c | 12 +++++++----- gcc/testsuite/gnat.dg/thunk1.adb | 9 +++++++++ gcc/testsuite/gnat.dg/thunk1_pkg1.ads | 7 +++++++ gcc/testsuite/gnat.dg/thunk1_pkg2.adb | 10 ++++++++++ gcc/testsuite/gnat.dg/thunk1_pkg2.ads | 14 ++++++++++++++ 6 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/thunk1.adb create mode 100644 gcc/testsuite/gnat.dg/thunk1_pkg1.ads create mode 100644 gcc/testsuite/gnat.dg/thunk1_pkg2.adb create mode 100644 gcc/testsuite/gnat.dg/thunk1_pkg2.ads diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 26d3995a0c0..bedb6e2eea1 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)); } 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); diff --git a/gcc/testsuite/gnat.dg/thunk1.adb b/gcc/testsuite/gnat.dg/thunk1.adb new file mode 100644 index 00000000000..278e023bbbc --- /dev/null +++ b/gcc/testsuite/gnat.dg/thunk1.adb @@ -0,0 +1,9 @@ +-- { dg-do run } + +with Thunk1_Pkg1; use Thunk1_Pkg1; + +procedure Thunk1 is + D: Derived; +begin + D.Op ("Message"); +end; diff --git a/gcc/testsuite/gnat.dg/thunk1_pkg1.ads b/gcc/testsuite/gnat.dg/thunk1_pkg1.ads new file mode 100644 index 00000000000..edb3eac04b3 --- /dev/null +++ b/gcc/testsuite/gnat.dg/thunk1_pkg1.ads @@ -0,0 +1,7 @@ +with Thunk1_Pkg2; use Thunk1_Pkg2; + +package Thunk1_Pkg1 is + + type Derived is new Ext with null record; + +end Thunk1_Pkg1; diff --git a/gcc/testsuite/gnat.dg/thunk1_pkg2.adb b/gcc/testsuite/gnat.dg/thunk1_pkg2.adb new file mode 100644 index 00000000000..71ad45d19a5 --- /dev/null +++ b/gcc/testsuite/gnat.dg/thunk1_pkg2.adb @@ -0,0 +1,10 @@ +package body Thunk1_Pkg2 is + + procedure Op (This : in out Ext; S : String) is + begin + if S /= "Message" then + raise Program_Error; + end if; + end; + +end Thunk1_Pkg2; diff --git a/gcc/testsuite/gnat.dg/thunk1_pkg2.ads b/gcc/testsuite/gnat.dg/thunk1_pkg2.ads new file mode 100644 index 00000000000..82a48d500aa --- /dev/null +++ b/gcc/testsuite/gnat.dg/thunk1_pkg2.ads @@ -0,0 +1,14 @@ +package Thunk1_Pkg2 is + + type Root is tagged record + I : Integer; + end record; + + type Iface is interface; + procedure Op (This : in out Iface; S : String) is abstract; + + type Ext is new Root and Iface with null record; + + procedure Op (This : in out Ext; S : String); + +end Thunk1_Pkg2; -- 2.30.2