From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2116) id 78E9E3858022; Mon, 24 May 2021 20:25:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 78E9E3858022 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Ian Lance Taylor To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-1022] compiler: mark global variables whose address is taken X-Act-Checkin: gcc X-Git-Author: Ian Lance Taylor X-Git-Refname: refs/heads/master X-Git-Oldrev: 2c43f5ec9db163696de8691eb529df06c4999bcc X-Git-Newrev: 358832c46a378e5a0b8a2fa3c2739125e3e680c7 Message-Id: <20210524202506.78E9E3858022@sourceware.org> Date: Mon, 24 May 2021 20:25:06 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 24 May 2021 20:25:06 -0000 https://gcc.gnu.org/g:358832c46a378e5a0b8a2fa3c2739125e3e680c7 commit r12-1022-g358832c46a378e5a0b8a2fa3c2739125e3e680c7 Author: Ian Lance Taylor Date: Sat May 22 19:19:13 2021 -0700 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 Diff: --- gcc/go/go-gcc.cc | 155 ++++++++++++++++++++++++++------------- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/backend.h | 145 +++++++++++++++++++----------------- gcc/go/gofrontend/expressions.cc | 63 +++++++++------- gcc/go/gofrontend/gogo.cc | 54 ++++++++------ gcc/go/gofrontend/statements.cc | 6 +- gcc/go/gofrontend/types.cc | 35 +++++---- 7 files changed, 276 insertions(+), 184 deletions(-) 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 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& 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; }