diff options
author | Ian Lance Taylor <iant@google.com> | 2015-12-22 01:58:17 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2015-12-22 01:58:17 +0000 |
commit | 399f5feb92e4c588ec230d4a0b8ac9b0fa95d7ed (patch) | |
tree | a8c1bae049e51a32ca8a424d0e68ee92fff9152e | |
parent | 18fb580c1e9e378448f202a818ff9f5aa1596574 (diff) | |
download | gcc-399f5feb92e4c588ec230d4a0b8ac9b0fa95d7ed.zip gcc-399f5feb92e4c588ec230d4a0b8ac9b0fa95d7ed.tar.gz gcc-399f5feb92e4c588ec230d4a0b8ac9b0fa95d7ed.tar.bz2 |
go-gcc.cc (class Bvariable): Remove Gcc_tree parent class.
* go-gcc.cc (class Bvariable): Remove Gcc_tree parent class. Add
t_ and orig_type_ fields. Add new two parameter constructor. Add
get_tree and get_decl methods.
(Gcc_backend::var_expression): Pass location to var get_tree.
(Gcc_backend::global_variable): Don't add VIEW_CONVERT_EXPR. Use
two parameter constructor for Bvariable.
(Gcc_backend::global_variable_set_init): Don't remove
VIEW_CONVERT_EXPR. Use var get_decl, not get_tree.
(Gcc_backend::write_global_definitions): Likewise.
(Gcc_backend::init_statement): Call var get_decl, not get_tree.
(Gcc_backend::block): Likewise.
(Gcc_backend::implicit_variable_set_init): Likewise.
(Gcc_backend::immutable_struct_set_init): Likewise.
(Gcc_backend::function_set_parameters): Likewise.
From-SVN: r231894
-rw-r--r-- | gcc/go/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/go/go-gcc.cc | 89 |
2 files changed, 77 insertions, 29 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 2a011dd..a6a0aad 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,5 +1,22 @@ 2015-12-21 Ian Lance Taylor <iant@google.com> + * go-gcc.cc (class Bvariable): Remove Gcc_tree parent class. Add + t_ and orig_type_ fields. Add new two parameter constructor. Add + get_tree and get_decl methods. + (Gcc_backend::var_expression): Pass location to var get_tree. + (Gcc_backend::global_variable): Don't add VIEW_CONVERT_EXPR. Use + two parameter constructor for Bvariable. + (Gcc_backend::global_variable_set_init): Don't remove + VIEW_CONVERT_EXPR. Use var get_decl, not get_tree. + (Gcc_backend::write_global_definitions): Likewise. + (Gcc_backend::init_statement): Call var get_decl, not get_tree. + (Gcc_backend::block): Likewise. + (Gcc_backend::implicit_variable_set_init): Likewise. + (Gcc_backend::immutable_struct_set_init): Likewise. + (Gcc_backend::function_set_parameters): Likewise. + +2015-12-21 Ian Lance Taylor <iant@google.com> + * go-gcc.cc (Gcc_backend::global_variable): If type is zero-sized, add a VIEW_CONVERT_EXPR to the tree. (Gcc_backend::global_variable_set_init): Remove any diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index cb196b3..eac321b 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -109,22 +109,65 @@ class Bblock : public Gcc_tree { } }; -class Bvariable : public Gcc_tree +class Blabel : public Gcc_tree { public: - Bvariable(tree t) + Blabel(tree t) : Gcc_tree(t) { } }; -class Blabel : public Gcc_tree +// Bvariable is a bit more complicated, because of zero-sized types. +// The GNU linker does not permit dynamic variables with zero size. +// When we see such a variable, we generate a version of the type with +// non-zero size. However, when referring to the global variable, we +// want an expression of zero size; otherwise, if, say, the global +// variable is passed to a function, we will be passing a +// non-zero-sized value to a zero-sized value, which can lead to a +// miscompilation. + +class Bvariable { public: - Blabel(tree t) - : Gcc_tree(t) + Bvariable(tree t) + : t_(t), orig_type_(NULL) + { } + + Bvariable(tree t, tree orig_type) + : t_(t), orig_type_(orig_type) { } + + // Get the tree for use as an expression. + tree + get_tree(Location) const; + + // Get the actual decl; + tree + get_decl() const + { return this->t_; } + + private: + tree t_; + tree orig_type_; }; +// Get the tree of a variable for use as an expression. If this is a +// zero-sized global, create an expression that refers to the decl but +// has zero size. +tree +Bvariable::get_tree(Location location) const +{ + if (this->orig_type_ == NULL + || this->t_ == error_mark_node + || TREE_TYPE(this->t_) == this->orig_type_) + return this->t_; + // Return *(orig_type*)&decl. */ + tree t = build_fold_addr_expr_loc(location.gcc_location(), this->t_); + t = fold_build1_loc(location.gcc_location(), NOP_EXPR, + build_pointer_type(this->orig_type_), t); + return build_fold_indirect_ref_loc(location.gcc_location(), t); +} + // This file implements the interface between the Go frontend proper // and the gcc IR. This implements specific instantiations of // abstract classes defined by the Go frontend proper. The Go @@ -1158,9 +1201,9 @@ Gcc_backend::zero_expression(Btype* btype) // An expression that references a variable. Bexpression* -Gcc_backend::var_expression(Bvariable* var, Location) +Gcc_backend::var_expression(Bvariable* var, Location location) { - tree ret = var->get_tree(); + tree ret = var->get_tree(location); if (ret == error_mark_node) return this->error_expression(); return this->make_expression(ret); @@ -1894,7 +1937,7 @@ Gcc_backend::expression_statement(Bexpression* expr) Bstatement* Gcc_backend::init_statement(Bvariable* var, Bexpression* init) { - tree var_tree = var->get_tree(); + tree var_tree = var->get_decl(); tree init_tree = init->get_tree(); if (var_tree == error_mark_node || init_tree == error_mark_node) return this->error_statement(); @@ -2264,7 +2307,7 @@ Gcc_backend::block(Bfunction* function, Bblock* enclosing, pv != vars.end(); ++pv) { - *pp = (*pv)->get_tree(); + *pp = (*pv)->get_decl(); if (*pp != error_mark_node) pp = &DECL_CHAIN(*pp); } @@ -2420,11 +2463,7 @@ Gcc_backend::global_variable(const std::string& package_name, go_preserve_from_gc(decl); - if (orig_type_tree != type_tree) - decl = fold_build1_loc(location.gcc_location(), VIEW_CONVERT_EXPR, - orig_type_tree, decl); - - return new Bvariable(decl); + return new Bvariable(decl, orig_type_tree); } // Set the initial value of a global variable. @@ -2436,13 +2475,9 @@ Gcc_backend::global_variable_set_init(Bvariable* var, Bexpression* expr) if (expr_tree == error_mark_node) return; gcc_assert(TREE_CONSTANT(expr_tree)); - tree var_decl = var->get_tree(); + tree var_decl = var->get_decl(); if (var_decl == error_mark_node) return; - // Undo the VIEW_CONVERT_EXPR that may have been added by - // global_variable. - if (TREE_CODE(var_decl) == VIEW_CONVERT_EXPR) - var_decl = TREE_OPERAND(var_decl, 0); DECL_INITIAL(var_decl) = expr_tree; // If this variable goes in a unique section, it may need to go into @@ -2668,7 +2703,7 @@ Gcc_backend::implicit_variable_set_init(Bvariable* var, const std::string&, Btype*, bool, bool, bool is_common, Bexpression* init) { - tree decl = var->get_tree(); + tree decl = var->get_decl(); tree init_tree; if (init == NULL) init_tree = NULL_TREE; @@ -2762,7 +2797,7 @@ Gcc_backend::immutable_struct_set_init(Bvariable* var, const std::string&, bool, bool is_common, Btype*, Location, Bexpression* initializer) { - tree decl = var->get_tree(); + tree decl = var->get_decl(); tree init_tree = initializer->get_tree(); if (decl == error_mark_node || init_tree == error_mark_node) return; @@ -2981,7 +3016,7 @@ Gcc_backend::function_set_parameters(Bfunction* function, pv != param_vars.end(); ++pv) { - *pp = (*pv)->get_tree(); + *pp = (*pv)->get_decl(); gcc_assert(*pp != error_mark_node); pp = &DECL_CHAIN(*pp); } @@ -3037,14 +3072,10 @@ Gcc_backend::write_global_definitions( p != variable_decls.end(); ++p) { - if ((*p)->get_tree() != error_mark_node) + tree v = (*p)->get_decl(); + if (v != error_mark_node) { - tree t = (*p)->get_tree(); - // Undo the VIEW_CONVERT_EXPR that may have been added by - // global_variable. - if (TREE_CODE(t) == VIEW_CONVERT_EXPR) - t = TREE_OPERAND(t, 0); - defs[i] = t; + defs[i] = v; go_preserve_from_gc(defs[i]); ++i; } |