OSDN Git Service

* cp-tree.h (struct language_function): Remove temp_name_counter.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 30 Jun 2000 07:16:35 +0000 (07:16 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 30 Jun 2000 07:16:35 +0000 (07:16 +0000)
(temp_name_counter): Remove.
(get_temp_name): Change prototype.
(get_guard): New function.
(get_guard_cond): Likewise.
(set_guard): Likewise.
* cvt.c (build_up_reference): Adjust call to get_temp_name.
* decl.c (expand_static_init): Use get_guard and friends to
implement guard variables.
* decl2.c (get_temp_name): Assume that the variables created are
always static.
(get_sentry): Rename to ...
(get_guard): ... this.  Implement new ABI guard variables.
(get_guard_bits): New function.
(get_guard_cond): Likewise.
(set_guard): Likewise.
(start_static_initialization_or_destruction): Use them.
(do_static_initialization): Replace sentry with guard throughout.
(do_static_destruction): Likewise.
* init.c (create_temporary_var): Add comment.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@34803 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c

index ef87879..4654401 100644 (file)
@@ -1,3 +1,26 @@
+2000-06-30  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.h (struct language_function): Remove temp_name_counter.
+       (temp_name_counter): Remove.
+       (get_temp_name): Change prototype.
+       (get_guard): New function.
+       (get_guard_cond): Likewise.
+       (set_guard): Likewise.
+       * cvt.c (build_up_reference): Adjust call to get_temp_name.
+       * decl.c (expand_static_init): Use get_guard and friends to
+       implement guard variables.
+       * decl2.c (get_temp_name): Assume that the variables created are
+       always static.
+       (get_sentry): Rename to ...
+       (get_guard): ... this.  Implement new ABI guard variables.
+       (get_guard_bits): New function.
+       (get_guard_cond): Likewise.
+       (set_guard): Likewise.
+       (start_static_initialization_or_destruction): Use them.
+       (do_static_initialization): Replace sentry with guard throughout.
+       (do_static_destruction): Likewise.
+       * init.c (create_temporary_var): Add comment.
+       
 2000-06-29  Mark Mitchell  <mark@codesourcery.com>
 
        * cp-tree.h (flag_const_strings): Remove.
index f98c5ea..fb37a3d 100644 (file)
@@ -900,7 +900,6 @@ struct language_function
   int returns_value;
   int returns_null;
   int parms_stored;
-  int temp_name_counter;
   int in_function_try_handler;
   int x_expanding_p;
   int name_declared;
@@ -1004,11 +1003,6 @@ struct language_function
 
 #define vtbls_set_up_p cp_function_chain->vtbls_set_up_p
 
-/* Used to help generate temporary names which are unique within
-   a function.  Reset to 0 by start_function.  */
-
-#define temp_name_counter cp_function_chain->temp_name_counter
-
 /* Non-zero if we should generate RTL for functions that we process.
    When this is zero, we just accumulate tree structure, without
    interacting with the back end.  */
@@ -4075,7 +4069,7 @@ extern tree constructor_name_full         PARAMS ((tree));
 extern tree constructor_name                   PARAMS ((tree));
 extern void setup_vtbl_ptr                     PARAMS ((tree, tree));
 extern void defer_fn                           PARAMS ((tree));
-extern tree get_temp_name                      PARAMS ((tree, int));
+extern tree get_temp_name                      PARAMS ((tree));
 extern void finish_anon_union                  PARAMS ((tree));
 extern tree finish_table                       PARAMS ((tree, tree, tree, int));
 extern void finish_builtin_type                        PARAMS ((tree, const char *,
@@ -4110,6 +4104,9 @@ extern tree handle_class_head                     PARAMS ((tree, tree, tree));
 extern tree lookup_arg_dependent                PARAMS ((tree, tree, tree));
 extern void finish_static_data_member_decl      PARAMS ((tree, tree, tree, int));
 extern tree build_artificial_parm               PARAMS ((tree, tree));
+extern tree get_guard                           PARAMS ((tree));
+extern tree get_guard_cond                      PARAMS ((tree));
+extern tree set_guard                           PARAMS ((tree));
 
 /* in parse.y */
 extern void cp_parse_init                      PARAMS ((void));
index e3e8692..2cbbd59 100644 (file)
@@ -356,7 +356,7 @@ build_up_reference (type, arg, flags)
       /* Create a new temporary variable.  */
       tree targ = arg;
       if (toplevel_bindings_p ())
-       arg = get_temp_name (argtype, 1);
+       arg = get_temp_name (argtype);
       else
        {
          arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype));
index dea9902..ae933ab 100644 (file)
@@ -8572,19 +8572,19 @@ expand_static_init (decl, init)
   else if (! toplevel_bindings_p ())
     {
       /* Emit code to perform this initialization but once.  */
-      tree temp;
       tree if_stmt;
       tree then_clause;
       tree assignment;
-      tree temp_init;
+      tree guard;
+      tree guard_init;
 
       /* Emit code to perform this initialization but once.  This code
         looks like:
 
-           static int temp = 0;
-           if (!temp) {
+           static int guard = 0;
+           if (!guard) {
              // Do initialization.
-            temp = 1;
+            guard = 1;
             // Register variable for destruction at end of program.
           }
 
@@ -8602,14 +8602,13 @@ expand_static_init (decl, init)
          In theory, this process should be thread-safe, too; multiple
         threads should not be able to initialize the variable more
         than once.  We don't yet attempt to ensure thread-safety.  */
-      temp = get_temp_name (integer_type_node, 1);
-      rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
+
+      /* Create the guard variable.  */
+      guard = get_guard (decl);
 
       /* Begin the conditional initialization.  */
       if_stmt = begin_if_stmt ();
-      finish_if_stmt_cond (cp_build_binary_op (EQ_EXPR, temp,
-                                              integer_zero_node),
-                          if_stmt);
+      finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
       then_clause = begin_compound_stmt (/*has_no_scope=*/0);
 
       /* Do the initialization itself.  */
@@ -8631,16 +8630,16 @@ expand_static_init (decl, init)
         the assignment to TEMP into a single expression, ensuring
         that when we call finish_expr_stmt the cleanups will not be
         run until after TEMP is set to 1.  */
-      temp_init = build_modify_expr (temp, NOP_EXPR, integer_one_node);
+      guard_init = set_guard (guard);
       if (assignment)
        {
          assignment = tree_cons (NULL_TREE, assignment,
                                  build_tree_list (NULL_TREE,
-                                                  temp_init));
+                                                  guard_init));
          assignment = build_compound_expr (assignment);
        }
       else
-       assignment = temp_init;
+       assignment = guard_init;
       finish_expr_stmt (assignment);
 
       /* Use atexit to register a function for destroying this static
index f21187e..c172d50 100644 (file)
@@ -62,7 +62,6 @@ typedef struct priority_info_s {
   int destructions_p;
 } *priority_info;
 
-static tree get_sentry PARAMS ((tree));
 static void mark_vtable_entries PARAMS ((tree));
 static void grok_function_init PARAMS ((tree, tree));
 static int finish_vtable_vardecl PARAMS ((tree *, void *));
@@ -95,6 +94,7 @@ static void write_out_vars PARAMS ((tree));
 static void import_export_class        PARAMS ((tree));
 static tree key_method PARAMS ((tree));
 static int compare_options PARAMS ((const PTR, const PTR));
+static tree get_guard_bits PARAMS ((tree));
 
 extern int current_class_depth;
 
@@ -2098,32 +2098,24 @@ defer_fn (fn)
 /* Hand off a unique name which can be used for variable we don't really
    want to know about anyway, for example, the anonymous variables which
    are needed to make references work.  Declare this thing so we can use it.
-   The variable created will be of type TYPE.
-
-   STATICP is nonzero if this variable should be static.  */
+   The variable created will be of type TYPE, and will have internal
+   linkage.  */
 
 tree
-get_temp_name (type, staticp)
+get_temp_name (type)
      tree type;
-     int staticp;
 {
   char buf[sizeof (AUTO_TEMP_FORMAT) + 20];
   tree decl;
   int toplev = toplevel_bindings_p ();
 
-  if (toplev || staticp)
-    {
-      sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++);
-      decl = pushdecl_top_level (build_decl (VAR_DECL, get_identifier (buf), type));
-    }
-  else
-    {
-      sprintf (buf, AUTO_TEMP_FORMAT, temp_name_counter++);
-      decl = pushdecl (build_decl (VAR_DECL, get_identifier (buf), type));
-    }
-  TREE_USED (decl) = 1;
-  TREE_STATIC (decl) = staticp;
+  sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++);
+  decl = build_decl (VAR_DECL, get_identifier (buf), type);
   DECL_ARTIFICIAL (decl) = 1;
+  TREE_USED (decl) = 1;
+  TREE_STATIC (decl) = 1;
+  
+  decl = pushdecl_top_level (decl);
 
   /* If this is a local variable, then lay out its rtl now.
      Otherwise, callers of this function are responsible for dealing
@@ -2866,37 +2858,111 @@ build_cleanup (decl)
   return temp;
 }
 
-/* Returns the initialization guard variable for the non-local
-   variable DECL.  */
+/* Returns the initialization guard variable for the variable DECL,
+   which has static storage duration.  */
 
-static tree
-get_sentry (decl)
+tree
+get_guard (decl)
      tree decl;
 {
   tree sname;
-  tree sentry;
+  tree guard;
+
+  /* For a local variable, under the old ABI, we do not try to get a
+     unique mangled name for the DECL.  */
+  if (!flag_new_abi && !DECL_NAMESPACE_SCOPE_P (decl))
+    {
+      guard = get_temp_name (integer_type_node);
+      rest_of_decl_compilation (guard, NULL_PTR, 0, 0);
+    }
 
   if (!flag_new_abi)
+    /* For struct X foo __attribute__((weak)), there is a counter
+       __snfoo. Since base is already an assembler name, sname should
+       be globally unique */
     sname = get_id_2 ("__sn", DECL_ASSEMBLER_NAME (decl));
   else
     sname = mangle_guard_variable (decl);
 
-  /* For struct X foo __attribute__((weak)), there is a counter
-     __snfoo. Since base is already an assembler name, sname should
-     be globally unique */
-  sentry = IDENTIFIER_GLOBAL_VALUE (sname);
-  if (! sentry)
+  guard = IDENTIFIER_GLOBAL_VALUE (sname);
+  if (! guard)
     {
-      sentry = build_decl (VAR_DECL, sname, integer_type_node);
-      TREE_PUBLIC (sentry) = 1;
-      DECL_ARTIFICIAL (sentry) = 1;
-      TREE_STATIC (sentry) = 1;
-      TREE_USED (sentry) = 1;
-      DECL_COMMON (sentry) = 1;
-      pushdecl_top_level (sentry);
-      cp_finish_decl (sentry, NULL_TREE, NULL_TREE, 0);
+      tree guard_type;
+
+      /* Under the new ABI, we use a type that is big enough to
+        contain a mutex as well as an integer counter.  */
+      if (flag_new_abi)
+       guard_type = long_long_integer_type_node;
+      else
+       guard_type = integer_type_node;
+
+      guard = build_decl (VAR_DECL, sname, guard_type);
+      TREE_PUBLIC (guard) = 1;
+      DECL_ARTIFICIAL (guard) = 1;
+      TREE_STATIC (guard) = 1;
+      TREE_USED (guard) = 1;
+      DECL_COMMON (guard) = 1;
+      pushdecl_top_level (guard);
+      cp_finish_decl (guard, NULL_TREE, NULL_TREE, 0);
     }
-  return sentry;
+  return guard;
+}
+
+/* Return those bits of the GUARD variable that should be set when the
+   guarded entity is actually initialized.  */
+
+static tree
+get_guard_bits (guard)
+     tree guard;
+{
+  if (!flag_new_abi)
+    return guard;
+
+  /* Under the new ABI, we only set the first byte of the guard,
+     in order to leave room for a mutex in the high-order bits.  */
+  guard = build1 (ADDR_EXPR, 
+                 build_pointer_type (TREE_TYPE (guard)),
+                 guard);
+  guard = build1 (NOP_EXPR, 
+                 build_pointer_type (char_type_node), 
+                 guard);
+  guard = build1 (INDIRECT_REF, char_type_node, guard);
+
+  return guard;
+}
+
+/* Return an expression which determines whether or not the GUARD
+   variable has already been initialized.  */
+
+tree
+get_guard_cond (guard)
+     tree guard;
+{
+  tree guard_value;
+
+  /* Check to see if the GUARD is zero.  */
+  guard = get_guard_bits (guard);
+  guard_value = integer_zero_node;
+  if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
+    guard_value = convert (TREE_TYPE (guard), guard_value);
+  return cp_build_binary_op (EQ_EXPR, guard, guard_value);
+}
+
+/* Return an expression which sets the GUARD variable, indicating that
+   the variable being guarded has been initialized.  */
+
+tree
+set_guard (guard)
+     tree guard;
+{
+  tree guard_init;
+
+  /* Set the GUARD to one.  */
+  guard = get_guard_bits (guard);
+  guard_init = integer_one_node;
+  if (!same_type_p (TREE_TYPE (guard_init), TREE_TYPE (guard)))
+    guard_init = convert (TREE_TYPE (guard), guard_init);
+  return build_modify_expr (guard, NOP_EXPR, guard_init);
 }
 
 /* Start the process of running a particular set of global constructors
@@ -3201,9 +3267,10 @@ start_static_initialization_or_destruction (decl, initp)
      tree decl;
      int initp;
 {
-  tree sentry_if_stmt = NULL_TREE;
+  tree guard_if_stmt = NULL_TREE;
   int priority;
   tree cond;
+  tree guard;
   tree init_cond;
   priority_info pi;
 
@@ -3247,7 +3314,7 @@ start_static_initialization_or_destruction (decl, initp)
   
   /* Conditionalize this initialization on being in the right priority
      and being initializing/finalizing appropriately.  */
-  sentry_if_stmt = begin_if_stmt ();
+  guard_if_stmt = begin_if_stmt ();
   cond = cp_build_binary_op (EQ_EXPR,
                             priority_decl,
                             build_int_2 (priority, 0));
@@ -3257,7 +3324,9 @@ start_static_initialization_or_destruction (decl, initp)
                                  init_cond);
   cond = cp_build_binary_op (TRUTH_ANDIF_EXPR, cond, init_cond);
 
-  /* We need a sentry if this is an object with external linkage that
+  /* Assume we don't need a guard.  */
+  guard = NULL_TREE;
+  /* We need a guard if this is an object with external linkage that
      might be initialized in more than one place.  (For example, a
      static data member of a template, when the data member requires
      construction.)  */
@@ -3265,47 +3334,60 @@ start_static_initialization_or_destruction (decl, initp)
                             || DECL_ONE_ONLY (decl)
                             || DECL_WEAK (decl)))
     {
-      tree sentry;
-      tree sentry_cond;
+      tree guard_cond;
 
-      sentry = get_sentry (decl);
+      guard = get_guard (decl);
 
-      /* We do initializations only if the SENTRY is zero, i.e., if we
-        are the first to initialize the variable.  We do destructions
-        only if the SENTRY is one, i.e., if we are the last to
-        destroy the variable.  */
-      if (initp)
-       sentry_cond 
+      /* When using __cxa_atexit, we just check the GUARD as we would
+        for a local static.  */
+      if (flag_use_cxa_atexit)
+       {
+         /* When using __cxa_atexit, we never try to destroy
+            anything from a static destructor.  */
+         my_friendly_assert (initp, 20000629);
+         guard_cond = get_guard_cond (guard);
+       }
+      /* Under the old ABI, e do initializations only if the GUARD is
+        zero, i.e., if we are the first to initialize the variable.
+        We do destructions only if the GUARD is one, i.e., if we are
+        the last to destroy the variable.  */
+      else if (initp)
+       guard_cond 
          = cp_build_binary_op (EQ_EXPR,
                                build_unary_op (PREINCREMENT_EXPR,
-                                               sentry,
+                                               guard,
                                                /*noconvert=*/1),
                                integer_one_node);
       else
-       sentry_cond 
+       guard_cond 
          = cp_build_binary_op (EQ_EXPR,
                                build_unary_op (PREDECREMENT_EXPR,
-                                               sentry,
+                                               guard,
                                                /*noconvert=*/1),
                                integer_zero_node);
 
-      cond = cp_build_binary_op (TRUTH_ANDIF_EXPR, cond, sentry_cond);
+      cond = cp_build_binary_op (TRUTH_ANDIF_EXPR, cond, guard_cond);
     }
 
-  finish_if_stmt_cond (cond, sentry_if_stmt);
+  finish_if_stmt_cond (cond, guard_if_stmt);
+
+  /* Under the new ABI, we have not already set the GUARD, so we must
+     do so now.  */
+  if (guard && initp && flag_new_abi)
+    finish_expr_stmt (set_guard (guard));
 
-  return sentry_if_stmt;
+  return guard_if_stmt;
 }
 
 /* We've just finished generating code to do an initialization or
-   finalization.  SENTRY_IF_STMT is the if-statement we used to guard
+   finalization.  GUARD_IF_STMT is the if-statement we used to guard
    the initialization.  */
 
 static void
-finish_static_initialization_or_destruction (sentry_if_stmt)
-     tree sentry_if_stmt;
+finish_static_initialization_or_destruction (guard_if_stmt)
+     tree guard_if_stmt;
 {
-  finish_then_clause (sentry_if_stmt);
+  finish_then_clause (guard_if_stmt);
   finish_if_stmt ();
 
   /* Now that we're done with DECL we don't need to pretend to be a
@@ -3316,7 +3398,7 @@ finish_static_initialization_or_destruction (sentry_if_stmt)
 
 /* Generate code to do the static initialization of DECL.  The
    initialization is INIT.  If DECL may be initialized more than once
-   in different object files, SENTRY is the guard variable to 
+   in different object files, GUARD is the guard variable to 
    check.  PRIORITY is the priority for the initialization.  */
 
 static void
@@ -3325,10 +3407,10 @@ do_static_initialization (decl, init)
      tree init;
 {
   tree expr;
-  tree sentry_if_stmt;
+  tree guard_if_stmt;
 
   /* Set up for the initialization.  */
-  sentry_if_stmt
+  guard_if_stmt
     = start_static_initialization_or_destruction (decl,
                                                  /*initp=*/1);
   
@@ -3353,11 +3435,11 @@ do_static_initialization (decl, init)
     register_dtor_fn (decl);
 
   /* Finsh up.  */
-  finish_static_initialization_or_destruction (sentry_if_stmt);
+  finish_static_initialization_or_destruction (guard_if_stmt);
 }
 
 /* Generate code to do the static destruction of DECL.  If DECL may be
-   initialized more than once in different object files, SENTRY is the
+   initialized more than once in different object files, GUARD is the
    guard variable to check.  PRIORITY is the priority for the
    destruction.  */
 
@@ -3365,7 +3447,7 @@ static void
 do_static_destruction (decl)
      tree decl;
 {
-  tree sentry_if_stmt;
+  tree guard_if_stmt;
 
   /* If we're using __cxa_atexit, then destructors are registered
      immediately after objects are initialized.  */
@@ -3376,10 +3458,10 @@ do_static_destruction (decl)
     return;
 
   /* Actually do the destruction.  */
-  sentry_if_stmt = start_static_initialization_or_destruction (decl,
+  guard_if_stmt = start_static_initialization_or_destruction (decl,
                                                               /*initp=*/0);
   finish_expr_stmt (build_cleanup (decl));
-  finish_static_initialization_or_destruction (sentry_if_stmt);
+  finish_static_initialization_or_destruction (guard_if_stmt);
 }
 
 /* VARS is a list of variables with static storage duration which may
index a78da11..089559f 100644 (file)
@@ -2729,6 +2729,8 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
     return cp_convert (void_type_node, body);
 }
 
+/* Create an unnamed variable of the indicated TYPE.  */ 
+
 tree
 create_temporary_var (type)
      tree type;