+2016-12-16 Than McIntosh <thanm@google.com>
+
+ * go-gcc.cc (Gcc_backend::expression_statement): Add Bfunction*
+ parameter.
+ (Gcc_backend::init_statement): Likewise.
+ (Gcc_backend::assignment_statement): Likewise.
+ (Gcc_backend::if_statement): Likewise.
+
2016-12-06 Than McIntosh <thanm@google.com>
* go-gcc.cc (Gcc_backend::var_expression): Add Varexpr_context
{ return this->make_statement(error_mark_node); }
Bstatement*
- expression_statement(Bexpression*);
+ expression_statement(Bfunction*, Bexpression*);
Bstatement*
- init_statement(Bvariable* var, Bexpression* init);
+ init_statement(Bfunction*, Bvariable* var, Bexpression* init);
Bstatement*
- assignment_statement(Bexpression* lhs, Bexpression* rhs, Location);
+ assignment_statement(Bfunction*, Bexpression* lhs, Bexpression* rhs,
+ Location);
Bstatement*
return_statement(Bfunction*, const std::vector<Bexpression*>&,
Location);
Bstatement*
- if_statement(Bexpression* condition, Bblock* then_block, Bblock* else_block,
- Location);
+ if_statement(Bfunction*, Bexpression* condition, Bblock* then_block,
+ Bblock* else_block, Location);
Bstatement*
switch_statement(Bfunction* function, Bexpression* value,
// An expression as a statement.
Bstatement*
-Gcc_backend::expression_statement(Bexpression* expr)
+Gcc_backend::expression_statement(Bfunction*, Bexpression* expr)
{
return this->make_statement(expr->get_tree());
}
// Variable initialization.
Bstatement*
-Gcc_backend::init_statement(Bvariable* var, Bexpression* init)
+Gcc_backend::init_statement(Bfunction*, Bvariable* var, Bexpression* init)
{
tree var_tree = var->get_decl();
tree init_tree = init->get_tree();
// Assignment.
Bstatement*
-Gcc_backend::assignment_statement(Bexpression* lhs, Bexpression* rhs,
- Location location)
+Gcc_backend::assignment_statement(Bfunction* bfn, Bexpression* lhs,
+ Bexpression* rhs, Location location)
{
tree lhs_tree = lhs->get_tree();
tree rhs_tree = rhs->get_tree();
// anything anyhow.
if (int_size_in_bytes(TREE_TYPE(lhs_tree)) == 0
|| int_size_in_bytes(TREE_TYPE(rhs_tree)) == 0)
- return this->compound_statement(this->expression_statement(lhs),
- this->expression_statement(rhs));
+ return this->compound_statement(this->expression_statement(bfn, lhs),
+ this->expression_statement(bfn, rhs));
// Sometimes the same unnamed Go type can be created multiple times
// and thus have multiple tree representations. Make sure this does
// If.
Bstatement*
-Gcc_backend::if_statement(Bexpression* condition, Bblock* then_block,
- Bblock* else_block, Location location)
+Gcc_backend::if_statement(Bfunction*, Bexpression* condition,
+ Bblock* then_block, Bblock* else_block,
+ Location location)
{
tree cond_tree = condition->get_tree();
tree then_tree = then_block->get_tree();
// Don't initialize VAR with BINIT, but still evaluate BINIT for
// its side effects.
if (this->type_size(btype) == 0 && init_tree != NULL_TREE)
- *pstatement = this->compound_statement(this->expression_statement(binit),
- *pstatement);
+ *pstatement =
+ this->compound_statement(this->expression_statement(function, binit),
+ *pstatement);
return new Bvariable(var);
}
-310862eb11ec0705f21a375c0dd16f46a8d901c1
+e6fb629c5b246bceab5fc8e8613cf2cf82b1e98f
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
virtual Bstatement*
error_statement() = 0;
- // Create an expression statement.
+ // Create an expression statement within the specified function.
virtual Bstatement*
- expression_statement(Bexpression*) = 0;
+ expression_statement(Bfunction*, Bexpression*) = 0;
- // Create a variable initialization statement. This initializes a
- // local variable at the point in the program flow where it is
- // declared.
+ // Create a variable initialization statement in the specified
+ // function. 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;
+ init_statement(Bfunction*, Bvariable* var, Bexpression* init) = 0;
- // Create an assignment statement.
+ // Create an assignment statement within the specified function.
virtual Bstatement*
- assignment_statement(Bexpression* lhs, Bexpression* rhs,
+ assignment_statement(Bfunction*, Bexpression* lhs, Bexpression* rhs,
Location) = 0;
// Create a return statement, passing the representation of the
return_statement(Bfunction*, const std::vector<Bexpression*>&,
Location) = 0;
- // Create an if statement. ELSE_BLOCK may be NULL.
+ // Create an if statement within a function. ELSE_BLOCK may be NULL.
virtual Bstatement*
- if_statement(Bexpression* condition, Bblock* then_block, Bblock* else_block,
+ if_statement(Bfunction*, Bexpression* condition,
+ Bblock* then_block, Bblock* else_block,
Location) = 0;
// Create a switch statement where the case values are constants.
Bvariable* bvar = this->statement_->get_backend_variable(context);
Bexpression* lvar_ref = gogo->backend()->var_expression(bvar, VE_rvalue, loc);
+ Named_object* fn = context->function();
+ go_assert(fn != NULL);
+ Bfunction* bfn = fn->func_value()->get_or_make_decl(gogo, fn);
Bexpression* bexpr = this->expr_->get_backend(context);
- Bstatement* set = gogo->backend()->assignment_statement(lvar_ref, bexpr, loc);
+ Bstatement* set = gogo->backend()->assignment_statement(bfn, lvar_ref,
+ bexpr, loc);
Bexpression* var_ref = gogo->backend()->var_expression(bvar, VE_lvalue, loc);
Bexpression* ret = gogo->backend()->compound_expression(set, var_ref, loc);
return ret;
gogo->backend()->var_expression(bvar, VE_lvalue, loc);
Bexpression* bval = sut->expression()->get_backend(context);
+ Named_object* fn = context->function();
+ go_assert(fn != NULL);
+ Bfunction* bfn =
+ fn->func_value()->get_or_make_decl(gogo, fn);
Bstatement* bassign =
- gogo->backend()->assignment_statement(bvar_expr, bval, loc);
+ gogo->backend()->assignment_statement(bfn, bvar_expr, bval, loc);
Bexpression* bvar_addr =
gogo->backend()->address_expression(bvar_expr, loc);
return gogo->backend()->compound_expression(bassign, bvar_addr, loc);
Expression* call_ref =
Expression::make_temporary_reference(this->call_temp_, location);
Bexpression* bcall_ref = call_ref->get_backend(context);
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
Bstatement* assn_stmt =
- gogo->backend()->assignment_statement(bcall_ref, call, location);
+ gogo->backend()->assignment_statement(bfunction,
+ bcall_ref, call, location);
this->call_ = this->set_results(context, bcall_ref);
Expression::make_temporary_reference(temp, loc);
ref->set_is_lvalue();
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
Bexpression* result_ref = ref->get_backend(context);
Bexpression* call_result =
gogo->backend()->struct_field_expression(call, i, loc);
Bstatement* assn_stmt =
- gogo->backend()->assignment_statement(result_ref, call_result, loc);
+ gogo->backend()->assignment_statement(bfunction,
+ result_ref, call_result, loc);
Bexpression* result =
gogo->backend()->compound_expression(assn_stmt, call_result, loc);
results = result;
else
{
- Bstatement* expr_stmt = gogo->backend()->expression_statement(result);
+ Bstatement* expr_stmt =
+ gogo->backend()->expression_statement(bfunction, result);
results =
gogo->backend()->compound_expression(expr_stmt, results, loc);
}
Bexpression* bcond =
gogo->backend()->conditional_expression(NULL, bnil_check, bcrash, NULL, loc);
- Bstatement* cond_statement = gogo->backend()->expression_statement(bcond);
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
+ Bstatement* cond_statement =
+ gogo->backend()->expression_statement(bfunction, bcond);
return gogo->backend()->compound_expression(cond_statement, bclosure, loc);
}
gogo->backend()->indirect_expression(expr_btype, space, true, loc);
Bexpression* bexpr = this->expr_->get_backend(context);
- Bstatement* assn = gogo->backend()->assignment_statement(ref, bexpr, loc);
+ Bstatement* assn = gogo->backend()->assignment_statement(fndecl, ref,
+ bexpr, loc);
decl = gogo->backend()->compound_statement(decl, assn);
space = gogo->backend()->var_expression(space_temp, VE_rvalue, loc);
return gogo->backend()->compound_expression(decl, space, loc);
{
Gogo* gogo = context->gogo();
Bexpression* binit = this->init_->get_backend(context);
- Bstatement* init_stmt = gogo->backend()->expression_statement(binit);
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
+ Bstatement* init_stmt = gogo->backend()->expression_statement(bfunction,
+ binit);
Bexpression* bexpr = this->expr_->get_backend(context);
return gogo->backend()->compound_expression(init_stmt, bexpr,
this->location());
// package.
void
-Gogo::init_imports(std::vector<Bstatement*>& init_stmts)
+Gogo::init_imports(std::vector<Bstatement*>& init_stmts, Bfunction *bfunction)
{
go_assert(this->is_main_package());
Bexpression* pfunc_call =
this->backend()->call_expression(pfunc_code, empty_args,
NULL, unknown_loc);
- init_stmts.push_back(this->backend()->expression_statement(pfunc_call));
+ init_stmts.push_back(this->backend()->expression_statement(bfunction,
+ pfunc_call));
}
}
void
Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc,
- std::vector<Bstatement*>& init_stmts)
+ std::vector<Bstatement*>& init_stmts,
+ Bfunction* init_bfn)
{
if (var_gc.empty())
return;
Translate_context context(this, NULL, NULL, NULL);
Bexpression* bcall = register_roots->get_backend(&context);
- init_stmts.push_back(this->backend()->expression_statement(bcall));
+ init_stmts.push_back(this->backend()->expression_statement(init_bfn, bcall));
}
// Get the name to use for the import control function. If there is a
std::vector<Bexpression*> const_decls;
std::vector<Bfunction*> func_decls;
- // The init function declaration, if necessary.
+ // The init function declaration and associated Bfunction, if necessary.
Named_object* init_fndecl = NULL;
+ Bfunction* init_bfn = NULL;
std::vector<Bstatement*> init_stmts;
std::vector<Bstatement*> var_init_stmts;
if (this->is_main_package())
- this->init_imports(init_stmts);
+ {
+ init_fndecl = this->initialization_function_decl();
+ init_bfn = init_fndecl->func_value()->get_or_make_decl(this, init_fndecl);
+ this->init_imports(init_stmts, init_bfn);
+ }
// A list of variable initializations.
Var_inits var_inits;
else
{
if (init_fndecl == NULL)
- init_fndecl = this->initialization_function_decl();
+ {
+ init_fndecl = this->initialization_function_decl();
+ Function* func = init_fndecl->func_value();
+ init_bfn = func->get_or_make_decl(this, init_fndecl);
+ }
var_init_fn = init_fndecl;
}
Bexpression* var_binit = var->get_init(this, var_init_fn);
}
else if (is_sink)
var_init_stmt =
- this->backend()->expression_statement(var_binit);
+ this->backend()->expression_statement(init_bfn, var_binit);
else
{
Location loc = var->location();
Bexpression* var_expr =
this->backend()->var_expression(bvar, VE_lvalue, loc);
var_init_stmt =
- this->backend()->assignment_statement(var_expr, var_binit,
- loc);
+ this->backend()->assignment_statement(init_bfn, var_expr,
+ var_binit, loc);
}
}
else
Btype* btype = no->var_value()->type()->get_backend(this);
Bexpression* zero = this->backend()->zero_expression(btype);
Bstatement* zero_stmt =
- this->backend()->expression_statement(zero);
+ this->backend()->expression_statement(init_bfn, zero);
var_inits.push_back(Var_init(no, zero_stmt));
}
}
// Register global variables with the garbage collector.
- this->register_gc_vars(var_gc, init_stmts);
+ this->register_gc_vars(var_gc, init_stmts, init_bfn);
// Simple variable initializations, after all variables are
// registered.
Bexpression* call = this->backend()->call_expression(func_code,
empty_args,
NULL, func_loc);
- init_stmts.push_back(this->backend()->expression_statement(call));
+ Bstatement* ist = this->backend()->expression_statement(initfn, call);
+ init_stmts.push_back(ist);
}
// Set up a magic function to do all the initialization actions.
for (size_t i = 0; i < vars.size(); ++i)
{
Bstatement* init_stmt =
- gogo->backend()->init_statement(vars[i], var_inits[i]);
+ gogo->backend()->init_statement(this->fndecl_, vars[i],
+ var_inits[i]);
init.push_back(init_stmt);
}
if (defer_init != NULL)
this->defer_stack(end_loc));
Translate_context context(gogo, named_function, NULL, NULL);
Bexpression* defer = call->get_backend(&context);
- stmts.push_back(gogo->backend()->expression_statement(defer));
+ stmts.push_back(gogo->backend()->expression_statement(this->fndecl_, defer));
Bstatement* ret_bstmt = this->return_value(gogo, named_function, end_loc);
if (ret_bstmt != NULL)
Bexpression* bref = ref->get_backend(&context);
ret = gogo->backend()->conditional_expression(NULL, bref, ret, NULL,
end_loc);
- stmts.push_back(gogo->backend()->expression_statement(ret));
+ stmts.push_back(gogo->backend()->expression_statement(this->fndecl_, ret));
}
go_assert(*fini == NULL);
Translate_context context(gogo, function, NULL, NULL);
Bblock* bblock = this->preinit_->get_backend(&context);
+ Bfunction* bfunction =
+ function->func_value()->get_or_make_decl(gogo, function);
// It's possible to have pre-init statements without an initializer
// if the pre-init statements set the variable.
if (var_decl == NULL)
{
Bexpression* init_bexpr = this->init_->get_backend(&context);
- decl_init = gogo->backend()->expression_statement(init_bexpr);
+ decl_init = gogo->backend()->expression_statement(bfunction,
+ init_bexpr);
}
else
{
Bexpression* val = val_expr->get_backend(&context);
Bexpression* var_ref =
gogo->backend()->var_expression(var_decl, VE_lvalue, loc);
- decl_init = gogo->backend()->assignment_statement(var_ref, val, loc);
+ decl_init = gogo->backend()->assignment_statement(bfunction, var_ref,
+ val, loc);
}
}
Bstatement* block_stmt = gogo->backend()->block_statement(bblock);
Named_object*
create_initialization_function(Named_object* fndecl, Bstatement* code_stmt);
- // Initialize imported packages.
+ // Initialize imported packages. BFUNCTION is the function
+ // into which the package init calls will be placed.
void
- init_imports(std::vector<Bstatement*>&);
+ init_imports(std::vector<Bstatement*>&, Bfunction* bfunction);
// Register variables with the garbage collector.
void
register_gc_vars(const std::vector<Named_object*>&,
- std::vector<Bstatement*>&);
+ std::vector<Bstatement*>&,
+ Bfunction* init_bfunction);
// Type used to map import names to packages.
typedef std::map<std::string, Package*> Imports;
Bstatement*
Variable_declaration_statement::do_get_backend(Translate_context* context)
{
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
Variable* var = this->var_->var_value();
Bvariable* bvar = this->var_->get_backend_variable(context->gogo(),
context->function());
if (!var->is_in_heap())
{
go_assert(binit != NULL);
- return context->backend()->init_statement(bvar, binit);
+ return context->backend()->init_statement(bfunction, bvar, binit);
}
// Something takes the address of this variable, so the value is
Expression* e = Expression::make_temporary_reference(temp, loc);
e = Expression::make_unary(OPERATOR_MULT, e, loc);
Bexpression* be = e->get_backend(context);
- set = context->backend()->assignment_statement(be, binit, loc);
+ set = context->backend()->assignment_statement(bfunction, be, binit, loc);
}
Expression* ref = Expression::make_temporary_reference(temp, loc);
Bexpression* bref = ref->get_backend(context);
- Bstatement* sinit = context->backend()->init_statement(bvar, bref);
+ Bstatement* sinit = context->backend()->init_statement(bfunction, bvar, bref);
std::vector<Bstatement*> stats;
stats.reserve(3);
return TRAVERSE_EXIT;
}
+ Unary_expression* ue = e->unary_expression();
+ if (ue && ue->op() == OPERATOR_MULT)
+ return TRAVERSE_CONTINUE;
+
return TRAVERSE_EXIT;
}
if (this->lhs_->is_sink_expression())
{
Bexpression* rhs = this->rhs_->get_backend(context);
- return context->backend()->expression_statement(rhs);
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
+ return context->backend()->expression_statement(bfunction, rhs);
}
Mark_lvalue_varexprs mlve;
Expression::convert_for_assignment(context->gogo(), this->lhs_->type(),
this->rhs_, this->location());
Bexpression* rhs = conv->get_backend(context);
- return context->backend()->assignment_statement(lhs, rhs, this->location());
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
+ return context->backend()->assignment_statement(bfunction, lhs, rhs,
+ this->location());
}
// Dump the AST representation for an assignment statement.
Expression_statement::do_get_backend(Translate_context* context)
{
Bexpression* bexpr = this->expr_->get_backend(context);
- return context->backend()->expression_statement(bexpr);
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
+ return context->backend()->expression_statement(bfunction, bexpr);
}
// Dump the AST representation for an expression statement
Expression* call = Runtime::make_call(Runtime::GO, this->location(), 2,
fn, arg);
Bexpression* bcall = call->get_backend(context);
- return context->backend()->expression_statement(bcall);
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
+ return context->backend()->expression_statement(bfunction, bcall);
}
// Dump the AST representation for go statement.
Expression* call = Runtime::make_call(Runtime::DEFERPROC, loc, 3,
ds, fn, arg);
Bexpression* bcall = call->get_backend(context);
- return context->backend()->expression_statement(bcall);
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
+ return context->backend()->expression_statement(bfunction, bcall);
}
// Dump the AST representation for defer statement.
if (this->label_->is_dummy_label())
{
Bexpression* bce = context->backend()->boolean_constant_expression(false);
- return context->backend()->expression_statement(bce);
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
+ return context->backend()->expression_statement(bfunction, bce);
}
Blabel* blabel = this->label_->get_backend_label(context);
return context->backend()->label_definition_statement(blabel);
Bblock* else_block = (this->else_block_ == NULL
? NULL
: this->else_block_->get_backend(context));
- return context->backend()->if_statement(cond, then_block, else_block,
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
+ return context->backend()->if_statement(bfunction,
+ cond, then_block, else_block,
this->location());
}
context->gogo()->lower_expression(context->function(), NULL, &call);
Bexpression* bcall = call->get_backend(context);
- Bstatement* s = context->backend()->expression_statement(bcall);
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
+ Bstatement* s = context->backend()->expression_statement(bfunction, bcall);
if (btemp == NULL)
return s;
if (s == NULL)
clauses[i] = g;
else
- clauses[i] = context->backend()->compound_statement(s, g);
+ clauses[i] = context->backend()->compound_statement(s, g);
}
Expression* selref = Expression::make_temporary_reference(sel, location);
Bexpression* bcall = call->get_backend(context);
if (count == 0)
- return context->backend()->expression_statement(bcall);
+ {
+ Bfunction* bfunction = context->function()->func_value()->get_decl();
+ return context->backend()->expression_statement(bfunction, bcall);
+ }
std::vector<Bstatement*> statements;
statements.reserve(2);