]> gcc.gnu.org Git - gcc.git/commitdiff
cp-tree.h (cp_tree_index): Add CPTI_DSO_HANDLE.
authorMark Mitchell <mark@codesourcery.com>
Fri, 17 Dec 1999 07:40:08 +0000 (07:40 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 17 Dec 1999 07:40:08 +0000 (07:40 +0000)
* cp-tree.h (cp_tree_index): Add CPTI_DSO_HANDLE.
(dso_handle_node): New macro.
(flag_use_cxa_atexit): New variable.
(declare_global_var): New function.
(start_anon_func): Remove declaration.
(end_anon_func): Likewise.
* decl.c (get_atexit_node): New function, split out from
destroy_local_static.  Handle flag_use_cxa_atexit.
(get_dso_handle_node): Likewise.
(start_cleanup_fn): Renamed from start_anon_func.  Moved here from
except.c.  Handle flag_use_cxa_atexit.
(end_cleanup_fn): Renamed from end_anon_func.  Moved here from
except.c.
(declare_global_var): New variable.
(destroy_local_static): Handle flag_use_cxa_atexit.
* decl2.c (flag_use_cxa_atexit): New variable.
(lang_f_options): Likewise.
* except.c (start_anon_func): Remove.
(end_anon_func): Liekwise.
* lang-options.h: Add -fuse-cxa-atexit and -fno-use-cxa-atexit.
* rtti.c (get_tinfo_var): Use declare_global_var.

From-SVN: r30990

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/except.c
gcc/cp/lang-options.h
gcc/cp/rtti.c

index 2fe8bd30b9be034635bd1d49b35c0f62ab33ad9e..73cfd67b319fb3ee6933071a26ec90f33a64458a 100644 (file)
@@ -1,3 +1,27 @@
+1999-12-16  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.h (cp_tree_index): Add CPTI_DSO_HANDLE.
+       (dso_handle_node): New macro.
+       (flag_use_cxa_atexit): New variable.
+       (declare_global_var): New function.
+       (start_anon_func): Remove declaration.
+       (end_anon_func): Likewise.
+       * decl.c (get_atexit_node): New function, split out from
+       destroy_local_static.  Handle flag_use_cxa_atexit.
+       (get_dso_handle_node): Likewise.
+       (start_cleanup_fn): Renamed from start_anon_func.  Moved here from
+       except.c.  Handle flag_use_cxa_atexit.
+       (end_cleanup_fn): Renamed from end_anon_func.  Moved here from
+       except.c.
+       (declare_global_var): New variable.
+       (destroy_local_static): Handle flag_use_cxa_atexit.
+       * decl2.c (flag_use_cxa_atexit): New variable.
+       (lang_f_options): Likewise.
+       * except.c (start_anon_func): Remove.
+       (end_anon_func): Liekwise.
+       * lang-options.h: Add -fuse-cxa-atexit and -fno-use-cxa-atexit.
+       * rtti.c (get_tinfo_var): Use declare_global_var.
+
 1999-12-16  Mark Mitchell  <mark@codesourcery.com>
 
        * class.c (check_field_decls): Don't return a value.
index 0fefc7d7fcd089d93658a5e9461a16c8483db966..6b22ee9e573fe216b05dcc1454f5cf14e28fe05b 100644 (file)
@@ -483,6 +483,7 @@ enum cp_tree_index
     CPTI_MINUS_ONE,
     CPTI_TERMINATE,
     CPTI_ATEXIT,
+    CPTI_DSO_HANDLE,
 
     CPTI_MAX
 };
@@ -574,9 +575,12 @@ extern tree cp_global_trees[CPTI_MAX];
 /* The declaration for `std::terminate'.  */
 #define terminate_node                  cp_global_trees[CPTI_TERMINATE]
 
-/* The declaration for `std::atexit'.  */
+/* A pointer to `std::atexit'.  */
 #define atexit_node                     cp_global_trees[CPTI_ATEXIT]
 
+/* A pointer to `__dso_handle'.  */
+#define dso_handle_node                 cp_global_trees[CPTI_DSO_HANDLE]
+
 /* The type of a destructor.  */
 #define cleanup_type                    cp_global_trees[CPTI_CLEANUP_TYPE]
 
@@ -3128,6 +3132,11 @@ extern int flag_weak;
 
 extern int flag_new_abi;
 
+/* Nonzero to use __cxa_atexit, rather than atexit, to register
+   destructors for local statics and global objects.  */
+
+extern int flag_use_cxa_atexit;
+
 /* Nonzero to not ignore namespace std. */
 
 extern int flag_honor_std;
@@ -3564,6 +3573,7 @@ extern tree build_target_expr_with_type         PROTO((tree, tree));
 extern void make_rtl_for_local_static           PROTO((tree));
 extern int local_variable_p                     PROTO((tree));
 extern int nonstatic_local_decl_p               PROTO((tree));
+extern tree declare_global_var                  PROTO((tree, tree));
 
 /* in decl2.c */
 extern void init_decl2                         PROTO((void));
@@ -3659,8 +3669,6 @@ extern void expand_builtin_throw          PROTO((void));
 extern tree expand_start_eh_spec               PROTO((void));
 extern void expand_end_eh_spec                 PROTO((tree, tree));
 extern void expand_exception_blocks            PROTO((void));
-extern tree start_anon_func                    PROTO((void));
-extern void end_anon_func                      PROTO((void));
 extern tree build_throw                                PROTO((tree));
 extern void mark_all_runtime_matches            PROTO((void));
 
index b08f4db1725c3225f66abd6fadae1b9e2dfa155d..6b240f9e246a138150688987764e21cd074a9543 100644 (file)
@@ -175,6 +175,10 @@ static void destroy_local_var PROTO((tree));
 static void finish_constructor_body PROTO((void));
 static void finish_destructor_body PROTO((void));
 static tree create_array_type_for_decl PROTO((tree, tree, tree));
+static tree get_atexit_node PROTO((void));
+static tree get_dso_handle_node PROTO((void));
+static tree start_cleanup_fn PROTO((void));
+static void end_cleanup_fn PROTO((void));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
 static void indent PROTO((void));
@@ -7856,6 +7860,184 @@ finish_decl (decl, init, asmspec_tree)
   cp_finish_decl (decl, init, asmspec_tree, 0);
 }
 
+/* Returns a declaration for a VAR_DECL as if:
+
+     extern "C" TYPE NAME;
+
+   had been seen.  Used to create compiler-generated global
+   variables.  */
+
+tree
+declare_global_var (name, type)
+     tree name;
+     tree type;
+{
+  tree decl;
+
+  push_to_top_level ();
+  decl = build_decl (VAR_DECL, name, type);
+  TREE_PUBLIC (decl) = 1;
+  DECL_EXTERNAL (decl) = 1;
+  DECL_ARTIFICIAL (decl) = 1;
+  pushdecl (decl);
+  cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0);
+  pop_from_top_level ();
+
+  return decl;
+}
+
+/* Returns a pointer to the `atexit' function.  Note that if
+   FLAG_USE_CXA_ATEXIT is non-zero, then this will actually be the new
+   `__cxa_atexit' function specified in the IA64 C++ ABI.  */
+
+static tree
+get_atexit_node ()
+{
+  tree atexit_fndecl;
+  tree arg_types;
+  tree fn_type;
+  tree fn_ptr_type;
+  const char *name;
+
+  if (atexit_node)
+    return atexit_node;
+
+  if (flag_use_cxa_atexit)
+    {
+      /* The declaration for `__cxa_atexit' is:
+
+          int __cxa_atexit (void (*)(void *), void *, void *)
+
+        We build up the argument types and then then function type
+        itself.  */
+      
+      /* First, build the pointer-to-function type for the first
+        argument.  */
+      arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+      fn_type = build_function_type (void_type_node, arg_types);
+      fn_ptr_type = build_pointer_type (fn_type);
+      /* Then, build the rest of the argument types.  */
+      arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+      arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
+      arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types);
+      /* And the final __cxa_atexit type.  */
+      fn_type = build_function_type (integer_type_node, arg_types);
+      fn_ptr_type = build_pointer_type (fn_type);
+      name = "__cxa_atexit";
+    }
+  else
+    {
+      /* The declaration for `atexit' is:
+         
+           int atexit (void (*)());
+
+        We build up the argument types and then then function type
+        itself.  */
+      fn_type = build_function_type (void_type_node, void_list_node);
+      fn_ptr_type = build_pointer_type (fn_type);
+      arg_types = tree_cons (NULL_TREE, fn_ptr_type, void_list_node);
+      /* Build the final atexit type.  */
+      fn_type = build_function_type (integer_type_node, arg_types);
+      name = "atexit";
+    }
+
+  /* Now, build the function declaration.  */
+  push_lang_context (lang_name_c);
+  atexit_fndecl = define_function (name, fn_type, /*pfn=*/0, NULL_PTR);
+  mark_used (atexit_fndecl);
+  pop_lang_context ();
+  atexit_node = default_conversion (atexit_fndecl);
+
+  return atexit_node;
+}
+
+/* Returns the __dso_handle VAR_DECL.  */
+
+static tree
+get_dso_handle_node ()
+{
+  if (dso_handle_node)
+    return dso_handle_node;
+
+  /* Declare the variable.  */
+  dso_handle_node = declare_global_var (get_identifier ("__dso_handle"),
+                                       ptr_type_node);
+
+  return dso_handle_node;
+}
+
+/* Begin a new function with internal linkage whose job will be simply
+   to destroy some particular variable.  */
+
+static tree
+start_cleanup_fn ()
+{
+  static int counter = 0;
+  int old_interface_unknown = interface_unknown;
+  char name[32];
+  tree parmtypes;
+  tree fntype;
+  tree fndecl;
+
+  push_to_top_level ();
+
+  /* No need to mangle this.  */
+  push_lang_context (lang_name_c);
+
+  interface_unknown = 1;
+
+  /* Build the parameter-types.  */
+  parmtypes = void_list_node;
+  /* Functions passed to __cxa_atexit take an additional parameter.
+     We'll just ignore it.  After we implement the new calling
+     convention for destructors, we can eliminate the use of
+     additional cleanup functions entirely in the -fnew-abi case.  */
+  if (flag_use_cxa_atexit)
+    parmtypes = tree_cons (NULL_TREE, ptr_type_node, parmtypes);
+  /* Build the function type itself.  */
+  fntype = build_function_type (void_type_node, parmtypes);
+  /* Build the name of the function.  */
+  sprintf (name, "__tcf_%d", counter++);
+  /* Build the function declaration.  */
+  fndecl = build_lang_decl (FUNCTION_DECL, get_identifier (name), fntype);
+  /* It's a function with internal linkage, generated by the
+     compiler.  */
+  TREE_PUBLIC (fndecl) = 0;
+  DECL_ARTIFICIAL (fndecl) = 1;
+  /* Build the parameter.  */
+  if (flag_use_cxa_atexit)
+    {
+      tree parmdecl;
+
+      parmdecl = build_decl (PARM_DECL, NULL_TREE, ptr_type_node);
+      DECL_CONTEXT (parmdecl) = fndecl;
+      DECL_ARG_TYPE (parmdecl) = ptr_type_node;
+      TREE_USED (parmdecl) = 1;
+      DECL_ARGUMENTS (fndecl) = parmdecl;
+    }
+
+  start_function (/*specs=*/NULL_TREE, fndecl, NULL_TREE, SF_PRE_PARSED);
+  do_pushlevel ();
+
+  interface_unknown = old_interface_unknown;
+
+  pop_lang_context ();
+
+  return current_function_decl;
+}
+
+/* Finish the cleanup function begun by start_cleanup_fn.  */
+
+static void
+end_cleanup_fn ()
+{
+  do_poplevel ();
+
+  expand_body (finish_function (lineno, 0));
+
+  pop_from_top_level ();
+}
+
 /* Generate code to handle the destruction of the function-scoped
    static variable DECL.  */
 
@@ -7863,40 +8045,20 @@ static void
 destroy_local_static (decl)
      tree decl;
 {
-  tree cleanup, fcall;
+  tree cleanup;
   tree compound_stmt;
-  int saved_flag_access_control;
+  tree args;
+  tree fcall;
 
-  if (atexit_node == 0)
-    {
-      tree atexit_fndecl, PFV, pfvlist;
-
-      PFV = build_pointer_type (build_function_type
-                               (void_type_node, void_list_node));
-
-      pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
+  int saved_flag_access_control;
 
-      push_lang_context (lang_name_c);
-      /* Note that we do not call pushdecl for this function;
-        there's no reason that this declaration should be
-        accessible to anyone.  */
-      atexit_fndecl
-       = define_function ("atexit",
-                          build_function_type (void_type_node,
-                                               pfvlist),
-                          /*pfn=*/0, NULL_PTR);
-      mark_used (atexit_fndecl);
-      atexit_node = default_conversion (atexit_fndecl);
-      pop_lang_context ();
-    }
-             
   /* Call build_cleanup before we enter the anonymous function so that
      any access checks will be done relative to the current scope,
      rather than the scope of the anonymous function.  */
   build_cleanup (decl);
 
   /* Now start the function.  */
-  cleanup = start_anon_func ();
+  cleanup = start_cleanup_fn ();
 
   /* Now, recompute the cleanup.  It may contain SAVE_EXPRs that refer
      to the original function, rather than the anonymous one.  That
@@ -7911,16 +8073,20 @@ destroy_local_static (decl)
   compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
   finish_expr_stmt (fcall);
   finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
-  end_anon_func ();
+  end_cleanup_fn ();
 
   /* Call atexit with the cleanup function.  */
   mark_addressable (cleanup);
   cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
-  fcall = build_function_call (atexit_node,
-                              tree_cons (NULL_TREE, 
-                                         cleanup, 
-                                         NULL_TREE));
-  finish_expr_stmt (fcall);
+  if (flag_use_cxa_atexit)
+    {
+      args = tree_cons (NULL_TREE, get_dso_handle_node (), NULL_TREE);
+      args = tree_cons (NULL_TREE, null_pointer_node, args);
+      args = tree_cons (NULL_TREE, cleanup, args);
+    }
+  else
+    args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
+  finish_expr_stmt (build_function_call (get_atexit_node (), args));
 }
 
 void
index 937a1647cdb1a79d5a0bd8365ca7880fa6b31caa..7ed8ab0415304911f43095628d7edd43c8bbddcb 100644 (file)
@@ -441,6 +441,11 @@ int flag_weak = 1;
 
 int flag_new_abi;
 
+/* Nonzero to use __cxa_atexit, rather than atexit, to register
+   destructors for local statics and global objects.  */
+
+int flag_use_cxa_atexit;
+
 /* Nonzero to not ignore namespace std. */
 
 int flag_honor_std;
@@ -535,6 +540,7 @@ lang_f_options[] =
   {"squangle", &flag_do_squangling, 1},
   {"stats", &flag_detailed_statistics, 1},
   {"strict-prototype", &flag_strict_prototype, 1},
+  {"use-cxa-atexit", &flag_use_cxa_atexit, 1},
   {"vtable-gc", &flag_vtable_gc, 1},
   {"vtable-thunks", &flag_vtable_thunks, 1},
   {"weak", &flag_weak, 1},
index 7e41d2e9dea7b8b30bc13cba30bcee4d4de29c26..1dd167cc7adb35063a66cccb7cfc37005c63fb78 100644 (file)
@@ -681,49 +681,6 @@ expand_exception_blocks ()
     }
 }
 
-tree
-start_anon_func ()
-{
-  static int counter = 0;
-  int old_interface_unknown = interface_unknown;
-  char name[32];
-  tree params;
-  tree t;
-
-  push_to_top_level ();
-
-  /* No need to mangle this.  */
-  push_lang_context (lang_name_c);
-
-  interface_unknown = 1;
-
-  params = void_list_node;
-  /* tcf stands for throw clean function.  */
-  sprintf (name, "__tcf_%d", counter++);
-  t = make_call_declarator (get_identifier (name), params, NULL_TREE,
-                           NULL_TREE);
-  start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
-                                 void_list_node),
-                 t, NULL_TREE, SF_DEFAULT);
-  do_pushlevel ();
-
-  interface_unknown = old_interface_unknown;
-
-  pop_lang_context ();
-
-  return current_function_decl;
-}
-
-void
-end_anon_func ()
-{
-  do_poplevel ();
-
-  expand_body (finish_function (lineno, 0));
-
-  pop_from_top_level ();
-}
-
 /* Return a pointer to a buffer for an exception object of type TYPE.  */
 
 static tree
index 4b743c0092b5052e2dfddf6994676330d003c33c..779cbcd643b5b729c4fa4a254cea49b87b361695 100644 (file)
@@ -98,6 +98,8 @@ DEFINE_LANG_NAME ("C++")
   { "-ftemplate-depth-", "Specify maximum template instantiation depth"},
   { "-fthis-is-variable", "Make 'this' not be type '* const'"  },
   { "-fno-this-is-variable", "" },
+  { "-fuse-cxa-atexit", "Use __cxa_atexit to register destructors." },
+  { "-fno-use-cxa-atexit", "" },
   { "-fvtable-gc", "Discard unused virtual functions" },
   { "-fno-vtable-gc", "" },
   { "-fvtable-thunks", "Implement vtables using thunks" },
index 6776d11670c7282d979bc923c7ab084a9542b103..5c8da916fbbbf793777d6f90f678b86bb87a0fc4 100644 (file)
@@ -308,7 +308,7 @@ get_tinfo_var (type)
      tree type;
 {
   tree tname = build_overload_with_type (get_identifier ("__ti"), type);
-  tree tdecl, arrtype;
+  tree arrtype;
   int size;
 
   if (IDENTIFIER_GLOBAL_VALUE (tname))
@@ -342,16 +342,7 @@ get_tinfo_var (type)
     (unsigned_char_type_node,
      build_index_type (size_int (size / BITS_PER_UNIT - 1)));
 
-  tdecl = build_decl (VAR_DECL, tname, arrtype);
-  TREE_PUBLIC (tdecl) = 1;
-  DECL_EXTERNAL (tdecl) = 1;
-  DECL_ARTIFICIAL (tdecl) = 1;
-  push_to_top_level ();
-  pushdecl (tdecl);
-  cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0);
-  pop_from_top_level ();
-
-  return tdecl;
+  return declare_global_var (tname, arrtype);
 }
 
 /* Returns the decl for a function which will return a type_info node for
This page took 0.099807 seconds and 5 git commands to generate.