Since cfun is already a macro in most of the compiler, we redefine it to point
to a second variable, to avoid having to support C++ objects as GC roots.
However we keep the existing function * global for internal use as a gc root.
It is unfortunate the two globals need to stay in sync, but there is only a
couple of places that update it, and this seems much easier than getting
gengtype to properly handle objects as roots and in pch generation and use.

bootstrapped and regtested on x86_64-linux-gnu, ok?

Trev

gcc/cp/ChangeLog:

        * module.cc (module_state::read_cluster): Set cfun_poison as well as
        cfun.

gcc/ChangeLog:

        * function.c (cfun_poison): New global.
        (set_cfun): Set cfun_poison.
        (allocate_struct_function): Likewise.
        * function.h (cfun_poison): New declaration.
        (cfun): Adjust.
---
 gcc/cp/module.cc | 2 ++
 gcc/function.c   | 4 ++++
 gcc/function.h   | 4 +++-
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 72f32487e51..2f1126211e6 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -14868,6 +14868,8 @@ module_state::read_cluster (unsigned snum)
      redesigning that API right now.  */
 #undef cfun
   cfun = old_cfun;
+  cfun_poison = old_cfun;
+  cfun_poison = old_cfun;
   current_function_decl = old_cfd;
   comparing_dependent_aliases--;
 
diff --git a/gcc/function.c b/gcc/function.c
index 00b2fe70c7d..87e8bc86166 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -84,6 +84,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "function-abi.h"
 #include "value-range.h"
 #include "gimple-range.h"
+#include "poison.h"
 
 /* So we can assign to cfun in this file.  */
 #undef cfun
@@ -118,6 +119,7 @@ struct machine_function * (*init_machine_status) (void);
 
 /* The currently compiled function.  */
 struct function *cfun = 0;
+poisonable<function *> cfun_poison (0);
 
 /* These hashes record the prologue and epilogue insns.  */
 
@@ -4715,6 +4717,7 @@ set_cfun (struct function *new_cfun, bool force)
   if (cfun != new_cfun || force)
     {
       cfun = new_cfun;
+      cfun_poison = new_cfun;
       invoke_set_current_function_hook (new_cfun ? new_cfun->decl : NULL_TREE);
       redirect_edge_var_map_empty ();
     }
@@ -4797,6 +4800,7 @@ allocate_struct_function (tree fndecl, bool abstract_p)
   tree fntype = fndecl ? TREE_TYPE (fndecl) : NULL_TREE;
 
   cfun = ggc_cleared_alloc<function> ();
+  cfun_poison = cfun;
 
   init_eh_for_function ();
 
diff --git a/gcc/function.h b/gcc/function.h
index 0db51775e7c..82f7510bdc3 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_FUNCTION_H
 #define GCC_FUNCTION_H
 
+template<typename T> class poisonable;
 
 /* Stack of pending (incomplete) sequences saved by `start_sequence'.
    Each element describes one pending sequence.
@@ -459,11 +460,12 @@ void record_dynamic_alloc (tree decl_or_exp);
 
 /* The function currently being compiled.  */
 extern GTY(()) struct function *cfun;
+extern poisonable<function *> cfun_poison;
 
 /* In order to ensure that cfun is not set directly, we redefine it so
    that it is not an lvalue.  Rather than assign to cfun, use
    push_cfun or set_cfun.  */
-#define cfun (cfun + 0)
+#define cfun (cfun_poison + 0)
 
 /* Nonzero if we've already converted virtual regs to hard regs.  */
 extern int virtuals_instantiated;
-- 
2.20.1

Reply via email to