This patch to the Go frontend marks global variables whose address is
taken.  To implement this, change the backend to use flag bits for
variables.  This fixes GCC PR 100537.  Bootstrapped and ran Go
testsuite on x86_64-pc-linux-gnu.  Committed to mainline.

Ian

        PR go/100537
        * go-gcc.cc (class Gcc_backend): Update methods that create
        variables to take a flags parameter.
18c7d35682baa62e1c3bee22a909d3e95ab08a12
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 5d9dbb5d068..41f309e7294 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -415,47 +415,46 @@ class Gcc_backend : public Backend
   global_variable(const std::string& var_name,
                  const std::string& asm_name,
                  Btype* btype,
-                 bool is_external,
-                 bool is_hidden,
-                 bool in_unique_section,
+                 unsigned int flags,
                  Location location);
 
   void
   global_variable_set_init(Bvariable*, Bexpression*);
 
   Bvariable*
-  local_variable(Bfunction*, const std::string&, Btype*, Bvariable*, bool,
-                Location);
+  local_variable(Bfunction*, const std::string&, Btype*, Bvariable*,
+                unsigned int, Location);
 
   Bvariable*
-  parameter_variable(Bfunction*, const std::string&, Btype*, bool,
+  parameter_variable(Bfunction*, const std::string&, Btype*, unsigned int,
                     Location);
 
   Bvariable*
-  static_chain_variable(Bfunction*, const std::string&, Btype*, Location);
+  static_chain_variable(Bfunction*, const std::string&, Btype*, unsigned int,
+                       Location);
 
   Bvariable*
-  temporary_variable(Bfunction*, Bblock*, Btype*, Bexpression*, bool,
+  temporary_variable(Bfunction*, Bblock*, Btype*, Bexpression*, unsigned int,
                     Location, Bstatement**);
 
   Bvariable*
   implicit_variable(const std::string&, const std::string&, Btype*,
-                    bool, bool, bool, int64_t);
+                    unsigned int, int64_t);
 
   void
   implicit_variable_set_init(Bvariable*, const std::string&, Btype*,
-                            bool, bool, bool, Bexpression*);
+                            unsigned int, Bexpression*);
 
   Bvariable*
   implicit_variable_reference(const std::string&, const std::string&, Btype*);
 
   Bvariable*
   immutable_struct(const std::string&, const std::string&,
-                   bool, bool, Btype*, Location);
+                   unsigned int, Btype*, Location);
 
   void
-  immutable_struct_set_init(Bvariable*, const std::string&, bool, bool, Btype*,
-                           Location, Bexpression*);
+  immutable_struct_set_init(Bvariable*, const std::string&, unsigned int,
+                           Btype*, Location, Bexpression*);
 
   Bvariable*
   immutable_struct_reference(const std::string&, const std::string&,
@@ -2696,9 +2695,7 @@ Bvariable*
 Gcc_backend::global_variable(const std::string& var_name,
                             const std::string& asm_name,
                             Btype* btype,
-                            bool is_external,
-                            bool is_hidden,
-                            bool in_unique_section,
+                            unsigned int flags,
                             Location location)
 {
   tree type_tree = btype->get_tree();
@@ -2707,30 +2704,49 @@ Gcc_backend::global_variable(const std::string& 
var_name,
 
   // The GNU linker does not like dynamic variables with zero size.
   tree orig_type_tree = type_tree;
+  bool is_external = (flags & variable_is_external) != 0;
+  bool is_hidden = (flags & variable_is_hidden) != 0;
   if ((is_external || !is_hidden) && int_size_in_bytes(type_tree) == 0)
     type_tree = this->non_zero_size_type(type_tree);
 
   tree decl = build_decl(location.gcc_location(), VAR_DECL,
                         get_identifier_from_string(var_name),
                         type_tree);
-  if (is_external)
-    DECL_EXTERNAL(decl) = 1;
-  else
-    TREE_STATIC(decl) = 1;
-  if (!is_hidden)
+  if ((flags & variable_is_external) != 0)
     {
-      TREE_PUBLIC(decl) = 1;
-      SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
+      DECL_EXTERNAL(decl) = 1;
+      flags &=~ variable_is_external;
     }
   else
+    TREE_STATIC(decl) = 1;
+
+  if ((flags & variable_is_hidden) == 0)
+    TREE_PUBLIC(decl) = 1;
+  else
+    flags &=~ variable_is_hidden;
+
+  if ((flags & variable_address_is_taken) != 0)
     {
-      SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
+      TREE_ADDRESSABLE(decl) = 1;
+      flags &=~ variable_address_is_taken;
     }
 
+  // We take the address in Bvariable::get_tree if orig_type_tree is
+  // different from type_tree.
+  if (orig_type_tree != type_tree)
+    TREE_ADDRESSABLE(decl) = 1;
+
+  SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
+
   TREE_USED(decl) = 1;
 
-  if (in_unique_section)
-    resolve_unique_section (decl, 0, 1);
+  if ((flags & variable_in_unique_section) != 0)
+    {
+      resolve_unique_section (decl, 0, 1);
+      flags &=~ variable_in_unique_section;
+    }
+
+  gcc_assert(flags == 0);
 
   go_preserve_from_gc(decl);
 
@@ -2768,7 +2784,7 @@ Gcc_backend::global_variable_set_init(Bvariable* var, 
Bexpression* expr)
 Bvariable*
 Gcc_backend::local_variable(Bfunction* function, const std::string& name,
                            Btype* btype, Bvariable* decl_var, 
-                           bool is_address_taken, Location location)
+                           unsigned int flags, Location location)
 {
   tree type_tree = btype->get_tree();
   if (type_tree == error_mark_node)
@@ -2778,13 +2794,17 @@ Gcc_backend::local_variable(Bfunction* function, const 
std::string& name,
                         type_tree);
   DECL_CONTEXT(decl) = function->get_tree();
   TREE_USED(decl) = 1;
-  if (is_address_taken)
-    TREE_ADDRESSABLE(decl) = 1;
+  if ((flags & variable_address_is_taken) != 0)
+    {
+      TREE_ADDRESSABLE(decl) = 1;
+      flags &=~ variable_address_is_taken;
+    }
   if (decl_var != NULL)
     {
       DECL_HAS_VALUE_EXPR_P(decl) = 1;
       SET_DECL_VALUE_EXPR(decl, decl_var->get_decl());
     }
+  go_assert(flags == 0);
   go_preserve_from_gc(decl);
   return new Bvariable(decl);
 }
@@ -2793,7 +2813,7 @@ Gcc_backend::local_variable(Bfunction* function, const 
std::string& name,
 
 Bvariable*
 Gcc_backend::parameter_variable(Bfunction* function, const std::string& name,
-                               Btype* btype, bool is_address_taken,
+                               Btype* btype, unsigned int flags,
                                Location location)
 {
   tree type_tree = btype->get_tree();
@@ -2805,8 +2825,12 @@ Gcc_backend::parameter_variable(Bfunction* function, 
const std::string& name,
   DECL_CONTEXT(decl) = function->get_tree();
   DECL_ARG_TYPE(decl) = type_tree;
   TREE_USED(decl) = 1;
-  if (is_address_taken)
-    TREE_ADDRESSABLE(decl) = 1;
+  if ((flags & variable_address_is_taken) != 0)
+    {
+      TREE_ADDRESSABLE(decl) = 1;
+      flags &=~ variable_address_is_taken;
+    }
+  go_assert(flags == 0);
   go_preserve_from_gc(decl);
   return new Bvariable(decl);
 }
@@ -2815,7 +2839,8 @@ Gcc_backend::parameter_variable(Bfunction* function, 
const std::string& name,
 
 Bvariable*
 Gcc_backend::static_chain_variable(Bfunction* function, const std::string& 
name,
-                                  Btype* btype, Location location)
+                                  Btype* btype, unsigned int flags,
+                                  Location location)
 {
   tree type_tree = btype->get_tree();
   if (type_tree == error_mark_node)
@@ -2840,6 +2865,7 @@ Gcc_backend::static_chain_variable(Bfunction* function, 
const std::string& name,
   gcc_assert(f->static_chain_decl == NULL);
   f->static_chain_decl = decl;
   DECL_STATIC_CHAIN(fndecl) = 1;
+  go_assert(flags == 0);
 
   go_preserve_from_gc(decl);
   return new Bvariable(decl);
@@ -2850,7 +2876,7 @@ Gcc_backend::static_chain_variable(Bfunction* function, 
const std::string& name,
 Bvariable*
 Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
                                Btype* btype, Bexpression* binit,
-                               bool is_address_taken,
+                               unsigned int flags,
                                Location location,
                                Bstatement** pstatement)
 {
@@ -2904,8 +2930,13 @@ Gcc_backend::temporary_variable(Bfunction* function, 
Bblock* bblock,
       && TREE_TYPE(init_tree) != void_type_node)
     DECL_INITIAL(var) = this->convert_tree(type_tree, init_tree, location);
 
-  if (is_address_taken)
-    TREE_ADDRESSABLE(var) = 1;
+  if ((flags & variable_address_is_taken) != 0)
+    {
+      TREE_ADDRESSABLE(var) = 1;
+      flags &=~ variable_address_is_taken;
+    }
+
+  gcc_assert(flags == 0);
 
   *pstatement = this->make_statement(build1_loc(location.gcc_location(),
                                                 DECL_EXPR,
@@ -2929,8 +2960,8 @@ Gcc_backend::temporary_variable(Bfunction* function, 
Bblock* bblock,
 Bvariable*
 Gcc_backend::implicit_variable(const std::string& name,
                                const std::string& asm_name,
-                               Btype* type, bool is_hidden, bool is_constant,
-                              bool is_common, int64_t alignment)
+                               Btype* type, unsigned int flags,
+                              int64_t alignment)
 {
   tree type_tree = type->get_tree();
   if (type_tree == error_mark_node)
@@ -2939,11 +2970,14 @@ Gcc_backend::implicit_variable(const std::string& name,
   tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL,
                          get_identifier_from_string(name), type_tree);
   DECL_EXTERNAL(decl) = 0;
-  TREE_PUBLIC(decl) = !is_hidden;
+  if ((flags & variable_is_hidden) != 0)
+    flags &=~ variable_is_hidden;
+  else
+    TREE_PUBLIC(decl) = 1;
   TREE_STATIC(decl) = 1;
   TREE_USED(decl) = 1;
   DECL_ARTIFICIAL(decl) = 1;
-  if (is_common)
+  if ((flags & variable_is_common) != 0)
     {
       DECL_COMMON(decl) = 1;
 
@@ -2960,11 +2994,19 @@ Gcc_backend::implicit_variable(const std::string& name,
       // mark this symbol as weak here.  We undo that below in
       // immutable_struct_set_init before calling mark_decl_one_only.
       DECL_WEAK(decl) = 1;
+
+      flags &=~ variable_is_common;
     }
-  if (is_constant)
+  if ((flags & variable_is_constant) != 0)
     {
       TREE_READONLY(decl) = 1;
       TREE_CONSTANT(decl) = 1;
+      flags &=~ variable_is_constant;
+    }
+  if ((flags & variable_address_is_taken) != 0)
+    {
+      TREE_ADDRESSABLE(decl) = 1;
+      flags &=~ variable_address_is_taken;
     }
   if (alignment != 0)
     {
@@ -2973,6 +3015,7 @@ Gcc_backend::implicit_variable(const std::string& name,
     }
   if (! asm_name.empty())
     SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
+  gcc_assert(flags == 0);
 
   go_preserve_from_gc(decl);
   return new Bvariable(decl);
@@ -2983,7 +3026,7 @@ Gcc_backend::implicit_variable(const std::string& name,
 
 void
 Gcc_backend::implicit_variable_set_init(Bvariable* var, const std::string&,
-                                       Btype*, bool, bool, bool is_common,
+                                       Btype*, unsigned int flags,
                                        Bexpression* init)
 {
   tree decl = var->get_decl();
@@ -2999,7 +3042,7 @@ Gcc_backend::implicit_variable_set_init(Bvariable* var, 
const std::string&,
 
   // Now that DECL_INITIAL is set, we can't call make_decl_one_only.
   // See the comment where DECL_WEAK is set in implicit_variable.
-  if (is_common)
+  if ((flags & variable_is_common) != 0)
     {
       DECL_WEAK(decl) = 0;
       make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
@@ -3038,8 +3081,8 @@ Gcc_backend::implicit_variable_reference(const 
std::string& name,
 Bvariable*
 Gcc_backend::immutable_struct(const std::string& name,
                               const std::string& asm_name,
-                              bool is_hidden,
-                             bool is_common, Btype* btype, Location location)
+                             unsigned int flags, Btype* btype,
+                             Location location)
 {
   tree type_tree = btype->get_tree();
   if (type_tree == error_mark_node)
@@ -3053,10 +3096,17 @@ Gcc_backend::immutable_struct(const std::string& name,
   TREE_READONLY(decl) = 1;
   TREE_CONSTANT(decl) = 1;
   DECL_ARTIFICIAL(decl) = 1;
-  if (!is_hidden)
+  if ((flags & variable_is_hidden) != 0)
+    flags &=~ variable_is_hidden;
+  else
     TREE_PUBLIC(decl) = 1;
   if (! asm_name.empty())
     SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
+  if ((flags & variable_address_is_taken) != 0)
+    {
+      TREE_ADDRESSABLE(decl) = 1;
+      flags &=~ variable_address_is_taken;
+    }
 
   // When the initializer for one immutable_struct refers to another,
   // it needs to know the visibility of the referenced struct so that
@@ -3070,8 +3120,13 @@ Gcc_backend::immutable_struct(const std::string& name,
   // the right value if some other initializer refers to this one, we
   // mark this symbol as weak here.  We undo that below in
   // immutable_struct_set_init before calling mark_decl_one_only.
-  if (is_common)
-    DECL_WEAK(decl) = 1;
+  if ((flags & variable_is_common) != 0)
+    {
+      DECL_WEAK(decl) = 1;
+      flags &=~ variable_is_common;
+    }
+
+  gcc_assert(flags == 0);
 
   // We don't call rest_of_decl_compilation until we have the
   // initializer.
@@ -3085,7 +3140,7 @@ Gcc_backend::immutable_struct(const std::string& name,
 
 void
 Gcc_backend::immutable_struct_set_init(Bvariable* var, const std::string&,
-                                      bool, bool is_common, Btype*, Location,
+                                      unsigned int flags, Btype*, Location,
                                       Bexpression* initializer)
 {
   tree decl = var->get_decl();
@@ -3097,7 +3152,7 @@ Gcc_backend::immutable_struct_set_init(Bvariable* var, 
const std::string&,
 
   // Now that DECL_INITIAL is set, we can't call make_decl_one_only.
   // See the comment where DECL_WEAK is set in immutable_struct.
-  if (is_common)
+  if ((flags & variable_is_common) != 0)
     {
       DECL_WEAK(decl) = 0;
       make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 373b58c75a4..1f38c9110ba 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-38228e7a91d37588463307ec60420c8f17f1aee4
+5a801b15699cced5203af5c7339b375cd55ecbac
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h
index c5b5d8f2054..5b6ffea0f6c 100644
--- a/gcc/go/gofrontend/backend.h
+++ b/gcc/go/gofrontend/backend.h
@@ -481,24 +481,51 @@ class Backend
   virtual Bvariable*
   error_variable() = 0;
 
+  // Bit flags to pass to the various methods that return Bvariable*.
+  // Not all flags are meaningful for all methods.
+
+  // Set if the variable's address is taken.  For a local variable
+  // this implies that the address does not escape the function, as
+  // otherwise the variable would be on the heap.
+  static const unsigned int variable_address_is_taken = 1 << 0;
+
+  // Set if the variable is defined in some other package.  Only
+  // meaningful for the global_variable method.  At most one of
+  // is_external, is_hidden, and is_common may be set.
+  static const unsigned int variable_is_external = 1 << 1;
+
+  // Set if the variable is not exported, and as such is only defined
+  // in the current package.  Only meaningful for global_variable,
+  // implicit_variable, and immutable_struct.  At most one of
+  // is_external, is_hidden, and is_common may be set.
+  static const unsigned variable_is_hidden = 1 << 2;
+
+  // Set if the variable should be treated as a common variable:
+  // multiple definitions with different sizes permitted in different
+  // object files, all merged into the largest definition at link
+  // time.  Only meaningful for implicit_variable and immutable_struct.
+  // At most one of is_external, is_hidden, and is_common may be set.
+  static const unsigned int variable_is_common = 1 << 3;
+
+  // Set if the variable should be put into a unique section if
+  // possible; this is intended to permit the linker to garbage
+  // collect the value if it is not referenced.  Only meaningful for
+  // global_variable.
+  static const unsigned int variable_in_unique_section = 1 << 4;
+
+  // Set if the variable should be treated as immutable.  Only
+  // meaningful for implicit_variable.  For example, this is set for
+  // slice initializers if the values must be copied to the heap.
+  static const unsigned int variable_is_constant = 1 << 5;
+
   // Create a global variable. NAME is the package-qualified name of
   // the variable.  ASM_NAME is the encoded identifier for the
   // variable, incorporating the package, and made safe for the
-  // assembler.  BTYPE is the type of the variable.  IS_EXTERNAL is
-  // true if the variable is defined in some other package.  IS_HIDDEN
-  // is true if the variable is not exported (name begins with a lower
-  // case letter).  IN_UNIQUE_SECTION is true if the variable should
-  // be put into a unique section if possible; this is intended to
-  // permit the linker to garbage collect the variable if it is not
-  // referenced.  LOCATION is where the variable was defined.
+  // assembler.  BTYPE is the type of the variable.  FLAGS is the bit
+  // flags defined above.  LOCATION is where the variable was defined.
   virtual Bvariable*
-  global_variable(const std::string& name,
-                  const std::string& asm_name,
-                 Btype* btype,
-                 bool is_external,
-                 bool is_hidden,
-                 bool in_unique_section,
-                 Location location) = 0;
+  global_variable(const std::string& name, const std::string& asm_name,
+                 Btype* btype, unsigned int flags, Location location) = 0;
 
   // A global variable will 1) be initialized to zero, or 2) be
   // initialized to a constant value, or 3) be initialized in the init
@@ -516,42 +543,40 @@ class Backend
   // null, gives the location at which the value of this variable may
   // be found, typically used to create an inner-scope reference to an
   // outer-scope variable, to extend the lifetime of the variable beyond
-  // the inner scope.  IS_ADDRESS_TAKEN is true if the address of this
-  // variable is taken (this implies that the address does not escape
-  // the function, as otherwise the variable would be on the heap).
+  // the inner scope.  FLAGS is the bit flags defined above.
   // LOCATION is where the variable is defined.  For each local variable
   // the frontend will call init_statement to set the initial value.
   virtual Bvariable*
   local_variable(Bfunction* function, const std::string& name, Btype* type,
-                Bvariable* decl_var, bool is_address_taken, Location location) 
= 0;
+                Bvariable* decl_var, unsigned int flags,
+                Location location) = 0;
 
   // Create a function parameter.  This is an incoming parameter, not
   // a result parameter (result parameters are treated as local
   // variables).  The arguments are as for local_variable.
   virtual Bvariable*
   parameter_variable(Bfunction* function, const std::string& name,
-                    Btype* type, bool is_address_taken,
-                    Location location) = 0;
+                    Btype* type, unsigned int flags, Location location) = 0;
 
   // Create a static chain parameter.  This is the closure parameter.
   virtual Bvariable*
   static_chain_variable(Bfunction* function, const std::string& name,
-                       Btype* type, Location location) = 0;
+                       Btype* type, unsigned int flags,
+                       Location location) = 0;
 
   // Create a temporary variable.  A temporary variable has no name,
   // just a type.  We pass in FUNCTION and BLOCK in case they are
   // needed.  If INIT is not NULL, the variable should be initialized
   // to that value.  Otherwise the initial value is irrelevant--the
   // backend does not have to explicitly initialize it to zero.
-  // ADDRESS_IS_TAKEN is true if the programs needs to take the
-  // address of this temporary variable.  LOCATION is the location of
+  // FLAGS is the bit flags defined above.  LOCATION is the location of
   // the statement or expression which requires creating the temporary
   // variable, and may not be very useful.  This function should
   // return a variable which can be referenced later and should set
   // *PSTATEMENT to a statement which initializes the variable.
   virtual Bvariable*
   temporary_variable(Bfunction*, Bblock*, Btype*, Bexpression* init,
-                    bool address_is_taken, Location location,
+                    unsigned int flags, Location location,
                     Bstatement** pstatement) = 0;
 
   // Create an implicit variable that is compiler-defined.  This is
@@ -566,46 +591,33 @@ class Backend
   //
   // TYPE is the type of the implicit variable.
   //
-  // IS_HIDDEN will be true if the descriptor should only be visible
-  // within the current object.
-  //
-  // IS_CONSTANT is true if the implicit variable should be treated like it is
-  // immutable.  For slice initializers, if the values must be copied to the
-  // heap, the variable IS_CONSTANT.
-  //
-  // IS_COMMON is true if the implicit variable should
-  // be treated as a common variable (multiple definitions with
-  // different sizes permitted in different object files, all merged
-  // into the largest definition at link time); this will be true for
-  // the zero value.  IS_HIDDEN and IS_COMMON will never both be true.
+  // FLAGS is the bit flags defined above.
   //
   // If ALIGNMENT is not zero, it is the desired alignment of the variable.
   virtual Bvariable*
   implicit_variable(const std::string& name, const std::string& asm_name,
-                    Btype* type, bool is_hidden, bool is_constant,
-                    bool is_common, int64_t alignment) = 0;
+                    Btype* type, unsigned int flags, int64_t alignment) = 0;
 
 
   // Set the initial value of a variable created by implicit_variable.
   // This must be called even if there is no initializer, i.e., INIT is NULL.
-  // The NAME, TYPE, IS_HIDDEN, IS_CONSTANT, and IS_COMMON parameters are
-  // the same ones passed to implicit_variable.  INIT will be a composite
-  // literal of type TYPE.  It will not contain any function calls or anything
-  // else that can not be put into a read-only data section.
-  // It may contain the address of variables created by implicit_variable.
+  // The NAME, TYPE, and FLAGS parameters are the same ones passed to
+  // implicit_variable.  INIT will be a composite literal of type
+  // TYPE.  It will not contain any function calls or anything else
+  // that can not be put into a read-only data section.  It may
+  // contain the address of variables created by implicit_variable.
   //
-  // If IS_COMMON is true, INIT will be NULL, and the
+  // If variable_is_common is set in FLAGS, INIT will be NULL, and the
   // variable should be initialized to all zeros.
   virtual void
   implicit_variable_set_init(Bvariable*, const std::string& name, Btype* type,
-                            bool is_hidden, bool is_constant, bool is_common,
-                            Bexpression* init) = 0;
+                            unsigned int flags, Bexpression* init) = 0;
 
   // Create a reference to a named implicit variable defined in some
   // other package.  This will be a variable created by a call to
   // implicit_variable with the same NAME, ASM_NAME and TYPE and with
-  // IS_COMMON passed as false.  This corresponds to an extern global
-  // variable in C.
+  // variable_is_common not set in FLAGS.  This corresponds to an
+  // extern global variable in C.
   virtual Bvariable*
   implicit_variable_reference(const std::string& name,
                               const std::string& asm_name,
@@ -622,15 +634,12 @@ class Backend
   // ASM_NAME is the encoded, assembler-friendly version of NAME, or
   // the empty string if no encoding is needed.
   //
-  // IS_HIDDEN will be true if the descriptor should only be visible
-  // within the current object.
-  //
-  // IS_COMMON is true if NAME may be defined by several packages, and
-  // the linker should merge all such definitions.  If IS_COMMON is
-  // false, NAME should be defined in only one file.  In general
-  // IS_COMMON will be true for the type descriptor of an unnamed type
-  // or a builtin type.  IS_HIDDEN and IS_COMMON will never both be
-  // true.
+  // FLAGS is the bit flags defined above.  The variable_is_common
+  // flag will be set if NAME may be defined by several packages, and
+  // the linker should merge all such definitions.  If the
+  // variable_is_common flag is not set, NAME should be defined in
+  // only one file.  In general variable_is_common will be set for the
+  // type descriptor of an unnamed type or a builtin type.
   //
   // TYPE will be a struct type; the type of the returned expression
   // must be a pointer to this struct type.
@@ -640,28 +649,26 @@ class Backend
   // address.  After calling this the frontend will call
   // immutable_struct_set_init.
   virtual Bvariable*
-  immutable_struct(const std::string& name,
-                   const std::string& asm_name,
-                   bool is_hidden, bool is_common,
-                  Btype* type, Location) = 0;
+  immutable_struct(const std::string& name, const std::string& asm_name,
+                  unsigned int flags, Btype* type, Location) = 0;
 
   // Set the initial value of a variable created by immutable_struct.
-  // The NAME, IS_HIDDEN, IS_COMMON, TYPE, and location parameters are
-  // the same ones passed to immutable_struct.  INITIALIZER will be a
-  // composite literal of type TYPE.  It will not contain any function
-  // calls or anything else that can not be put into a read-only data
-  // section.  It may contain the address of variables created by
+  // The NAME, FLAGS, TYPE, and location parameters are the same ones
+  // passed to immutable_struct.  INITIALIZER will be a composite
+  // literal of type TYPE.  It will not contain any function calls or
+  // anything else that can not be put into a read-only data section.
+  // It may contain the address of variables created by
   // immutable_struct.
   virtual void
   immutable_struct_set_init(Bvariable*, const std::string& name,
-                           bool is_hidden, bool is_common, Btype* type,
+                           unsigned int flags, Btype* type,
                            Location, Bexpression* initializer) = 0;
 
   // Create a reference to a named immutable initialized data
   // structure defined in some other package.  This will be a
   // structure created by a call to immutable_struct with the same
-  // NAME, ASM_NAME and TYPE and with IS_COMMON passed as false.  This
-  // corresponds to an extern const global variable in C.
+  // NAME, ASM_NAME and TYPE and with variable_is_common not set in
+  // flags.  This corresponds to an extern const global variable in C.
   virtual Bvariable*
   immutable_struct_reference(const std::string& name,
                              const std::string& asm_name,
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 5409d269ebf..5d45e4baab4 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -1427,7 +1427,7 @@ Sink_expression::do_get_backend(Translate_context* 
context)
       Bstatement* decl;
       this->bvar_ =
        gogo->backend()->temporary_variable(fn_ctx, context->bblock(), bt, NULL,
-                                           false, loc, &decl);
+                                           0, loc, &decl);
       Bexpression* var_ref =
           gogo->backend()->var_expression(this->bvar_, loc);
       var_ref = gogo->backend()->compound_expression(decl, var_ref, loc);
@@ -1724,10 +1724,12 @@ 
Func_descriptor_expression::do_get_backend(Translate_context* context)
       if (no->is_function() && no->func_value()->is_referenced_by_inline())
        is_hidden = false;
 
+      unsigned int flags = 0;
+      if (is_hidden)
+       flags |= Backend::variable_is_hidden;
       bvar = context->backend()->immutable_struct(bname.name(),
                                                  bname.optional_asm_name(),
-                                                  is_hidden, false,
-                                                 btype, bloc);
+                                                 flags, btype, bloc);
       Expression_list* vals = new Expression_list();
       vals->push_back(Expression::make_func_code_reference(this->fn_, bloc));
       Expression* init =
@@ -1736,8 +1738,7 @@ 
Func_descriptor_expression::do_get_backend(Translate_context* context)
       bcontext.set_is_const();
       Bexpression* binit = init->get_backend(&bcontext);
       context->backend()->immutable_struct_set_init(bvar, bname.name(),
-                                                   is_hidden, false, btype,
-                                                   bloc, binit);
+                                                   flags, btype, bloc, binit);
     }
 
   this->dvar_ = bvar;
@@ -5280,12 +5281,14 @@ Unary_expression::do_get_backend(Translate_context* 
context)
              copy_to_heap = (context->function() != NULL
                               || context->is_const());
            }
+         unsigned int flags = (Backend::variable_is_hidden
+                               | Backend::variable_address_is_taken);
+         if (copy_to_heap)
+           flags |= Backend::variable_is_constant;
          Bvariable* implicit =
-              gogo->backend()->implicit_variable(var_name, "", btype, true,
-                                                copy_to_heap, false, 0);
+           gogo->backend()->implicit_variable(var_name, "", btype, flags, 0);
          gogo->backend()->implicit_variable_set_init(implicit, var_name, btype,
-                                                     true, copy_to_heap, false,
-                                                     bexpr);
+                                                     flags, bexpr);
          bexpr = gogo->backend()->var_expression(implicit, loc);
 
          // If we are not copying a slice initializer to the heap,
@@ -5307,22 +5310,24 @@ Unary_expression::do_get_backend(Translate_context* 
context)
               && this->expr_->is_static_initializer())
         {
          std::string var_name(gogo->initializer_name());
+         unsigned int flags = (Backend::variable_is_hidden
+                               | Backend::variable_address_is_taken);
           Bvariable* decl =
-              gogo->backend()->immutable_struct(var_name, "", true, false,
-                                               btype, loc);
-          gogo->backend()->immutable_struct_set_init(decl, var_name, true,
-                                                    false, btype, loc, bexpr);
+           gogo->backend()->immutable_struct(var_name, "", flags, btype, loc);
+          gogo->backend()->immutable_struct_set_init(decl, var_name, flags,
+                                                    btype, loc, bexpr);
           bexpr = gogo->backend()->var_expression(decl, loc);
         }
       else if (this->expr_->is_constant())
         {
           std::string var_name(gogo->initializer_name());
+         unsigned int flags = (Backend::variable_is_hidden
+                               | Backend::variable_is_constant
+                               | Backend::variable_address_is_taken);
           Bvariable* decl =
-              gogo->backend()->implicit_variable(var_name, "", btype,
-                                                 true, true, false, 0);
+           gogo->backend()->implicit_variable(var_name, "", btype, flags, 0);
           gogo->backend()->implicit_variable_set_init(decl, var_name, btype,
-                                                      true, true, false,
-                                                      bexpr);
+                                                     flags, bexpr);
           bexpr = gogo->backend()->var_expression(decl, loc);
         }
 
@@ -14888,7 +14893,9 @@ 
Allocation_expression::do_get_backend(Translate_context* context)
                            : gogo->backend()->zero_expression(btype));
       Bvariable* temp =
         gogo->backend()->temporary_variable(fndecl, context->bblock(), btype,
-                                            init, true, loc, &decl);
+                                            init,
+                                           Backend::variable_address_is_taken,
+                                           loc, &decl);
       Bexpression* ret = gogo->backend()->var_expression(temp, loc);
       ret = gogo->backend()->address_expression(ret, loc);
       ret = gogo->backend()->compound_expression(decl, ret, loc);
@@ -17238,7 +17245,9 @@ Heap_expression::do_get_backend(Translate_context* 
context)
   Bfunction* fndecl = fn->func_value()->get_or_make_decl(gogo, fn);
   Bvariable* space_temp =
     gogo->backend()->temporary_variable(fndecl, context->bblock(), btype,
-                                       space, true, loc, &decl);
+                                       space,
+                                       Backend::variable_address_is_taken,
+                                       loc, &decl);
   Btype* expr_btype = etype->get_backend(gogo);
 
   Bexpression* bexpr = this->expr_->get_backend(context);
@@ -17259,8 +17268,9 @@ Heap_expression::do_get_backend(Translate_context* 
context)
       Bstatement* edecl;
       Bvariable* btemp =
        gogo->backend()->temporary_variable(fndecl, context->bblock(),
-                                           expr_btype, bexpr, true, loc,
-                                           &edecl);
+                                           expr_btype, bexpr,
+                                           Backend::variable_address_is_taken,
+                                           loc, &edecl);
       Bexpression* btempref = gogo->backend()->var_expression(btemp,
                                                              loc);
       space = gogo->backend()->var_expression(space_temp, loc);
@@ -18478,10 +18488,13 @@ 
Interface_mtable_expression::do_get_backend(Translate_context* context)
   Bexpression* ctor =
       gogo->backend()->constructor_expression(btype, ctor_bexprs, loc);
 
-  this->bvar_ = gogo->backend()->immutable_struct(mangled_name, "", false,
-                                                 !is_public, btype, loc);
-  gogo->backend()->immutable_struct_set_init(this->bvar_, mangled_name, false,
-                                             !is_public, btype, loc, ctor);
+  unsigned int flags = 0;
+  if (!is_public)
+    flags |= Backend::variable_is_hidden;
+  this->bvar_ = gogo->backend()->immutable_struct(mangled_name, "", flags,
+                                                 btype, loc);
+  gogo->backend()->immutable_struct_set_init(this->bvar_, mangled_name, flags,
+                                            btype, loc, ctor);
   return gogo->backend()->var_expression(this->bvar_, loc);
 }
 
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index 93b54fd8c11..2872d2ed3ab 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -918,9 +918,8 @@ Gogo::build_type_descriptor_list()
 
   // Create the variable
   std::string name = this->type_descriptor_list_symbol(this->pkgpath_symbol());
-  Bvariable* bv = this->backend()->implicit_variable(name, name, bt,
-                                                     false, true, false,
-                                                     0);
+  unsigned int flags = Backend::variable_is_constant;
+  Bvariable* bv = this->backend()->implicit_variable(name, name, bt, flags, 0);
 
   // Build the initializer
   std::vector<unsigned long> indexes;
@@ -946,8 +945,7 @@ Gogo::build_type_descriptor_list()
   Bexpression* binit =
     this->backend()->constructor_expression(bt, fields, builtin_loc);
 
-  this->backend()->implicit_variable_set_init(bv, name, bt, false,
-                                              true, false, binit);
+  this->backend()->implicit_variable_set_init(bv, name, bt, flags, binit);
 }
 
 // Register the type descriptors with the runtime.  This is to help
@@ -1002,11 +1000,11 @@ 
Gogo::register_type_descriptors(std::vector<Bstatement*>& init_stmts,
 
   // Create a variable holding the list.
   std::string name = this->typelists_symbol();
-  Bvariable* bv = this->backend()->implicit_variable(name, name, bat,
-                                                     true, true, false,
+  unsigned int flags = (Backend::variable_is_hidden
+                       | Backend::variable_is_constant);
+  Bvariable* bv = this->backend()->implicit_variable(name, name, bat, flags,
                                                      0);
-  this->backend()->implicit_variable_set_init(bv, name, bat, true, true,
-                                              false, barray);
+  this->backend()->implicit_variable_set_init(bv, name, bat, flags, barray);
 
   // Build the call in main package's init function.
   Translate_context context(this, NULL, NULL, NULL);
@@ -8062,16 +8060,24 @@ Variable::get_backend_variable(Gogo* gogo, 
Named_object* function,
              if (package != NULL)
                is_hidden = false;
 
+             unsigned int flags = 0;
+             if (this->is_address_taken_
+                 || this->is_non_escaping_address_taken_)
+               flags |= Backend::variable_address_is_taken;
+             if (package != NULL)
+               flags |= Backend::variable_is_external;
+             if (is_hidden)
+               flags |= Backend::variable_is_hidden;
+             if (this->in_unique_section_)
+               flags |= Backend::variable_in_unique_section;
+
              // For some reason asm_name can't be the empty string
              // for global_variable, so we call asm_name rather than
              // optional_asm_name here.  FIXME.
 
              bvar = backend->global_variable(bname.name(),
                                              bname.asm_name(),
-                                             btype,
-                                             package != NULL,
-                                             is_hidden,
-                                             this->in_unique_section_,
+                                             btype, flags,
                                              this->location_);
            }
          else if (function == NULL)
@@ -8083,15 +8089,16 @@ Variable::get_backend_variable(Gogo* gogo, 
Named_object* function,
            {
              const std::string n = Gogo::unpack_hidden_name(name);
              Bfunction* bfunction = function->func_value()->get_decl();
-             bool is_address_taken = (this->is_non_escaping_address_taken_
-                                      && !this->is_in_heap());
+             unsigned int flags = 0;
+             if (this->is_non_escaping_address_taken_
+                 && !this->is_in_heap())
+               flags |= Backend::variable_address_is_taken;
              if (this->is_closure())
                bvar = backend->static_chain_variable(bfunction, n, btype,
-                                                     this->location_);
+                                                     flags, this->location_);
              else if (is_parameter)
                bvar = backend->parameter_variable(bfunction, n, btype,
-                                                  is_address_taken,
-                                                  this->location_);
+                                                  flags, this->location_);
              else
                 {
                   Bvariable* bvar_decl = NULL;
@@ -8102,8 +8109,7 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* 
function,
                         ->get_backend_variable(&context);
                     }
                   bvar = backend->local_variable(bfunction, n, btype,
-                                                 bvar_decl,
-                                                 is_address_taken,
+                                                 bvar_decl, flags,
                                                  this->location_);
                 }
            }
@@ -8134,10 +8140,12 @@ Result_variable::get_backend_variable(Gogo* gogo, 
Named_object* function,
          Btype* btype = type->get_backend(gogo);
          Bfunction* bfunction = function->func_value()->get_decl();
          std::string n = Gogo::unpack_hidden_name(name);
-         bool is_address_taken = (this->is_non_escaping_address_taken_
-                                  && !this->is_in_heap());
+         unsigned int flags = 0;
+         if (this->is_non_escaping_address_taken_
+             && !this->is_in_heap())
+           flags |= Backend::variable_address_is_taken;
          this->backend_ = backend->local_variable(bfunction, n, btype,
-                                                  NULL, is_address_taken,
+                                                  NULL, flags,
                                                   this->location_);
        }
     }
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index b0660111ac8..9643d1b42b3 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -643,11 +643,13 @@ Temporary_statement::do_get_backend(Translate_context* 
context)
     binit = context->backend()->convert_expression(btype, binit,
                                                    this->location());
 
+  unsigned int flags = 0;
+  if (this->is_address_taken_)
+    flags |= Backend::variable_address_is_taken;
   Bstatement* statement;
   this->bvariable_ =
     context->backend()->temporary_variable(bfunction, context->bblock(),
-                                          btype, binit,
-                                          this->is_address_taken_,
+                                          btype, binit, flags,
                                           this->location(), &statement);
   return statement;
 }
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 7d4c47f1c42..d08cbc96ea1 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -1410,10 +1410,12 @@ Type::make_type_descriptor_var(Gogo* gogo)
   // ensure that type_descriptor_pointer will work if called while
   // converting INITIALIZER.
 
+  unsigned int flags = 0;
+  if (is_common)
+    flags |= Backend::variable_is_common;
   this->type_descriptor_var_ =
     gogo->backend()->immutable_struct(bname.name(), bname.optional_asm_name(),
-                                     false, is_common, initializer_btype,
-                                     loc);
+                                     flags, initializer_btype, loc);
   if (phash != NULL)
     *phash = this->type_descriptor_var_;
 
@@ -1422,7 +1424,7 @@ Type::make_type_descriptor_var(Gogo* gogo)
   Bexpression* binitializer = initializer->get_backend(&context);
 
   gogo->backend()->immutable_struct_set_init(this->type_descriptor_var_,
-                                            bname.name(), false, is_common,
+                                            bname.name(), flags,
                                             initializer_btype, loc,
                                             binitializer);
 
@@ -2714,9 +2716,13 @@ Type::make_gc_symbol_var(Gogo* gogo)
   // Since we are building the GC symbol in this package, we must create the
   // variable before converting the initializer to its backend representation
   // because the initializer may refer to the GC symbol for this type.
+  unsigned int flags = Backend::variable_is_constant;
+  if (is_common)
+    flags |= Backend::variable_is_common;
+  else
+    flags |= Backend::variable_is_hidden;
   this->gc_symbol_var_ =
-      gogo->backend()->implicit_variable(sym_name, "", sym_btype, false, true,
-                                        is_common, 0);
+    gogo->backend()->implicit_variable(sym_name, "", sym_btype, flags, 0);
   if (phash != NULL)
     *phash = this->gc_symbol_var_;
 
@@ -2724,8 +2730,7 @@ Type::make_gc_symbol_var(Gogo* gogo)
   context.set_is_const();
   Bexpression* sym_binit = sym_init->get_backend(&context);
   gogo->backend()->implicit_variable_set_init(this->gc_symbol_var_, sym_name,
-                                             sym_btype, false, true, is_common,
-                                             sym_binit);
+                                             sym_btype, flags, sym_binit);
 }
 
 // Return whether this type needs a GC program, and set *PTRDATA to
@@ -3013,11 +3018,12 @@ Type::gc_ptrmask_var(Gogo* gogo, int64_t ptrsize, 
int64_t ptrdata)
   Bexpression* bval = val->get_backend(&context);
 
   Btype *btype = val->type()->get_backend(gogo);
+  unsigned int flags = (Backend::variable_is_constant
+                       | Backend::variable_is_common);
   Bvariable* ret = gogo->backend()->implicit_variable(sym_name, "",
-                                                     btype, false, true,
-                                                     true, 0);
-  gogo->backend()->implicit_variable_set_init(ret, sym_name, btype, false,
-                                             true, true, bval);
+                                                     btype, flags, 0);
+  gogo->backend()->implicit_variable_set_init(ret, sym_name, btype, flags,
+                                             bval);
   ins.first->second = ret;
   return ret;
 }
@@ -8145,11 +8151,12 @@ Map_type::backend_zero_value(Gogo* gogo)
   Btype* barray_type = gogo->backend()->array_type(buint8_type, blength);
 
   std::string zname = Map_type::zero_value->name();
+  unsigned int flags = Backend::variable_is_common;
   Bvariable* zvar =
-      gogo->backend()->implicit_variable(zname, "", barray_type, false, false,
-                                        true, Map_type::zero_value_align);
+    gogo->backend()->implicit_variable(zname, "", barray_type, flags,
+                                      Map_type::zero_value_align);
   gogo->backend()->implicit_variable_set_init(zvar, zname, barray_type,
-                                             false, false, true, NULL);
+                                             flags, NULL);
   return zvar;
 }
 

Reply via email to