Commit e09ce6c5 by Ian Lance Taylor Committed by Ian Lance Taylor

Use backend interface for variables.

	* go-gcc.cc: Include "go-c.h".
	(class Bvariable): Define.
	(Gcc_backend::init_statement): New function.
	(Gcc_backend::global_variable): New function.
	(Gcc_backend::global_variable_set_init): New function.
	(Gcc_backend::local_variable): New function.
	(Gcc_backend::parameter_variable): New function.
	(tree_to_type, var_to_tree): New functions.
	* Make-lang.in (go/go-gcc.o): Depend on $(GO_C_H).
	* (go/gogo-tree.o): Depend on go/gofrontend/backend.h.

From-SVN: r172693
parent 61bd5ad8
2011-04-18 Ian Lance Taylor <iant@google.com>
* go-gcc.cc: Include "go-c.h".
(class Bvariable): Define.
(Gcc_backend::init_statement): New function.
(Gcc_backend::global_variable): New function.
(Gcc_backend::global_variable_set_init): New function.
(Gcc_backend::local_variable): New function.
(Gcc_backend::parameter_variable): New function.
(tree_to_type, var_to_tree): New functions.
* Make-lang.in (go/go-gcc.o): Depend on $(GO_C_H).
* (go/gogo-tree.o): Depend on go/gofrontend/backend.h.
2011-04-15 Ian Lance Taylor <iant@google.com> 2011-04-15 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::compound_statement): New function. * go-gcc.cc (Gcc_backend::compound_statement): New function.
......
...@@ -239,7 +239,7 @@ go/go-lang.o: go/go-lang.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(OPTS_H) \ ...@@ -239,7 +239,7 @@ go/go-lang.o: go/go-lang.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(OPTS_H) \
GOINCLUDES = -I $(srcdir)/go -I $(srcdir)/go/gofrontend GOINCLUDES = -I $(srcdir)/go -I $(srcdir)/go/gofrontend
go/go-gcc.o: go/go-gcc.cc $(GO_SYSTEM_H) $(TREE_H) tree-iterator.h \ go/go-gcc.o: go/go-gcc.cc $(GO_SYSTEM_H) $(TREE_H) tree-iterator.h \
$(GIMPLE_H) $(GO_GOGO_H) go/gofrontend/backend.h $(GIMPLE_H) $(GO_C_H) $(GO_GOGO_H) go/gofrontend/backend.h
$(CXX) -c $(GOINCLUDES) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< $(OUTPUT_OPTION) $(CXX) -c $(GOINCLUDES) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< $(OUTPUT_OPTION)
go/%.o: go/gofrontend/%.cc go/%.o: go/gofrontend/%.cc
...@@ -262,7 +262,8 @@ go/go-dump.o: go/gofrontend/go-dump.cc $(GO_SYSTEM_H) $(GO_C_H) \ ...@@ -262,7 +262,8 @@ go/go-dump.o: go/gofrontend/go-dump.cc $(GO_SYSTEM_H) $(GO_C_H) \
go/gogo-tree.o: go/gofrontend/gogo-tree.cc $(GO_SYSTEM_H) $(TOPLEV_H) \ go/gogo-tree.o: go/gofrontend/gogo-tree.cc $(GO_SYSTEM_H) $(TOPLEV_H) \
$(TREE_H) $(GIMPLE_H) tree-iterator.h $(CGRAPH_H) langhooks.h \ $(TREE_H) $(GIMPLE_H) tree-iterator.h $(CGRAPH_H) langhooks.h \
convert.h output.h $(DIAGNOSTIC_H) $(GO_TYPES_H) \ convert.h output.h $(DIAGNOSTIC_H) $(GO_TYPES_H) \
$(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) $(GO_RUNTIME_H) $(GO_GOGO_H) $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) $(GO_RUNTIME_H) \
go/gofrontend/backend.h $(GO_GOGO_H)
go/gogo.o: go/gofrontend/gogo.cc $(GO_SYSTEM_H) $(GO_C_H) \ go/gogo.o: go/gofrontend/gogo.cc $(GO_SYSTEM_H) $(GO_C_H) \
go/gofrontend/go-dump.h $(GO_LEX_H) $(GO_TYPES_H) $(GO_STATEMENTS_H) \ go/gofrontend/go-dump.h $(GO_LEX_H) $(GO_TYPES_H) $(GO_STATEMENTS_H) \
$(GO_EXPRESSIONS_H) go/gofrontend/dataflow.h $(GO_RUNTIME_H) \ $(GO_EXPRESSIONS_H) go/gofrontend/dataflow.h $(GO_RUNTIME_H) \
......
...@@ -37,6 +37,8 @@ extern "C" ...@@ -37,6 +37,8 @@ extern "C"
} }
#endif #endif
#include "go-c.h"
#include "gogo.h" #include "gogo.h"
#include "backend.h" #include "backend.h"
...@@ -90,6 +92,14 @@ class Bfunction : public Gcc_tree ...@@ -90,6 +92,14 @@ class Bfunction : public Gcc_tree
{ } { }
}; };
class Bvariable : public Gcc_tree
{
public:
Bvariable(tree t)
: Gcc_tree(t)
{ }
};
class Blabel : public Gcc_tree class Blabel : public Gcc_tree
{ {
public: public:
...@@ -174,6 +184,9 @@ class Gcc_backend : public Backend ...@@ -174,6 +184,9 @@ class Gcc_backend : public Backend
expression_statement(Bexpression*); expression_statement(Bexpression*);
Bstatement* Bstatement*
init_statement(Bvariable* var, Bexpression* init);
Bstatement*
assignment_statement(Bexpression* lhs, Bexpression* rhs, source_location); assignment_statement(Bexpression* lhs, Bexpression* rhs, source_location);
Bstatement* Bstatement*
...@@ -196,6 +209,32 @@ class Gcc_backend : public Backend ...@@ -196,6 +209,32 @@ class Gcc_backend : public Backend
Bstatement* Bstatement*
statement_list(const std::vector<Bstatement*>&); statement_list(const std::vector<Bstatement*>&);
// Variables.
Bvariable*
error_variable()
{ return new Bvariable(error_mark_node); }
Bvariable*
global_variable(const std::string& package_name,
const std::string& unique_prefix,
const std::string& name,
Btype* btype,
bool is_external,
bool is_hidden,
source_location location);
void
global_variable_set_init(Bvariable*, Bexpression*);
Bvariable*
local_variable(Bfunction*, const std::string& name, Btype* type,
source_location);
Bvariable*
parameter_variable(Bfunction*, const std::string& name, Btype* type,
source_location);
// Labels. // Labels.
Blabel* Blabel*
...@@ -238,6 +277,21 @@ Gcc_backend::expression_statement(Bexpression* expr) ...@@ -238,6 +277,21 @@ Gcc_backend::expression_statement(Bexpression* expr)
return this->make_statement(expr->get_tree()); return this->make_statement(expr->get_tree());
} }
// Variable initialization.
Bstatement*
Gcc_backend::init_statement(Bvariable* var, Bexpression* init)
{
tree var_tree = var->get_tree();
tree init_tree = init->get_tree();
if (var_tree == error_mark_node || init_tree == error_mark_node)
return this->error_statement();
gcc_assert(TREE_CODE(var_tree) == VAR_DECL);
DECL_INITIAL(var_tree) = init_tree;
return this->make_statement(build1_loc(DECL_SOURCE_LOCATION(var_tree),
DECL_EXPR, void_type_node, var_tree));
}
// Assignment. // Assignment.
Bstatement* Bstatement*
...@@ -427,6 +481,99 @@ Gcc_backend::statement_list(const std::vector<Bstatement*>& statements) ...@@ -427,6 +481,99 @@ Gcc_backend::statement_list(const std::vector<Bstatement*>& statements)
return this->make_statement(stmt_list); return this->make_statement(stmt_list);
} }
// Make a global variable.
Bvariable*
Gcc_backend::global_variable(const std::string& package_name,
const std::string& unique_prefix,
const std::string& name,
Btype* btype,
bool is_external,
bool is_hidden,
source_location location)
{
tree type_tree = btype->get_tree();
if (type_tree == error_mark_node)
return this->error_variable();
std::string var_name(package_name);
var_name.push_back('.');
var_name.append(name);
tree decl = build_decl(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)
{
TREE_PUBLIC(decl) = 1;
std::string asm_name(unique_prefix);
asm_name.push_back('.');
asm_name.append(var_name);
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
}
TREE_USED(decl) = 1;
go_preserve_from_gc(decl);
return new Bvariable(decl);
}
// Set the initial value of a global variable.
void
Gcc_backend::global_variable_set_init(Bvariable* var, Bexpression* expr)
{
tree expr_tree = expr->get_tree();
if (expr_tree == error_mark_node)
return;
gcc_assert(TREE_CONSTANT(expr_tree));
tree var_decl = var->get_tree();
if (var_decl == error_mark_node)
return;
DECL_INITIAL(var_decl) = expr_tree;
}
// Make a local variable.
Bvariable*
Gcc_backend::local_variable(Bfunction* function, const std::string& name,
Btype* btype, source_location location)
{
tree type_tree = btype->get_tree();
if (type_tree == error_mark_node)
return this->error_variable();
tree decl = build_decl(location, VAR_DECL,
get_identifier_from_string(name),
type_tree);
DECL_CONTEXT(decl) = function->get_tree();
TREE_USED(decl) = 1;
go_preserve_from_gc(decl);
return new Bvariable(decl);
}
// Make a function parameter variable.
Bvariable*
Gcc_backend::parameter_variable(Bfunction* function, const std::string& name,
Btype* btype, source_location location)
{
tree type_tree = btype->get_tree();
if (type_tree == error_mark_node)
return this->error_variable();
tree decl = build_decl(location, PARM_DECL,
get_identifier_from_string(name),
type_tree);
DECL_CONTEXT(decl) = function->get_tree();
DECL_ARG_TYPE(decl) = type_tree;
TREE_USED(decl) = 1;
go_preserve_from_gc(decl);
return new Bvariable(decl);
}
// Make a label. // Make a label.
Blabel* Blabel*
...@@ -494,6 +641,12 @@ go_get_backend() ...@@ -494,6 +641,12 @@ go_get_backend()
// FIXME: Temporary functions while converting to the new backend // FIXME: Temporary functions while converting to the new backend
// interface. // interface.
Btype*
tree_to_type(tree t)
{
return new Btype(t);
}
Bexpression* Bexpression*
tree_to_expr(tree t) tree_to_expr(tree t)
{ {
...@@ -523,3 +676,9 @@ stat_to_tree(Bstatement* bs) ...@@ -523,3 +676,9 @@ stat_to_tree(Bstatement* bs)
{ {
return bs->get_tree(); return bs->get_tree();
} }
tree
var_to_tree(Bvariable* bv)
{
return bv->get_tree();
}
...@@ -27,6 +27,9 @@ class Bstatement; ...@@ -27,6 +27,9 @@ class Bstatement;
// The backend representation of a function definition. // The backend representation of a function definition.
class Bfunction; class Bfunction;
// The backend representation of a variable.
class Bvariable;
// The backend representation of a label. // The backend representation of a label.
class Blabel; class Blabel;
...@@ -117,6 +120,12 @@ class Backend ...@@ -117,6 +120,12 @@ class Backend
virtual Bstatement* virtual Bstatement*
expression_statement(Bexpression*) = 0; expression_statement(Bexpression*) = 0;
// Create a variable initialization statement. This initializes a
// local variable at the point in the program flow where it is
// declared.
virtual Bstatement*
init_statement(Bvariable* var, Bexpression* init) = 0;
// Create an assignment statement. // Create an assignment statement.
virtual Bstatement* virtual Bstatement*
assignment_statement(Bexpression* lhs, Bexpression* rhs, assignment_statement(Bexpression* lhs, Bexpression* rhs,
...@@ -154,6 +163,57 @@ class Backend ...@@ -154,6 +163,57 @@ class Backend
virtual Bstatement* virtual Bstatement*
statement_list(const std::vector<Bstatement*>&) = 0; statement_list(const std::vector<Bstatement*>&) = 0;
// Variables.
// Create an error variable. This is used for cases which should
// not occur in a correct program, in order to keep the compilation
// going without crashing.
virtual Bvariable*
error_variable() = 0;
// Create a global variable. PACKAGE_NAME is the name of the
// package where the variable is defined. UNIQUE_PREFIX is the
// prefix for that package, from the -fgo-prefix option. NAME is
// the name of the variable. 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). LOCATION is where the variable
// was defined.
virtual Bvariable*
global_variable(const std::string& package_name,
const std::string& unique_prefix,
const std::string& name,
Btype* btype,
bool is_external,
bool is_hidden,
source_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
// function. In case 2, the frontend will call
// global_variable_set_init to set the initial value. If this is
// not called, the backend should initialize a global variable to 0.
// The init function may then assign a value to it.
virtual void
global_variable_set_init(Bvariable*, Bexpression*) = 0;
// 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.
virtual Bvariable*
local_variable(Bfunction* function, const std::string& name, Btype* type,
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;
// Labels. // Labels.
// Create a new label. NAME will be empty if this is a label // Create a new label. NAME will be empty if this is a label
...@@ -186,10 +246,12 @@ extern Backend* go_get_backend(); ...@@ -186,10 +246,12 @@ extern Backend* go_get_backend();
// FIXME: Temporary helper functions while converting to new backend // FIXME: Temporary helper functions while converting to new backend
// interface. // interface.
extern Btype* tree_to_type(tree);
extern Bexpression* tree_to_expr(tree); extern Bexpression* tree_to_expr(tree);
extern Bstatement* tree_to_stat(tree); extern Bstatement* tree_to_stat(tree);
extern Bfunction* tree_to_function(tree); extern Bfunction* tree_to_function(tree);
extern tree expr_to_tree(Bexpression*); extern tree expr_to_tree(Bexpression*);
extern tree stat_to_tree(Bstatement*); extern tree stat_to_tree(Bstatement*);
extern tree var_to_tree(Bvariable*);
#endif // !defined(GO_BACKEND_H) #endif // !defined(GO_BACKEND_H)
...@@ -972,7 +972,24 @@ Var_expression::do_address_taken(bool escapes) ...@@ -972,7 +972,24 @@ Var_expression::do_address_taken(bool escapes)
tree tree
Var_expression::do_get_tree(Translate_context* context) Var_expression::do_get_tree(Translate_context* context)
{ {
return this->variable_->get_tree(context->gogo(), context->function()); Bvariable* bvar = this->variable_->get_backend_variable(context->gogo(),
context->function());
tree ret = var_to_tree(bvar);
if (ret == error_mark_node)
return error_mark_node;
bool is_in_heap;
if (this->variable_->is_variable())
is_in_heap = this->variable_->var_value()->is_in_heap();
else if (this->variable_->is_result_variable())
is_in_heap = this->variable_->result_var_value()->is_in_heap();
else
gcc_unreachable();
if (is_in_heap)
{
ret = build_fold_indirect_ref_loc(this->location(), ret);
TREE_THIS_NOTRAP(ret) = 1;
}
return ret;
} }
// Make a reference to a variable in an expression. // Make a reference to a variable in an expression.
......
...@@ -32,6 +32,7 @@ extern "C" ...@@ -32,6 +32,7 @@ extern "C"
#include "expressions.h" #include "expressions.h"
#include "statements.h" #include "statements.h"
#include "runtime.h" #include "runtime.h"
#include "backend.h"
#include "gogo.h" #include "gogo.h"
// Whether we have seen any errors. // Whether we have seen any errors.
...@@ -277,7 +278,8 @@ Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc, ...@@ -277,7 +278,8 @@ Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc,
constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL); constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
tree field = TYPE_FIELDS(root_type); tree field = TYPE_FIELDS(root_type);
elt->index = field; elt->index = field;
tree decl = (*p)->get_tree(this, NULL); Bvariable* bvar = (*p)->get_backend_variable(this, NULL);
tree decl = var_to_tree(bvar);
gcc_assert(TREE_CODE(decl) == VAR_DECL); gcc_assert(TREE_CODE(decl) == VAR_DECL);
elt->value = build_fold_addr_expr(decl); elt->value = build_fold_addr_expr(decl);
...@@ -704,24 +706,31 @@ Gogo::write_globals() ...@@ -704,24 +706,31 @@ Gogo::write_globals()
} }
} }
vec[i] = no->get_tree(this, NULL); if (!no->is_variable())
if (vec[i] == error_mark_node)
{ {
gcc_assert(saw_errors()); vec[i] = no->get_tree(this, NULL);
--i; if (vec[i] == error_mark_node)
--count; {
continue; gcc_assert(saw_errors());
--i;
--count;
continue;
}
} }
else
// If a variable is initialized to a non-constant value, do the
// initialization in an initialization function.
if (TREE_CODE(vec[i]) == VAR_DECL)
{ {
gcc_assert(no->is_variable()); Bvariable* var = no->get_backend_variable(this, NULL);
vec[i] = var_to_tree(var);
if (vec[i] == error_mark_node)
{
gcc_assert(saw_errors());
--i;
--count;
continue;
}
// Check for a sink variable, which may be used to run // Check for a sink variable, which may be used to run an
// an initializer purely for its side effects. // initializer purely for its side effects.
bool is_sink = no->name()[0] == '_' && no->name()[1] == '.'; bool is_sink = no->name()[0] == '_' && no->name()[1] == '.';
tree var_init_tree = NULL_TREE; tree var_init_tree = NULL_TREE;
...@@ -733,7 +742,8 @@ Gogo::write_globals() ...@@ -733,7 +742,8 @@ Gogo::write_globals()
else if (init == NULL_TREE) else if (init == NULL_TREE)
; ;
else if (TREE_CONSTANT(init)) else if (TREE_CONSTANT(init))
DECL_INITIAL(vec[i]) = init; this->backend()->global_variable_set_init(var,
tree_to_expr(init));
else if (is_sink) else if (is_sink)
var_init_tree = init; var_init_tree = init;
else else
...@@ -828,16 +838,15 @@ Gogo::write_globals() ...@@ -828,16 +838,15 @@ Gogo::write_globals()
tree tree
Named_object::get_id(Gogo* gogo) Named_object::get_id(Gogo* gogo)
{ {
gcc_assert(!this->is_variable() && !this->is_result_variable());
std::string decl_name; std::string decl_name;
if (this->is_function_declaration() if (this->is_function_declaration()
&& !this->func_declaration_value()->asm_name().empty()) && !this->func_declaration_value()->asm_name().empty())
decl_name = this->func_declaration_value()->asm_name(); decl_name = this->func_declaration_value()->asm_name();
else if ((this->is_variable() && !this->var_value()->is_global()) else if (this->is_type()
|| (this->is_type() && this->type_value()->location() == BUILTINS_LOCATION)
&& this->type_value()->location() == BUILTINS_LOCATION))
{ {
// We don't need the package name for local variables or builtin // We don't need the package name for builtin types.
// types.
decl_name = Gogo::unpack_hidden_name(this->name_); decl_name = Gogo::unpack_hidden_name(this->name_);
} }
else else
...@@ -878,22 +887,7 @@ tree ...@@ -878,22 +887,7 @@ tree
Named_object::get_tree(Gogo* gogo, Named_object* function) Named_object::get_tree(Gogo* gogo, Named_object* function)
{ {
if (this->tree_ != NULL_TREE) if (this->tree_ != NULL_TREE)
{ return this->tree_;
// If this is a variable whose address is taken, we must rebuild
// the INDIRECT_REF each time to avoid invalid sharing.
tree ret = this->tree_;
if (((this->classification_ == NAMED_OBJECT_VAR
&& this->var_value()->is_in_heap())
|| (this->classification_ == NAMED_OBJECT_RESULT_VAR
&& this->result_var_value()->is_in_heap()))
&& ret != error_mark_node)
{
gcc_assert(TREE_CODE(ret) == INDIRECT_REF);
ret = build_fold_indirect_ref(TREE_OPERAND(ret, 0));
TREE_THIS_NOTRAP(ret) = 1;
}
return ret;
}
tree name; tree name;
if (this->classification_ == NAMED_OBJECT_TYPE) if (this->classification_ == NAMED_OBJECT_TYPE)
...@@ -976,117 +970,7 @@ Named_object::get_tree(Gogo* gogo, Named_object* function) ...@@ -976,117 +970,7 @@ Named_object::get_tree(Gogo* gogo, Named_object* function)
return error_mark_node; return error_mark_node;
case NAMED_OBJECT_VAR: case NAMED_OBJECT_VAR:
{
Variable* var = this->u_.var_value;
Type* type = var->type();
if (type->is_error_type()
|| (type->is_undefined()
&& (!var->is_global() || this->package() == NULL)))
{
// Force the error for an undefined type, just in case.
type->base();
decl = error_mark_node;
}
else
{
tree var_type = type->get_tree(gogo);
bool is_parameter = var->is_parameter();
if (var->is_receiver() && type->points_to() == NULL)
is_parameter = false;
if (var->is_in_heap())
{
is_parameter = false;
var_type = build_pointer_type(var_type);
}
decl = build_decl(var->location(),
is_parameter ? PARM_DECL : VAR_DECL,
name, var_type);
if (!var->is_global())
{
tree fnid = function->get_id(gogo);
tree fndecl = function->func_value()->get_or_make_decl(gogo,
function,
fnid);
DECL_CONTEXT(decl) = fndecl;
}
if (is_parameter)
DECL_ARG_TYPE(decl) = TREE_TYPE(decl);
if (var->is_global())
{
const Package* package = this->package();
if (package == NULL)
TREE_STATIC(decl) = 1;
else
DECL_EXTERNAL(decl) = 1;
if (!Gogo::is_hidden_name(this->name_))
{
TREE_PUBLIC(decl) = 1;
std::string asm_name = (package == NULL
? gogo->unique_prefix()
: package->unique_prefix());
asm_name.append(1, '.');
asm_name.append(IDENTIFIER_POINTER(name),
IDENTIFIER_LENGTH(name));
tree asm_id = get_identifier_from_string(asm_name);
SET_DECL_ASSEMBLER_NAME(decl, asm_id);
}
}
// FIXME: We should only set this for variables which are
// actually used somewhere.
TREE_USED(decl) = 1;
}
}
break;
case NAMED_OBJECT_RESULT_VAR: case NAMED_OBJECT_RESULT_VAR:
{
Result_variable* result = this->u_.result_var_value;
Type* type = result->type();
if (type->is_error())
decl = error_mark_node;
else
{
gcc_assert(result->function() == function->func_value());
source_location loc = function->location();
tree result_type = type->get_tree(gogo);
tree init;
if (!result->is_in_heap())
init = type->get_init_tree(gogo, false);
else
{
tree space = gogo->allocate_memory(type,
TYPE_SIZE_UNIT(result_type),
loc);
result_type = build_pointer_type(result_type);
tree subinit = type->get_init_tree(gogo, true);
if (subinit == NULL_TREE)
init = fold_convert_loc(loc, result_type, space);
else
{
space = save_expr(space);
space = fold_convert_loc(loc, result_type, space);
tree spaceref = build_fold_indirect_ref_loc(loc, space);
TREE_THIS_NOTRAP(spaceref) = 1;
tree set = fold_build2_loc(loc, MODIFY_EXPR, void_type_node,
spaceref, subinit);
init = fold_build2_loc(loc, COMPOUND_EXPR, TREE_TYPE(space),
set, space);
}
}
decl = build_decl(loc, VAR_DECL, name, result_type);
tree fnid = function->get_id(gogo);
tree fndecl = function->func_value()->get_or_make_decl(gogo,
function,
fnid);
DECL_CONTEXT(decl) = fndecl;
DECL_INITIAL(decl) = init;
TREE_USED(decl) = 1;
}
}
break;
case NAMED_OBJECT_SINK: case NAMED_OBJECT_SINK:
gcc_unreachable(); gcc_unreachable();
...@@ -1129,20 +1013,6 @@ Named_object::get_tree(Gogo* gogo, Named_object* function) ...@@ -1129,20 +1013,6 @@ Named_object::get_tree(Gogo* gogo, Named_object* function)
tree ret = decl; tree ret = decl;
// If this is a local variable whose address is taken, then we
// actually store it in the heap. For uses of the variable we need
// to return a reference to that heap location.
if (((this->classification_ == NAMED_OBJECT_VAR
&& this->var_value()->is_in_heap())
|| (this->classification_ == NAMED_OBJECT_RESULT_VAR
&& this->result_var_value()->is_in_heap()))
&& ret != error_mark_node)
{
gcc_assert(POINTER_TYPE_P(TREE_TYPE(ret)));
ret = build_fold_indirect_ref(ret);
TREE_THIS_NOTRAP(ret) = 1;
}
this->tree_ = ret; this->tree_ = ret;
if (ret != error_mark_node) if (ret != error_mark_node)
...@@ -1162,7 +1032,9 @@ Variable::get_init_tree(Gogo* gogo, Named_object* function) ...@@ -1162,7 +1032,9 @@ Variable::get_init_tree(Gogo* gogo, Named_object* function)
if (this->init_ == NULL) if (this->init_ == NULL)
{ {
gcc_assert(!this->is_parameter_); gcc_assert(!this->is_parameter_);
return this->type_->get_init_tree(gogo, this->is_global_); return this->type_->get_init_tree(gogo,
(this->is_global_
|| this->is_in_heap()));
} }
else else
{ {
...@@ -1301,7 +1173,9 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no, tree id) ...@@ -1301,7 +1173,9 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no, tree id)
{ {
push_struct_function(decl); push_struct_function(decl);
tree closure_decl = this->closure_var_->get_tree(gogo, no); Bvariable* bvar = this->closure_var_->get_backend_variable(gogo,
no);
tree closure_decl = var_to_tree(bvar);
if (closure_decl == error_mark_node) if (closure_decl == error_mark_node)
this->fndecl_ = error_mark_node; this->fndecl_ = error_mark_node;
else else
...@@ -1384,26 +1258,15 @@ Function::make_receiver_parm_decl(Gogo* gogo, Named_object* no, tree var_decl) ...@@ -1384,26 +1258,15 @@ Function::make_receiver_parm_decl(Gogo* gogo, Named_object* no, tree var_decl)
{ {
if (var_decl == error_mark_node) if (var_decl == error_mark_node)
return error_mark_node; return error_mark_node;
// If the function takes the address of a receiver which is passed gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
// by value, then we will have an INDIRECT_REF here. We need to get tree val_type = TREE_TYPE(var_decl);
// the real variable.
bool is_in_heap = no->var_value()->is_in_heap(); bool is_in_heap = no->var_value()->is_in_heap();
tree val_type; if (is_in_heap)
if (TREE_CODE(var_decl) != INDIRECT_REF)
{
gcc_assert(!is_in_heap);
val_type = TREE_TYPE(var_decl);
}
else
{ {
gcc_assert(is_in_heap); gcc_assert(POINTER_TYPE_P(val_type));
var_decl = TREE_OPERAND(var_decl, 0); val_type = TREE_TYPE(val_type);
if (var_decl == error_mark_node)
return error_mark_node;
gcc_assert(POINTER_TYPE_P(TREE_TYPE(var_decl)));
val_type = TREE_TYPE(TREE_TYPE(var_decl));
} }
gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
source_location loc = DECL_SOURCE_LOCATION(var_decl); source_location loc = DECL_SOURCE_LOCATION(var_decl);
std::string name = IDENTIFIER_POINTER(DECL_NAME(var_decl)); std::string name = IDENTIFIER_POINTER(DECL_NAME(var_decl));
name += ".pointer"; name += ".pointer";
...@@ -1456,14 +1319,8 @@ Function::make_receiver_parm_decl(Gogo* gogo, Named_object* no, tree var_decl) ...@@ -1456,14 +1319,8 @@ Function::make_receiver_parm_decl(Gogo* gogo, Named_object* no, tree var_decl)
// indirection. // indirection.
tree tree
Function::copy_parm_to_heap(Gogo* gogo, Named_object* no, tree ref) Function::copy_parm_to_heap(Gogo* gogo, Named_object* no, tree var_decl)
{ {
if (ref == error_mark_node)
return error_mark_node;
gcc_assert(TREE_CODE(ref) == INDIRECT_REF);
tree var_decl = TREE_OPERAND(ref, 0);
if (var_decl == error_mark_node) if (var_decl == error_mark_node)
return error_mark_node; return error_mark_node;
gcc_assert(TREE_CODE(var_decl) == VAR_DECL); gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
...@@ -1514,7 +1371,8 @@ Function::build_tree(Gogo* gogo, Named_object* named_function) ...@@ -1514,7 +1371,8 @@ Function::build_tree(Gogo* gogo, Named_object* named_function)
{ {
if ((*p)->is_variable() && (*p)->var_value()->is_parameter()) if ((*p)->is_variable() && (*p)->var_value()->is_parameter())
{ {
*pp = (*p)->get_tree(gogo, named_function); Bvariable* bvar = (*p)->get_backend_variable(gogo, named_function);
*pp = var_to_tree(bvar);
// We always pass the receiver to a method as a pointer. If // We always pass the receiver to a method as a pointer. If
// the receiver is declared as a non-pointer type, then we // the receiver is declared as a non-pointer type, then we
...@@ -1524,8 +1382,6 @@ Function::build_tree(Gogo* gogo, Named_object* named_function) ...@@ -1524,8 +1382,6 @@ Function::build_tree(Gogo* gogo, Named_object* named_function)
{ {
tree parm_decl = this->make_receiver_parm_decl(gogo, *p, *pp); tree parm_decl = this->make_receiver_parm_decl(gogo, *p, *pp);
tree var = *pp; tree var = *pp;
if (TREE_CODE(var) == INDIRECT_REF)
var = TREE_OPERAND(var, 0);
if (var != error_mark_node) if (var != error_mark_node)
{ {
gcc_assert(TREE_CODE(var) == VAR_DECL); gcc_assert(TREE_CODE(var) == VAR_DECL);
...@@ -1539,16 +1395,12 @@ Function::build_tree(Gogo* gogo, Named_object* named_function) ...@@ -1539,16 +1395,12 @@ Function::build_tree(Gogo* gogo, Named_object* named_function)
// If we take the address of a parameter, then we need // If we take the address of a parameter, then we need
// to copy it into the heap. // to copy it into the heap.
tree parm_decl = this->copy_parm_to_heap(gogo, *p, *pp); tree parm_decl = this->copy_parm_to_heap(gogo, *p, *pp);
if (*pp != error_mark_node) tree var = *pp;
if (var != error_mark_node)
{ {
gcc_assert(TREE_CODE(*pp) == INDIRECT_REF); gcc_assert(TREE_CODE(var) == VAR_DECL);
tree var_decl = TREE_OPERAND(*pp, 0); DECL_CHAIN(var) = declare_vars;
if (var_decl != error_mark_node) declare_vars = var;
{
gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
DECL_CHAIN(var_decl) = declare_vars;
declare_vars = var_decl;
}
} }
*pp = parm_decl; *pp = parm_decl;
} }
...@@ -1561,16 +1413,41 @@ Function::build_tree(Gogo* gogo, Named_object* named_function) ...@@ -1561,16 +1413,41 @@ Function::build_tree(Gogo* gogo, Named_object* named_function)
} }
else if ((*p)->is_result_variable()) else if ((*p)->is_result_variable())
{ {
tree var_decl = (*p)->get_tree(gogo, named_function); Bvariable* bvar = (*p)->get_backend_variable(gogo, named_function);
if (var_decl != error_mark_node tree var_decl = var_to_tree(bvar);
&& (*p)->result_var_value()->is_in_heap())
Type* type = (*p)->result_var_value()->type();
tree init;
if (!(*p)->result_var_value()->is_in_heap())
init = type->get_init_tree(gogo, false);
else
{ {
gcc_assert(TREE_CODE(var_decl) == INDIRECT_REF); source_location loc = (*p)->location();
var_decl = TREE_OPERAND(var_decl, 0); tree type_tree = type->get_tree(gogo);
tree space = gogo->allocate_memory(type,
TYPE_SIZE_UNIT(type_tree),
loc);
tree ptr_type_tree = build_pointer_type(type_tree);
tree subinit = type->get_init_tree(gogo, true);
if (subinit == NULL_TREE)
init = fold_convert_loc(loc, ptr_type_tree, space);
else
{
space = save_expr(space);
space = fold_convert_loc(loc, ptr_type_tree, space);
tree spaceref = build_fold_indirect_ref_loc(loc, space);
TREE_THIS_NOTRAP(spaceref) = 1;
tree set = fold_build2_loc(loc, MODIFY_EXPR, void_type_node,
spaceref, subinit);
init = fold_build2_loc(loc, COMPOUND_EXPR, TREE_TYPE(space),
set, space);
}
} }
if (var_decl != error_mark_node) if (var_decl != error_mark_node)
{ {
gcc_assert(TREE_CODE(var_decl) == VAR_DECL); gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
DECL_INITIAL(var_decl) = init;
DECL_CHAIN(var_decl) = declare_vars; DECL_CHAIN(var_decl) = declare_vars;
declare_vars = var_decl; declare_vars = var_decl;
} }
...@@ -1769,7 +1646,15 @@ Function::return_value(Gogo* gogo, Named_object* named_function, ...@@ -1769,7 +1646,15 @@ Function::return_value(Gogo* gogo, Named_object* named_function,
tree retval; tree retval;
if (results->size() == 1) if (results->size() == 1)
return this->results_->front()->get_tree(gogo, named_function); {
Bvariable* bvar =
this->results_->front()->get_backend_variable(gogo,
named_function);
tree ret = var_to_tree(bvar);
if (this->results_->front()->result_var_value()->is_in_heap())
ret = build_fold_indirect_ref_loc(location, ret);
return ret;
}
else else
{ {
tree rettype = TREE_TYPE(DECL_RESULT(this->fndecl_)); tree rettype = TREE_TYPE(DECL_RESULT(this->fndecl_));
...@@ -1781,8 +1666,11 @@ Function::return_value(Gogo* gogo, Named_object* named_function, ...@@ -1781,8 +1666,11 @@ Function::return_value(Gogo* gogo, Named_object* named_function,
++pr, ++index, field = DECL_CHAIN(field)) ++pr, ++index, field = DECL_CHAIN(field))
{ {
gcc_assert(field != NULL); gcc_assert(field != NULL);
tree val; Named_object* no = (*this->results_)[index];
val = (*this->results_)[index]->get_tree(gogo, named_function); Bvariable* bvar = no->get_backend_variable(gogo, named_function);
tree val = var_to_tree(bvar);
if (no->result_var_value()->is_in_heap())
val = build_fold_indirect_ref_loc(location, val);
tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node, tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node,
build3(COMPONENT_REF, TREE_TYPE(field), build3(COMPONENT_REF, TREE_TYPE(field),
retval, field, NULL_TREE), retval, field, NULL_TREE),
...@@ -1847,28 +1735,18 @@ Block::get_tree(Translate_context* context) ...@@ -1847,28 +1735,18 @@ Block::get_tree(Translate_context* context)
pv != this->bindings_->end_definitions(); pv != this->bindings_->end_definitions();
++pv) ++pv)
{ {
if ((!(*pv)->is_variable() || !(*pv)->var_value()->is_parameter()) if ((*pv)->is_variable() && !(*pv)->var_value()->is_parameter())
&& !(*pv)->is_result_variable()
&& !(*pv)->is_const())
{ {
tree var = (*pv)->get_tree(gogo, context->function()); Bvariable* var = (*pv)->get_backend_variable(gogo,
if (var != error_mark_node && TREE_TYPE(var) != error_mark_node) context->function());
{ *pp = var_to_tree(var);
if ((*pv)->is_variable() && (*pv)->var_value()->is_in_heap()) if (*pp != error_mark_node)
{ pp = &DECL_CHAIN(*pp);
gcc_assert(TREE_CODE(var) == INDIRECT_REF);
var = TREE_OPERAND(var, 0);
gcc_assert(TREE_CODE(var) == VAR_DECL);
}
*pp = var;
pp = &DECL_CHAIN(*pp);
}
} }
} }
*pp = NULL_TREE; *pp = NULL_TREE;
Translate_context subcontext(context->gogo(), context->function(), Translate_context subcontext(gogo, context->function(), this, block);
this, block);
tree statements = NULL_TREE; tree statements = NULL_TREE;
......
...@@ -2659,7 +2659,8 @@ Function::create_result_variables(Gogo* gogo) ...@@ -2659,7 +2659,8 @@ Function::create_result_variables(Gogo* gogo)
++result_counter; ++result_counter;
name = gogo->pack_hidden_name(buf, false); name = gogo->pack_hidden_name(buf, false);
} }
Result_variable* result = new Result_variable(p->type(), this, index); Result_variable* result = new Result_variable(p->type(), this, index,
p->location());
Named_object* no = block->bindings()->add_result_variable(name, result); Named_object* no = block->bindings()->add_result_variable(name, result);
if (no->is_result_variable()) if (no->is_result_variable())
this->results_->push_back(no); this->results_->push_back(no);
...@@ -3290,7 +3291,7 @@ Variable::Variable(Type* type, Expression* init, bool is_global, ...@@ -3290,7 +3291,7 @@ Variable::Variable(Type* type, Expression* init, bool is_global,
bool is_parameter, bool is_receiver, bool is_parameter, bool is_receiver,
source_location location) source_location location)
: type_(type), init_(init), preinit_(NULL), location_(location), : type_(type), init_(init), preinit_(NULL), location_(location),
is_global_(is_global), is_parameter_(is_parameter), backend_(NULL), is_global_(is_global), is_parameter_(is_parameter),
is_receiver_(is_receiver), is_varargs_parameter_(false), is_receiver_(is_receiver), is_varargs_parameter_(false),
is_address_taken_(false), seen_(false), init_is_lowered_(false), is_address_taken_(false), seen_(false), init_is_lowered_(false),
type_from_init_tuple_(false), type_from_range_index_(false), type_from_init_tuple_(false), type_from_range_index_(false),
...@@ -3636,6 +3637,93 @@ Variable::import_var(Import* imp, std::string* pname, Type** ptype) ...@@ -3636,6 +3637,93 @@ Variable::import_var(Import* imp, std::string* pname, Type** ptype)
imp->require_c_string(";\n"); imp->require_c_string(";\n");
} }
// Convert a variable to the backend representation.
Bvariable*
Variable::get_backend_variable(Gogo* gogo, Named_object* function,
const Package* package, const std::string& name)
{
if (this->backend_ == NULL)
{
Backend* backend = gogo->backend();
Type* type = this->type_;
if (type->is_error_type()
|| (type->is_undefined()
&& (!this->is_global_ || package == NULL)))
this->backend_ = backend->error_variable();
else
{
bool is_parameter = this->is_parameter_;
if (this->is_receiver_ && type->points_to() == NULL)
is_parameter = false;
if (this->is_in_heap())
{
is_parameter = false;
type = Type::make_pointer_type(type);
}
std::string n = Gogo::unpack_hidden_name(name);
Btype* btype = tree_to_type(type->get_tree(gogo));
Bvariable* bvar;
if (this->is_global_)
bvar = backend->global_variable((package == NULL
? gogo->package_name()
: package->name()),
(package == NULL
? gogo->unique_prefix()
: package->unique_prefix()),
n,
btype,
package != NULL,
Gogo::is_hidden_name(name),
this->location_);
else
{
tree fndecl = function->func_value()->get_decl();
Bfunction* bfunction = tree_to_function(fndecl);
if (is_parameter)
bvar = backend->parameter_variable(bfunction, n, btype,
this->location_);
else
bvar = backend->local_variable(bfunction, n, btype,
this->location_);
}
this->backend_ = bvar;
}
}
return this->backend_;
}
// Class Result_variable.
// Convert a result variable to the backend representation.
Bvariable*
Result_variable::get_backend_variable(Gogo* gogo, Named_object* function,
const std::string& name)
{
if (this->backend_ == NULL)
{
Backend* backend = gogo->backend();
Type* type = this->type_;
if (type->is_error())
this->backend_ = backend->error_variable();
else
{
if (this->is_in_heap())
type = Type::make_pointer_type(type);
Btype* btype = tree_to_type(type->get_tree(gogo));
tree fndecl = function->func_value()->get_decl();
Bfunction* bfunction = tree_to_function(fndecl);
std::string n = Gogo::unpack_hidden_name(name);
this->backend_ = backend->local_variable(bfunction, n, btype,
this->location_);
}
}
return this->backend_;
}
// Class Named_constant. // Class Named_constant.
// Traverse the initializer expression. // Traverse the initializer expression.
...@@ -3997,7 +4085,7 @@ Named_object::location() const ...@@ -3997,7 +4085,7 @@ Named_object::location() const
return this->var_value()->location(); return this->var_value()->location();
case NAMED_OBJECT_RESULT_VAR: case NAMED_OBJECT_RESULT_VAR:
return this->result_var_value()->function()->location(); return this->result_var_value()->location();
case NAMED_OBJECT_SINK: case NAMED_OBJECT_SINK:
gcc_unreachable(); gcc_unreachable();
...@@ -4057,6 +4145,21 @@ Named_object::export_named_object(Export* exp) const ...@@ -4057,6 +4145,21 @@ Named_object::export_named_object(Export* exp) const
} }
} }
// Convert a variable to the backend representation.
Bvariable*
Named_object::get_backend_variable(Gogo* gogo, Named_object* function)
{
if (this->classification_ == NAMED_OBJECT_VAR)
return this->var_value()->get_backend_variable(gogo, function,
this->package_, this->name_);
else if (this->classification_ == NAMED_OBJECT_RESULT_VAR)
return this->result_var_value()->get_backend_variable(gogo, function,
this->name_);
else
gcc_unreachable();
}
// Class Bindings. // Class Bindings.
Bindings::Bindings(Bindings* enclosing) Bindings::Bindings(Bindings* enclosing)
......
...@@ -43,6 +43,7 @@ class Export; ...@@ -43,6 +43,7 @@ class Export;
class Import; class Import;
class Bexpression; class Bexpression;
class Bstatement; class Bstatement;
class Bvariable;
class Blabel; class Blabel;
// This file declares the basic classes used to hold the internal // This file declares the basic classes used to hold the internal
...@@ -1270,6 +1271,11 @@ class Variable ...@@ -1270,6 +1271,11 @@ class Variable
set_address_taken() set_address_taken()
{ this->is_address_taken_ = true; } { this->is_address_taken_ = true; }
// Get the backend representation of the variable.
Bvariable*
get_backend_variable(Gogo*, Named_object*, const Package*,
const std::string&);
// Get the initial value of the variable as a tree. This may only // Get the initial value of the variable as a tree. This may only
// be called if has_pre_init() returns false. // be called if has_pre_init() returns false.
tree tree
...@@ -1312,6 +1318,8 @@ class Variable ...@@ -1312,6 +1318,8 @@ class Variable
Block* preinit_; Block* preinit_;
// Location of variable definition. // Location of variable definition.
source_location location_; source_location location_;
// Backend representation.
Bvariable* backend_;
// Whether this is a global variable. // Whether this is a global variable.
bool is_global_ : 1; bool is_global_ : 1;
// Whether this is a function parameter. // Whether this is a function parameter.
...@@ -1346,9 +1354,10 @@ class Variable ...@@ -1346,9 +1354,10 @@ class Variable
class Result_variable class Result_variable
{ {
public: public:
Result_variable(Type* type, Function* function, int index) Result_variable(Type* type, Function* function, int index,
: type_(type), function_(function), index_(index), source_location location)
is_address_taken_(false) : type_(type), function_(function), index_(index), location_(location),
backend_(NULL), is_address_taken_(false)
{ } { }
// Get the type of the result variable. // Get the type of the result variable.
...@@ -1366,6 +1375,11 @@ class Result_variable ...@@ -1366,6 +1375,11 @@ class Result_variable
index() const index() const
{ return this->index_; } { return this->index_; }
// The location of the variable definition.
source_location
location() const
{ return this->location_; }
// Whether this variable's address is taken. // Whether this variable's address is taken.
bool bool
is_address_taken() const is_address_taken() const
...@@ -1387,6 +1401,10 @@ class Result_variable ...@@ -1387,6 +1401,10 @@ class Result_variable
set_function(Function* function) set_function(Function* function)
{ this->function_ = function; } { this->function_ = function; }
// Get the backend representation of the variable.
Bvariable*
get_backend_variable(Gogo*, Named_object*, const std::string&);
private: private:
// Type of result variable. // Type of result variable.
Type* type_; Type* type_;
...@@ -1394,6 +1412,10 @@ class Result_variable ...@@ -1394,6 +1412,10 @@ class Result_variable
Function* function_; Function* function_;
// Index in list of results. // Index in list of results.
int index_; int index_;
// Where the result variable is defined.
source_location location_;
// Backend representation.
Bvariable* backend_;
// Whether something takes the address of this variable. // Whether something takes the address of this variable.
bool is_address_taken_; bool is_address_taken_;
}; };
...@@ -1868,6 +1890,10 @@ class Named_object ...@@ -1868,6 +1890,10 @@ class Named_object
source_location source_location
location() const; location() const;
// Convert a variable to the backend representation.
Bvariable*
get_backend_variable(Gogo*, Named_object* function);
// Return a tree for the external identifier for this object. // Return a tree for the external identifier for this object.
tree tree
get_id(Gogo*); get_id(Gogo*);
......
...@@ -251,37 +251,46 @@ Variable_declaration_statement::do_traverse_assignments( ...@@ -251,37 +251,46 @@ Variable_declaration_statement::do_traverse_assignments(
tree tree
Variable_declaration_statement::do_get_tree(Translate_context* context) Variable_declaration_statement::do_get_tree(Translate_context* context)
{ {
tree val = this->var_->get_tree(context->gogo(), context->function()); Variable* var = this->var_->var_value();
if (val == error_mark_node || TREE_TYPE(val) == error_mark_node) Bvariable* bvar = this->var_->get_backend_variable(context->gogo(),
return error_mark_node; context->function());
Variable* variable = this->var_->var_value(); tree init = var->get_init_tree(context->gogo(), context->function());
Bexpression* binit = init == NULL_TREE ? NULL : tree_to_expr(init);
tree init = variable->get_init_tree(context->gogo(), context->function()); Bstatement* ret;
if (init == error_mark_node) if (!var->is_in_heap())
return error_mark_node;
// If this variable lives on the heap, we need to allocate it now.
if (!variable->is_in_heap())
{ {
DECL_INITIAL(val) = init; gcc_assert(binit != NULL);
return this->build_stmt_1(DECL_EXPR, val); ret = context->backend()->init_statement(bvar, binit);
} }
else else
{ {
gcc_assert(TREE_CODE(val) == INDIRECT_REF); // Something takes the address of this variable, so the value is
tree decl = TREE_OPERAND(val, 0); // stored in the heap. Initialize it to newly allocated memory
gcc_assert(TREE_CODE(decl) == VAR_DECL); // space, and assign the initial value to the new space.
tree type = TREE_TYPE(decl); source_location loc = this->location();
gcc_assert(POINTER_TYPE_P(type)); tree decl = var_to_tree(bvar);
tree size = TYPE_SIZE_UNIT(TREE_TYPE(type)); tree decl_type = TREE_TYPE(decl);
tree space = context->gogo()->allocate_memory(variable->type(), size, gcc_assert(POINTER_TYPE_P(decl_type));
this->location()); tree size = TYPE_SIZE_UNIT(TREE_TYPE(decl_type));
space = fold_convert(TREE_TYPE(decl), space); tree space = context->gogo()->allocate_memory(var->type(), size, loc);
DECL_INITIAL(decl) = space; if (binit != NULL)
return build2(COMPOUND_EXPR, void_type_node, space = save_expr(space);
this->build_stmt_1(DECL_EXPR, decl), space = fold_convert_loc(loc, decl_type, space);
build2(MODIFY_EXPR, void_type_node, val, init)); Bstatement* s1 = context->backend()->init_statement(bvar,
tree_to_expr(space));
if (binit == NULL)
ret = s1;
else
{
tree indir = build_fold_indirect_ref_loc(loc, space);
Bexpression* bindir = tree_to_expr(indir);
Bstatement* s2 = context->backend()->assignment_statement(bindir,
binit,
loc);
ret = context->backend()->compound_statement(s1, s2);
}
} }
return stat_to_tree(ret);
} }
// Make a variable declaration. // Make a variable declaration.
...@@ -2421,6 +2430,8 @@ Return_statement::do_lower(Gogo*, Named_object* function, Block* enclosing) ...@@ -2421,6 +2430,8 @@ Return_statement::do_lower(Gogo*, Named_object* function, Block* enclosing)
tree tree
Return_statement::do_get_tree(Translate_context* context) Return_statement::do_get_tree(Translate_context* context)
{ {
source_location loc = this->location();
Function* function = context->function()->func_value(); Function* function = context->function()->func_value();
tree fndecl = function->get_decl(); tree fndecl = function->get_decl();
...@@ -2433,14 +2444,14 @@ Return_statement::do_get_tree(Translate_context* context) ...@@ -2433,14 +2444,14 @@ Return_statement::do_get_tree(Translate_context* context)
p != results->end(); p != results->end();
p++) p++)
{ {
tree rv = (*p)->get_tree(context->gogo(), context->function()); Expression* vr = Expression::make_var_reference(*p, loc);
retvals.push_back(tree_to_expr(rv)); retvals.push_back(tree_to_expr(vr->get_tree(context)));
} }
} }
Bstatement* ret; Bstatement* ret;
ret = context->backend()->return_statement(tree_to_function(fndecl), ret = context->backend()->return_statement(tree_to_function(fndecl),
retvals, this->location()); retvals, loc);
return stat_to_tree(ret); return stat_to_tree(ret);
} }
......
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