Commit acf98146 by Ian Lance Taylor Committed by Ian Lance Taylor

Fix bug with taking address of a variable when address does not escape.

	* go-gcc.cc (Gcc_backend::local_variable): Add is_address_taken
	parameter.
	(Gcc_backend::parameter_variable): Likewise.

From-SVN: r173712
parent 1d15f620
2011-05-12 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::local_variable): Add is_address_taken
parameter.
(Gcc_backend::parameter_variable): Likewise.
2011-05-07 Eric Botcazou <ebotcazou@adacore.com>
* go-lang.c (global_bindings_p): Return bool and simplify.
......
......@@ -260,11 +260,11 @@ class Gcc_backend : public Backend
global_variable_set_init(Bvariable*, Bexpression*);
Bvariable*
local_variable(Bfunction*, const std::string& name, Btype* type,
local_variable(Bfunction*, const std::string&, Btype*, bool,
source_location);
Bvariable*
parameter_variable(Bfunction*, const std::string& name, Btype* type,
parameter_variable(Bfunction*, const std::string&, Btype*, bool,
source_location);
Bvariable*
......@@ -1074,7 +1074,8 @@ Gcc_backend::global_variable_set_init(Bvariable* var, Bexpression* expr)
Bvariable*
Gcc_backend::local_variable(Bfunction* function, const std::string& name,
Btype* btype, source_location location)
Btype* btype, bool is_address_taken,
source_location location)
{
tree type_tree = btype->get_tree();
if (type_tree == error_mark_node)
......@@ -1084,6 +1085,8 @@ 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;
go_preserve_from_gc(decl);
return new Bvariable(decl);
}
......@@ -1092,7 +1095,8 @@ Gcc_backend::local_variable(Bfunction* function, const std::string& name,
Bvariable*
Gcc_backend::parameter_variable(Bfunction* function, const std::string& name,
Btype* btype, source_location location)
Btype* btype, bool is_address_taken,
source_location location)
{
tree type_tree = btype->get_tree();
if (type_tree == error_mark_node)
......@@ -1103,6 +1107,8 @@ 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;
go_preserve_from_gc(decl);
return new Bvariable(decl);
}
......
......@@ -317,19 +317,23 @@ class Backend
// Create a local variable. The frontend will create the local
// variables first, and then create the block which contains them.
// FUNCTION is the function in which the variable is defined. NAME
// is the name of the variable. TYPE is the type. LOCATION is
// where the variable is defined. For each local variable the
// frontend will call init_statement to set the initial value.
// is the name of the variable. TYPE is the type. 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). 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,
source_location location) = 0;
bool is_address_taken, source_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, source_location location) = 0;
Btype* type, bool is_address_taken,
source_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
......
......@@ -958,13 +958,23 @@ void
Var_expression::do_address_taken(bool escapes)
{
if (!escapes)
;
else if (this->variable_->is_variable())
this->variable_->var_value()->set_address_taken();
else if (this->variable_->is_result_variable())
this->variable_->result_var_value()->set_address_taken();
{
if (this->variable_->is_variable())
this->variable_->var_value()->set_non_escaping_address_taken();
else if (this->variable_->is_result_variable())
this->variable_->result_var_value()->set_non_escaping_address_taken();
else
go_unreachable();
}
else
go_unreachable();
{
if (this->variable_->is_variable())
this->variable_->var_value()->set_address_taken();
else if (this->variable_->is_result_variable())
this->variable_->result_var_value()->set_address_taken();
else
go_unreachable();
}
}
// Get the tree for a reference to a variable.
......
......@@ -3333,10 +3333,11 @@ Variable::Variable(Type* type, Expression* init, bool is_global,
: type_(type), init_(init), preinit_(NULL), location_(location),
backend_(NULL), is_global_(is_global), is_parameter_(is_parameter),
is_receiver_(is_receiver), is_varargs_parameter_(false),
is_address_taken_(false), seen_(false), init_is_lowered_(false),
type_from_init_tuple_(false), type_from_range_index_(false),
type_from_range_value_(false), type_from_chan_element_(false),
is_type_switch_var_(false), determined_type_(false)
is_address_taken_(false), is_non_escaping_address_taken_(false),
seen_(false), init_is_lowered_(false), type_from_init_tuple_(false),
type_from_range_index_(false), type_from_range_value_(false),
type_from_chan_element_(false), is_type_switch_var_(false),
determined_type_(false)
{
go_assert(type != NULL || init != NULL);
go_assert(!is_parameter || init == NULL);
......@@ -3722,11 +3723,15 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
{
tree fndecl = function->func_value()->get_decl();
Bfunction* bfunction = tree_to_function(fndecl);
bool is_address_taken = (this->is_non_escaping_address_taken_
&& !this->is_in_heap());
if (is_parameter)
bvar = backend->parameter_variable(bfunction, n, btype,
is_address_taken,
this->location_);
else
bvar = backend->local_variable(bfunction, n, btype,
is_address_taken,
this->location_);
}
this->backend_ = bvar;
......@@ -3757,7 +3762,10 @@ Result_variable::get_backend_variable(Gogo* gogo, Named_object* function,
tree fndecl = function->func_value()->get_decl();
Bfunction* bfunction = tree_to_function(fndecl);
std::string n = Gogo::unpack_hidden_name(name);
bool is_address_taken = (this->is_non_escaping_address_taken_
&& !this->is_in_heap());
this->backend_ = backend->local_variable(bfunction, n, btype,
is_address_taken,
this->location_);
}
}
......
......@@ -1160,6 +1160,22 @@ class Variable
is_in_heap() const
{ return this->is_address_taken_ && !this->is_global_; }
// Note that something takes the address of this variable.
void
set_address_taken()
{ this->is_address_taken_ = true; }
// Return whether the address is taken but does not escape.
bool
is_non_escaping_address_taken() const
{ return this->is_non_escaping_address_taken_; }
// Note that something takes the address of this variable such that
// the address does not escape the function.
void
set_non_escaping_address_taken()
{ this->is_non_escaping_address_taken_ = true; }
// Get the source location of the variable's declaration.
source_location
location() const
......@@ -1252,11 +1268,6 @@ class Variable
void
determine_type();
// Note that something takes the address of this variable.
void
set_address_taken()
{ this->is_address_taken_ = true; }
// Get the backend representation of the variable.
Bvariable*
get_backend_variable(Gogo*, Named_object*, const Package*,
......@@ -1314,8 +1325,13 @@ class Variable
bool is_receiver_ : 1;
// Whether this is the varargs parameter of a function.
bool is_varargs_parameter_ : 1;
// Whether something takes the address of this variable.
// Whether something takes the address of this variable. For a
// local variable this implies that the variable has to be on the
// heap.
bool is_address_taken_ : 1;
// Whether something takes the address of this variable such that
// the address does not escape the function.
bool is_non_escaping_address_taken_ : 1;
// True if we have seen this variable in a traversal.
bool seen_ : 1;
// True if we have lowered the initialization expression.
......@@ -1343,7 +1359,8 @@ class Result_variable
Result_variable(Type* type, Function* function, int index,
source_location location)
: type_(type), function_(function), index_(index), location_(location),
backend_(NULL), is_address_taken_(false)
backend_(NULL), is_address_taken_(false),
is_non_escaping_address_taken_(false)
{ }
// Get the type of the result variable.
......@@ -1376,6 +1393,17 @@ class Result_variable
set_address_taken()
{ this->is_address_taken_ = true; }
// Return whether the address is taken but does not escape.
bool
is_non_escaping_address_taken() const
{ return this->is_non_escaping_address_taken_; }
// Note that something takes the address of this variable such that
// the address does not escape the function.
void
set_non_escaping_address_taken()
{ this->is_non_escaping_address_taken_ = true; }
// Whether this variable should live in the heap.
bool
is_in_heap() const
......@@ -1404,6 +1432,9 @@ class Result_variable
Bvariable* backend_;
// Whether something takes the address of this variable.
bool is_address_taken_;
// Whether something takes the address of this variable such that
// the address does not escape the function.
bool is_non_escaping_address_taken_;
};
// The value we keep for a named constant. This lets us hold a type
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment