From 399f5feb92e4c588ec230d4a0b8ac9b0fa95d7ed Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 22 Dec 2015 01:58:17 +0000 Subject: [PATCH] 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 --- gcc/go/ChangeLog | 17 +++++++++ gcc/go/go-gcc.cc | 89 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 77 insertions(+), 29 deletions(-) diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 2a011ddc60e..a6a0aad9256 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,20 @@ +2015-12-21 Ian Lance Taylor + + * 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 * go-gcc.cc (Gcc_backend::global_variable): If type is zero-sized, diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index cb196b32fde..eac321b7bb2 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; } -- 2.30.2