aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-05-22 19:19:13 -0700
committerIan Lance Taylor <iant@golang.org>2021-05-24 13:24:45 -0700
commit358832c46a378e5a0b8a2fa3c2739125e3e680c7 (patch)
tree9217b12417ae68331c8efd66fd230414b12b98dd
parent2c43f5ec9db163696de8691eb529df06c4999bcc (diff)
downloadgcc-358832c46a378e5a0b8a2fa3c2739125e3e680c7.zip
gcc-358832c46a378e5a0b8a2fa3c2739125e3e680c7.tar.gz
gcc-358832c46a378e5a0b8a2fa3c2739125e3e680c7.tar.bz2
compiler: mark global variables whose address is taken
To implement this, change the backend to use flag bits for variables. Fixes https://gcc.gnu.org/PR100537 PR go/100537 * go-gcc.cc (class Gcc_backend): Update methods that create variables to take a flags parameter. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/322129
-rw-r--r--gcc/go/go-gcc.cc155
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/backend.h145
-rw-r--r--gcc/go/gofrontend/expressions.cc63
-rw-r--r--gcc/go/gofrontend/gogo.cc54
-rw-r--r--gcc/go/gofrontend/statements.cc6
-rw-r--r--gcc/go/gofrontend/types.cc35
7 files changed, 276 insertions, 184 deletions
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 5d9dbb5..41f309e 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 373b58c..1f38c911 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 c5b5d8f..5b6ffea 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 5409d26..5d45e4b 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 93b54fd..2872d2e 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 b066011..9643d1b 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 7d4c47f..d08cbc9 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;
}