// statements.cc -- Go frontend statements.

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "go-system.h"

#include "go-c.h"
#include "go-diagnostics.h"
#include "types.h"
#include "expressions.h"
#include "gogo.h"
#include "export.h"
#include "import.h"
#include "runtime.h"
#include "backend.h"
#include "statements.h"
#include "ast-dump.h"

// Class Statement.

Statement::Statement(Statement_classification classification,
		     Location location)
  : classification_(classification), location_(location)
{
}

Statement::~Statement()
{
}

// Traverse the tree.  The work of walking the components is handled
// by the subclasses.

int
Statement::traverse(Block* block, size_t* pindex, Traverse* traverse)
{
  if (this->classification_ == STATEMENT_ERROR)
    return TRAVERSE_CONTINUE;

  unsigned int traverse_mask = traverse->traverse_mask();

  if ((traverse_mask & Traverse::traverse_statements) != 0)
    {
      int t = traverse->statement(block, pindex, this);
      if (t == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
      else if (t == TRAVERSE_SKIP_COMPONENTS)
	return TRAVERSE_CONTINUE;
    }

  // No point in checking traverse_mask here--a statement may contain
  // other blocks or statements, and if we got here we always want to
  // walk them.
  return this->do_traverse(traverse);
}

// Traverse the contents of a statement.

int
Statement::traverse_contents(Traverse* traverse)
{
  return this->do_traverse(traverse);
}

// Traverse assignments.

bool
Statement::traverse_assignments(Traverse_assignments* tassign)
{
  if (this->classification_ == STATEMENT_ERROR)
    return false;
  return this->do_traverse_assignments(tassign);
}

// Traverse an expression in a statement.  This is a helper function
// for child classes.

int
Statement::traverse_expression(Traverse* traverse, Expression** expr)
{
  if ((traverse->traverse_mask()
       & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
    return TRAVERSE_CONTINUE;
  return Expression::traverse(expr, traverse);
}

// Traverse an expression list in a statement.  This is a helper
// function for child classes.

int
Statement::traverse_expression_list(Traverse* traverse,
				    Expression_list* expr_list)
{
  if (expr_list == NULL)
    return TRAVERSE_CONTINUE;
  if ((traverse->traverse_mask()
       & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
    return TRAVERSE_CONTINUE;
  return expr_list->traverse(traverse);
}

// Traverse a type in a statement.  This is a helper function for
// child classes.

int
Statement::traverse_type(Traverse* traverse, Type* type)
{
  if ((traverse->traverse_mask()
       & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
    return TRAVERSE_CONTINUE;
  return Type::traverse(type, traverse);
}

// Set type information for unnamed constants.  This is really done by
// the child class.

void
Statement::determine_types()
{
  this->do_determine_types();
}

// Read a statement from export data.

Statement*
Statement::import_statement(Import_function_body* ifb, Location loc)
{
  if (ifb->match_c_string("{"))
    {
      bool is_lowered_for_statement;
      Block* block = Block_statement::do_import(ifb, loc,
						&is_lowered_for_statement);
      if (block == NULL)
	return Statement::make_error_statement(loc);
      Block_statement* s = Statement::make_block_statement(block, loc);
      if (is_lowered_for_statement)
	s->set_is_lowered_for_statement();
      return s;
    }
  else if (ifb->match_c_string("return"))
    {
      // After lowering return statements have no expressions.  The
      // return expressions are assigned to result parameters.
      ifb->advance(6);
      return Statement::make_return_statement(NULL, loc);
    }
  else if (ifb->match_c_string("var $t"))
    return Temporary_statement::do_import(ifb, loc);
  else if (ifb->match_c_string("var "))
    return Variable_declaration_statement::do_import(ifb, loc);
  else if (ifb->match_c_string("if "))
    return If_statement::do_import(ifb, loc);
  else if (ifb->match_c_string(":"))
    return Label_statement::do_import(ifb, loc);
  else if (ifb->match_c_string("goto "))
    return Goto_statement::do_import(ifb, loc);

  Expression* lhs = Expression::import_expression(ifb, loc);

  if (ifb->match_c_string(" //"))
    return Statement::make_statement(lhs, true);

  ifb->require_c_string(" = ");
  Expression* rhs = Expression::import_expression(ifb, loc);
  return Statement::make_assignment(lhs, rhs, loc);
}

// If this is a thunk statement, return it.

Thunk_statement*
Statement::thunk_statement()
{
  Thunk_statement* ret = this->convert<Thunk_statement, STATEMENT_GO>();
  if (ret == NULL)
    ret = this->convert<Thunk_statement, STATEMENT_DEFER>();
  return ret;
}

// Convert a Statement to the backend representation.  This is really
// done by the child class.

Bstatement*
Statement::get_backend(Translate_context* context)
{
  if (this->classification_ == STATEMENT_ERROR)
    return context->backend()->error_statement();
  return this->do_get_backend(context);
}

// Dump AST representation for a statement to a dump context.

void
Statement::dump_statement(Ast_dump_context* ast_dump_context) const
{
  this->do_dump_statement(ast_dump_context);
}

// Note that this statement is erroneous.  This is called by children
// when they discover an error.

void
Statement::set_is_error()
{
  this->classification_ = STATEMENT_ERROR;
}

// For children to call to report an error conveniently.

void
Statement::report_error(const char* msg)
{
  go_error_at(this->location_, "%s", msg);
  this->set_is_error();
}

// An error statement, used to avoid crashing after we report an
// error.

class Error_statement : public Statement
{
 public:
  Error_statement(Location location)
    : Statement(STATEMENT_ERROR, location)
  { }

 protected:
  int
  do_traverse(Traverse*)
  { return TRAVERSE_CONTINUE; }

  Bstatement*
  do_get_backend(Translate_context*)
  { go_unreachable(); }

  void
  do_dump_statement(Ast_dump_context*) const;
};

//
// Helper to tack on available source position information
// at the end of a statement.
//
static std::string
dsuffix(Location location)
{
  std::string lstr = Linemap::location_to_string(location);
  if (lstr == "")
    return lstr;
  std::string rval(" // ");
  rval += lstr;
  return rval;
}

// Dump the AST representation for an error statement.

void
Error_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << "Error statement" << std::endl;
}

// Make an error statement.

Statement*
Statement::make_error_statement(Location location)
{
  return new Error_statement(location);
}

// Class Variable_declaration_statement.

Variable_declaration_statement::Variable_declaration_statement(
    Named_object* var)
  : Statement(STATEMENT_VARIABLE_DECLARATION, var->var_value()->location()),
    var_(var)
{
}

// We don't actually traverse the variable here; it was traversed
// while traversing the Block.

int
Variable_declaration_statement::do_traverse(Traverse*)
{
  return TRAVERSE_CONTINUE;
}

// Traverse the assignments in a variable declaration.  Note that this
// traversal is different from the usual traversal.

bool
Variable_declaration_statement::do_traverse_assignments(
    Traverse_assignments* tassign)
{
  tassign->initialize_variable(this->var_);
  return true;
}

// Lower the variable's initialization expression.

Statement*
Variable_declaration_statement::do_lower(Gogo* gogo, Named_object* function,
					 Block*, Statement_inserter* inserter)
{
  this->var_->var_value()->lower_init_expression(gogo, function, inserter);
  return this;
}

// Flatten the variable's initialization expression.

Statement*
Variable_declaration_statement::do_flatten(Gogo* gogo, Named_object* function,
                                           Block*, Statement_inserter* inserter)
{
  Variable* var = this->var_->var_value();
  if (var->type()->is_error_type()
      || (var->init() != NULL
          && var->init()->is_error_expression()))
    {
      go_assert(saw_errors());
      return Statement::make_error_statement(this->location());
    }
  this->var_->var_value()->flatten_init_expression(gogo, function, inserter);
  return this;
}

// Add explicit type conversions.

void
Variable_declaration_statement::do_add_conversions()
{
  Variable* var = this->var_->var_value();
  Expression* init = var->init();
  if (init == NULL)
    return;
  Type* lt = var->type();
  Type* rt = init->type();
  if (!Type::are_identical(lt, rt, 0, NULL)
      && lt->interface_type() != NULL)
    var->set_init(Expression::make_cast(lt, init, this->location()));
}

// Convert a variable declaration to the backend representation.

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());
  Bexpression* binit = var->get_init(context->gogo(), context->function());

  if (!var->is_in_heap())
    {
      go_assert(binit != NULL);
      return context->backend()->init_statement(bfunction, bvar, binit);
    }

  // Something takes the address of this variable, so the value is
  // stored in the heap.  Initialize it to newly allocated memory
  // space, and assign the initial value to the new space.
  Location loc = this->location();
  Named_object* newfn = context->gogo()->lookup_global("new");
  go_assert(newfn != NULL && newfn->is_function_declaration());
  Expression* func = Expression::make_func_reference(newfn, NULL, loc);
  Expression_list* params = new Expression_list();
  params->push_back(Expression::make_type(var->type(), loc));
  Expression* call = Expression::make_call(func, params, false, loc);
  context->gogo()->lower_expression(context->function(), NULL, &call);
  Temporary_statement* temp = Statement::make_temporary(NULL, call, loc);
  Bstatement* btemp = temp->get_backend(context);

  Bstatement* set = NULL;
  if (binit != NULL)
    {
      Expression* e = Expression::make_temporary_reference(temp, loc);
      e = Expression::make_dereference(e, Expression::NIL_CHECK_NOT_NEEDED,
                                       loc);
      Bexpression* be = e->get_backend(context);
      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(bfunction, bvar, bref);

  std::vector<Bstatement*> stats;
  stats.reserve(3);
  stats.push_back(btemp);
  if (set != NULL)
    stats.push_back(set);
  stats.push_back(sinit);
  return context->backend()->statement_list(stats);
}

// Dump the AST representation for a variable declaration.

void
Variable_declaration_statement::do_dump_statement(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();

  go_assert(var_->is_variable());
  ast_dump_context->ostream() << "var " << this->var_->name() <<  " ";
  Variable* var = this->var_->var_value();
  if (var->has_type())
    {
      ast_dump_context->dump_type(var->type());
      ast_dump_context->ostream() << " ";
    }
  if (var->init() != NULL)
    {
      ast_dump_context->ostream() <<  "= ";
      ast_dump_context->dump_expression(var->init());
    }
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make a variable declaration.

Statement*
Statement::make_variable_declaration(Named_object* var)
{
  return new Variable_declaration_statement(var);
}

// Export a variable declaration.

void
Variable_declaration_statement::do_export_statement(Export_function_body* efb)
{
  efb->write_c_string("var ");
  efb->write_string(Gogo::unpack_hidden_name(this->var_->name()));
  efb->write_c_string(" ");
  Variable* var = this->var_->var_value();
  Type* type = var->type();
  efb->write_type(type);
  Expression* init = var->init();
  if (init != NULL)
    {
      efb->write_c_string(" = ");

      go_assert(efb->type_context() == NULL);
      efb->set_type_context(type);

      init->export_expression(efb);

      efb->set_type_context(NULL);
    }
}

// Import a variable declaration.

Statement*
Variable_declaration_statement::do_import(Import_function_body* ifb,
					  Location loc)
{
  ifb->require_c_string("var ");
  std::string id = ifb->read_identifier();
  ifb->require_c_string(" ");
  Type* type = ifb->read_type();
  Expression* init = NULL;
  if (ifb->match_c_string(" = "))
    {
      ifb->advance(3);
      init = Expression::import_expression(ifb, loc);
    }
  Variable* var = new Variable(type, init, false, false, false, loc);
  var->set_is_used();
  // FIXME: The package we are importing does not yet exist, so we
  // can't pass the correct package here.  It probably doesn't matter.
  Named_object* no = ifb->block()->bindings()->add_variable(id, NULL, var);
  return Statement::make_variable_declaration(no);
}

// Class Temporary_statement.

// Return the type of the temporary variable.

Type*
Temporary_statement::type() const
{
  Type* type = this->type_ != NULL ? this->type_ : this->init_->type();

  // Temporary variables cannot have a void type.
  if (type->is_void_type())
    {
      go_assert(saw_errors());
      return Type::make_error_type();
    }
  return type;
}

// Traversal.

int
Temporary_statement::do_traverse(Traverse* traverse)
{
  if (this->type_ != NULL
      && this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (this->init_ == NULL)
    return TRAVERSE_CONTINUE;
  else
    return this->traverse_expression(traverse, &this->init_);
}

// Traverse assignments.

bool
Temporary_statement::do_traverse_assignments(Traverse_assignments* tassign)
{
  if (this->init_ == NULL)
    return false;
  tassign->value(&this->init_, true, true);
  return true;
}

// Determine types.

void
Temporary_statement::do_determine_types()
{
  if (this->type_ != NULL && this->type_->is_abstract())
    this->type_ = this->type_->make_non_abstract_type();

  if (this->init_ != NULL)
    {
      if (this->type_ == NULL)
	this->init_->determine_type_no_context();
      else
	{
	  Type_context context(this->type_, false);
	  this->init_->determine_type(&context);
	}
    }

  if (this->type_ == NULL)
    {
      this->type_ = this->init_->type();
      go_assert(!this->type_->is_abstract());
    }
}

// Check types.

void
Temporary_statement::do_check_types(Gogo*)
{
  if (this->type_ != NULL && this->init_ != NULL)
    {
      std::string reason;
      if (!Type::are_assignable(this->type_, this->init_->type(), &reason))
	{
	  if (reason.empty())
	    go_error_at(this->location(), "incompatible types in assignment");
	  else
	    go_error_at(this->location(), "incompatible types in assignment (%s)",
		     reason.c_str());
	  this->set_is_error();
	}
    }
}

// Flatten a temporary statement: add another temporary when it might
// be needed for interface conversion.

Statement*
Temporary_statement::do_flatten(Gogo*, Named_object*, Block*,
				Statement_inserter* inserter)
{
  if (this->type()->is_error_type()
      || (this->init_ != NULL
          && this->init_->is_error_expression()))
    {
      go_assert(saw_errors());
      return Statement::make_error_statement(this->location());
    }

  if (this->type_ != NULL
      && this->init_ != NULL
      && !Type::are_identical(this->type_, this->init_->type(),
			      Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
			      NULL)
      && this->init_->type()->interface_type() != NULL
      && !this->init_->is_variable())
    {
      Temporary_statement *temp =
	Statement::make_temporary(NULL, this->init_, this->location());
      inserter->insert(temp);
      this->init_ = Expression::make_temporary_reference(temp,
							 this->location());
    }
  return this;
}

// Add explicit type conversions.

void
Temporary_statement::do_add_conversions()
{
  if (this->init_ == NULL)
    return;
  Type* lt = this->type();
  Type* rt = this->init_->type();
  if (!Type::are_identical(lt, rt, 0, NULL)
      && lt->interface_type() != NULL)
    this->init_ = Expression::make_cast(lt, this->init_, this->location());
}

// Convert to backend representation.

Bstatement*
Temporary_statement::do_get_backend(Translate_context* context)
{
  go_assert(this->bvariable_ == NULL);

  Named_object* function = context->function();
  go_assert(function != NULL);
  Bfunction* bfunction = function->func_value()->get_decl();
  Btype* btype = this->type()->get_backend(context->gogo());

  Bexpression* binit;
  if (this->init_ == NULL)
    binit = NULL;
  else if (this->type_ == NULL)
    binit = this->init_->get_backend(context);
  else
    {
      Expression* init = Expression::convert_for_assignment(context->gogo(),
							    this->type_,
							    this->init_,
							    this->location());
      binit = init->get_backend(context);
    }

  if (binit != NULL)
    binit = context->backend()->convert_expression(btype, binit,
                                                   this->location());

  Bstatement* statement;
  this->bvariable_ =
    context->backend()->temporary_variable(bfunction, context->bblock(),
					   btype, binit,
					   this->is_address_taken_,
					   this->location(), &statement);
  return statement;
}

// Return the backend variable.

Bvariable*
Temporary_statement::get_backend_variable(Translate_context* context) const
{
  if (this->bvariable_ == NULL)
    {
      go_assert(saw_errors());
      return context->backend()->error_variable();
    }
  return this->bvariable_;
}

// Dump the AST represemtation for a temporary statement

void
Temporary_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->dump_temp_variable_name(this);
  if (this->type_ != NULL)
    {
      ast_dump_context->ostream() << " ";
      ast_dump_context->dump_type(this->type_);
    }
  if (this->init_ != NULL)
    {
      ast_dump_context->ostream() << " = ";
      ast_dump_context->dump_expression(this->init_);
    }
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make and initialize a temporary variable in BLOCK.

Temporary_statement*
Statement::make_temporary(Type* type, Expression* init,
			  Location location)
{
  return new Temporary_statement(type, init, location);
}

// Export a temporary statement.

void
Temporary_statement::do_export_statement(Export_function_body* efb)
{
  unsigned int idx = efb->record_temporary(this);
  char buf[100];
  snprintf(buf, sizeof buf, "var $t%u", idx);
  efb->write_c_string(buf);
  if (this->type_ != NULL)
    {
      efb->write_c_string(" ");
      efb->write_type(this->type_);
    }
  if (this->init_ != NULL)
    {
      efb->write_c_string(" = ");

      go_assert(efb->type_context() == NULL);
      efb->set_type_context(this->type_);

      this->init_->export_expression(efb);

      efb->set_type_context(NULL);
    }
}

// Import a temporary statement.

Statement*
Temporary_statement::do_import(Import_function_body* ifb, Location loc)
{
  ifb->require_c_string("var ");
  std::string id = ifb->read_identifier();
  go_assert(id[0] == '$' && id[1] == 't');
  const char *p = id.c_str();
  char *end;
  long idx = strtol(p + 2, &end, 10);
  if (*end != '\0' || idx > 0x7fffffff)
    {
      if (!ifb->saw_error())
	go_error_at(loc,
		    ("invalid export data for %qs: "
		     "bad temporary statement index at %lu"),
		    ifb->name().c_str(),
		    static_cast<unsigned long>(ifb->off()));
      ifb->set_saw_error();
      return Statement::make_error_statement(loc);
    }

  Type* type = NULL;
  if (!ifb->match_c_string(" = "))
    {
      ifb->require_c_string(" ");
      type = ifb->read_type();
    }
  Expression* init = NULL;
  if (ifb->match_c_string(" = "))
    {
      ifb->advance(3);
      init = Expression::import_expression(ifb, loc);
    }
  if (type == NULL && init == NULL)
    {
      if (!ifb->saw_error())
	go_error_at(loc,
		    ("invalid export data for %qs: "
		     "temporary statement has neither type nor init at %lu"),
		    ifb->name().c_str(),
		    static_cast<unsigned long>(ifb->off()));
      ifb->set_saw_error();
      return Statement::make_error_statement(loc);
    }

  Temporary_statement* temp = Statement::make_temporary(type, init, loc);

  ifb->record_temporary(temp, static_cast<unsigned int>(idx));

  return temp;
}

// The Move_subexpressions class is used to move all top-level
// subexpressions of an expression.  This is used for things like
// index expressions in which we must evaluate the index value before
// it can be changed by a multiple assignment.

class Move_subexpressions : public Traverse
{
 public:
  Move_subexpressions(int skip, Block* block)
    : Traverse(traverse_expressions),
      skip_(skip), block_(block)
  { }

 protected:
  int
  expression(Expression**);

 private:
  // The number of subexpressions to skip moving.  This is used to
  // avoid moving the array itself, as we only need to move the index.
  int skip_;
  // The block where new temporary variables should be added.
  Block* block_;
};

int
Move_subexpressions::expression(Expression** pexpr)
{
  if (this->skip_ > 0)
    --this->skip_;
  else if ((*pexpr)->temporary_reference_expression() == NULL
	   && !(*pexpr)->is_nil_expression()
           && !(*pexpr)->is_constant())
    {
      Location loc = (*pexpr)->location();
      Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
      this->block_->add_statement(temp);
      *pexpr = Expression::make_temporary_reference(temp, loc);
    }
  // We only need to move top-level subexpressions.
  return TRAVERSE_SKIP_COMPONENTS;
}

// The Move_ordered_evals class is used to find any subexpressions of
// an expression that have an evaluation order dependency.  It creates
// temporary variables to hold them.

class Move_ordered_evals : public Traverse
{
 public:
  Move_ordered_evals(Block* block)
    : Traverse(traverse_expressions),
      block_(block)
  { }

 protected:
  int
  expression(Expression**);

 private:
  // The block where new temporary variables should be added.
  Block* block_;
};

int
Move_ordered_evals::expression(Expression** pexpr)
{
  // We have to look at subexpressions first.
  if ((*pexpr)->traverse_subexpressions(this) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;

  int i;
  if ((*pexpr)->must_eval_subexpressions_in_order(&i))
    {
      Move_subexpressions ms(i, this->block_);
      if ((*pexpr)->traverse_subexpressions(&ms) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }

  if ((*pexpr)->must_eval_in_order())
    {
      Call_expression* call = (*pexpr)->call_expression();
      if (call != NULL && call->is_multi_value_arg())
	{
	  // A call expression which returns multiple results as an argument
	  // to another call must be handled specially.  We can't create a
	  // temporary because there is no type to give it.  Instead, group
	  // the caller and this multi-valued call argument and use a temporary
	  // variable to hold them.
	  return TRAVERSE_SKIP_COMPONENTS;
	}

      Location loc = (*pexpr)->location();
      Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
      this->block_->add_statement(temp);
      *pexpr = Expression::make_temporary_reference(temp, loc);
    }
  return TRAVERSE_SKIP_COMPONENTS;
}

// Class Assignment_statement.

// Traversal.

int
Assignment_statement::do_traverse(Traverse* traverse)
{
  if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return this->traverse_expression(traverse, &this->rhs_);
}

bool
Assignment_statement::do_traverse_assignments(Traverse_assignments* tassign)
{
  tassign->assignment(&this->lhs_, &this->rhs_);
  return true;
}

// Lower an assignment to a map index expression to a runtime function
// call.  Mark some slice assignments as not requiring a write barrier.

Statement*
Assignment_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
			       Statement_inserter*)
{
  Map_index_expression* mie = this->lhs_->map_index_expression();
  if (mie != NULL)
    {
      Location loc = this->location();

      Expression* map = mie->map();
      Map_type* mt = map->type()->map_type();
      if (mt == NULL)
	{
	  go_assert(saw_errors());
	  return Statement::make_error_statement(loc);
	}

      Block* b = new Block(enclosing, loc);

      // Move out any subexpressions on the left hand side to make
      // sure that functions are called in the required order.
      Move_ordered_evals moe(b);
      mie->traverse_subexpressions(&moe);

      // Copy the key into a temporary so that we can take its address
      // without pushing the value onto the heap.

      // var key_temp KEY_TYPE = MAP_INDEX
      Temporary_statement* key_temp = Statement::make_temporary(mt->key_type(),
								mie->index(),
								loc);
      b->add_statement(key_temp);

      // Copy the value into a temporary to ensure that it is
      // evaluated before we add the key to the map.  This may matter
      // if the value is itself a reference to the map.

      // var val_temp VAL_TYPE = RHS
      Temporary_statement* val_temp = Statement::make_temporary(mt->val_type(),
								this->rhs_,
								loc);
      b->add_statement(val_temp);

      // *mapassign(TYPE, MAP, &key_temp) = RHS
      Expression* a1 = Expression::make_type_descriptor(mt, loc);
      Expression* a2 = mie->map();
      Temporary_reference_expression* ref =
	Expression::make_temporary_reference(key_temp, loc);
      Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc);
      Runtime::Function code;
      Map_type::Map_alg alg = mt->algorithm(gogo);
      switch (alg)
        {
          case Map_type::MAP_ALG_FAST32:
            {
              code = Runtime::MAPASSIGN_FAST32;
              Type* uint32_type = Type::lookup_integer_type("uint32");
              Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
              a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3,
                                                loc);
              a3 = Expression::make_dereference(a3,
                                                Expression::NIL_CHECK_NOT_NEEDED,
                                                loc);
              break;
            }
          case Map_type::MAP_ALG_FAST64:
            {
              code = Runtime::MAPASSIGN_FAST64;
              Type* uint64_type = Type::lookup_integer_type("uint64");
              Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
              a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3,
                                                loc);
              a3 = Expression::make_dereference(a3,
                                                Expression::NIL_CHECK_NOT_NEEDED,
                                                loc);
              break;
            }
          case Map_type::MAP_ALG_FAST32PTR:
          case Map_type::MAP_ALG_FAST64PTR:
            {
              code = (alg == Map_type::MAP_ALG_FAST32PTR
                      ? Runtime::MAPASSIGN_FAST32PTR
                      : Runtime::MAPASSIGN_FAST64PTR);
              Type* ptr_type =
                Type::make_pointer_type(Type::make_void_type());
              Type* ptr_ptr_type = Type::make_pointer_type(ptr_type);
              a3 = Expression::make_unsafe_cast(ptr_ptr_type, a3,
                                                loc);
              a3 = Expression::make_dereference(a3,
                                                Expression::NIL_CHECK_NOT_NEEDED,
                                                loc);
              break;
            }
          case Map_type::MAP_ALG_FASTSTR:
            code = Runtime::MAPASSIGN_FASTSTR;
            a3 = ref;
            break;
          default:
            code = Runtime::MAPASSIGN;
            break;
        }
      Expression* call = Runtime::make_call(code, loc, 3,
					    a1, a2, a3);
      Type* ptrval_type = Type::make_pointer_type(mt->val_type());
      call = Expression::make_cast(ptrval_type, call, loc);
      Expression* indir =
          Expression::make_dereference(call, Expression::NIL_CHECK_NOT_NEEDED,
                                       loc);
      ref = Expression::make_temporary_reference(val_temp, loc);
      b->add_statement(Statement::make_assignment(indir, ref, loc));

      return Statement::make_block_statement(b, loc);
    }

  // An assignment of the form s = s[:n] does not require a write
  // barrier, because the pointer value will not change.
  Array_index_expression* aie = this->rhs_->array_index_expression();
  if (aie != NULL
      && aie->end() != NULL
      && Expression::is_same_variable(this->lhs_, aie->array()))
    {
      Numeric_constant nc;
      unsigned long ival;
      if (aie->start()->numeric_constant_value(&nc)
	  && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID
	  && ival == 0)
	this->omit_write_barrier_ = true;
    }
  String_index_expression* sie = this->rhs_->string_index_expression();
  if (sie != NULL
      && sie->end() != NULL
      && Expression::is_same_variable(this->lhs_, sie->string()))
    {
      Numeric_constant nc;
      unsigned long ival;
      if (sie->start()->numeric_constant_value(&nc)
	  && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID
	  && ival == 0)
        this->omit_write_barrier_ = true;
    }

  return this;
}

// Set types for the assignment.

void
Assignment_statement::do_determine_types()
{
  this->lhs_->determine_type_no_context();
  Type* rhs_context_type = this->lhs_->type();
  if (rhs_context_type->is_sink_type())
    rhs_context_type = NULL;
  Type_context context(rhs_context_type, false);
  this->rhs_->determine_type(&context);
}

// Check types for an assignment.

void
Assignment_statement::do_check_types(Gogo*)
{
  // The left hand side must be either addressable, a map index
  // expression, or the blank identifier.
  if (!this->lhs_->is_addressable()
      && this->lhs_->map_index_expression() == NULL
      && !this->lhs_->is_sink_expression())
    {
      if (!this->lhs_->type()->is_error())
	this->report_error(_("invalid left hand side of assignment"));
      return;
    }

  Type* lhs_type = this->lhs_->type();
  Type* rhs_type = this->rhs_->type();

  // Invalid assignment of nil to the blank identifier.
  if (lhs_type->is_sink_type()
      && rhs_type->is_nil_type())
    {
      this->report_error(_("use of untyped nil"));
      return;
    }

  std::string reason;
  if (!Type::are_assignable(lhs_type, rhs_type, &reason))
    {
      if (reason.empty())
	go_error_at(this->location(), "incompatible types in assignment");
      else
	go_error_at(this->location(), "incompatible types in assignment (%s)",
		    reason.c_str());
      this->set_is_error();
    }

  if (lhs_type->is_error() || rhs_type->is_error())
    this->set_is_error();
}

void
Assignment_statement::do_export_statement(Export_function_body* efb)
{
  this->lhs_->export_expression(efb);
  efb->write_c_string(" = ");
  this->rhs_->export_expression(efb);
}

// Flatten an assignment statement.  We may need a temporary for
// interface conversion.

Statement*
Assignment_statement::do_flatten(Gogo*, Named_object*, Block*,
				 Statement_inserter* inserter)
{
  if (this->lhs_->is_error_expression()
      || this->lhs_->type()->is_error_type()
      || this->rhs_->is_error_expression()
      || this->rhs_->type()->is_error_type())
    {
      go_assert(saw_errors());
      return Statement::make_error_statement(this->location());
    }

  if (!this->lhs_->is_sink_expression()
      && !Type::are_identical(this->lhs_->type(), this->rhs_->type(),
			      Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
			      NULL)
      && this->rhs_->type()->interface_type() != NULL
      && !this->rhs_->is_variable())
    {
      Temporary_statement* temp =
	Statement::make_temporary(NULL, this->rhs_, this->location());
      inserter->insert(temp);
      this->rhs_ = Expression::make_temporary_reference(temp,
							this->location());
    }
  return this;
}

// Add explicit type conversions.

void
Assignment_statement::do_add_conversions()
{
  Type* lt = this->lhs_->type();
  Type* rt = this->rhs_->type();
  if (!Type::are_identical(lt, rt, 0, NULL)
      && lt->interface_type() != NULL)
    this->rhs_ = Expression::make_cast(lt, this->rhs_, this->location());
}

// Convert an assignment statement to the backend representation.

Bstatement*
Assignment_statement::do_get_backend(Translate_context* context)
{
  if (this->lhs_->is_sink_expression())
    {
      Bexpression* rhs = this->rhs_->get_backend(context);
      Bfunction* bfunction = context->function()->func_value()->get_decl();
      return context->backend()->expression_statement(bfunction, rhs);
    }

  Bexpression* lhs = this->lhs_->get_backend(context);
  Expression* conv =
      Expression::convert_for_assignment(context->gogo(), this->lhs_->type(),
                                         this->rhs_, this->location());
  Bexpression* rhs = conv->get_backend(context);
  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.

void
Assignment_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    const
{
  ast_dump_context->print_indent();
  ast_dump_context->dump_expression(this->lhs_);
  ast_dump_context->ostream() << " = " ;
  ast_dump_context->dump_expression(this->rhs_);
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make an assignment statement.

Assignment_statement*
Statement::make_assignment(Expression* lhs, Expression* rhs,
			   Location location)
{
  Temporary_reference_expression* tre = lhs->temporary_reference_expression();
  if (tre != NULL)
    tre->statement()->set_assigned();
  return new Assignment_statement(lhs, rhs, location);
}

// An assignment operation statement.

class Assignment_operation_statement : public Statement
{
 public:
  Assignment_operation_statement(Operator op, Expression* lhs, Expression* rhs,
				 Location location)
    : Statement(STATEMENT_ASSIGNMENT_OPERATION, location),
      op_(op), lhs_(lhs), rhs_(rhs)
  { }

 protected:
  int
  do_traverse(Traverse*);

  bool
  do_traverse_assignments(Traverse_assignments*)
  { go_unreachable(); }

  Statement*
  do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);

  Bstatement*
  do_get_backend(Translate_context*)
  { go_unreachable(); }

  void
  do_dump_statement(Ast_dump_context*) const;

 private:
  // The operator (OPERATOR_PLUSEQ, etc.).
  Operator op_;
  // Left hand side.
  Expression* lhs_;
  // Right hand side.
  Expression* rhs_;
};

// Traversal.

int
Assignment_operation_statement::do_traverse(Traverse* traverse)
{
  if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return this->traverse_expression(traverse, &this->rhs_);
}

// Lower an assignment operation statement to a regular assignment
// statement.

Statement*
Assignment_operation_statement::do_lower(Gogo*, Named_object*,
					 Block* enclosing, Statement_inserter*)
{
  Location loc = this->location();

  // We have to evaluate the left hand side expression only once.  We
  // do this by moving out any expression with side effects.
  Block* b = new Block(enclosing, loc);
  Move_ordered_evals moe(b);
  this->lhs_->traverse_subexpressions(&moe);

  Expression* lval = this->lhs_->copy();

  Operator op;
  switch (this->op_)
    {
    case OPERATOR_PLUSEQ:
      op = OPERATOR_PLUS;
      break;
    case OPERATOR_MINUSEQ:
      op = OPERATOR_MINUS;
      break;
    case OPERATOR_OREQ:
      op = OPERATOR_OR;
      break;
    case OPERATOR_XOREQ:
      op = OPERATOR_XOR;
      break;
    case OPERATOR_MULTEQ:
      op = OPERATOR_MULT;
      break;
    case OPERATOR_DIVEQ:
      op = OPERATOR_DIV;
      break;
    case OPERATOR_MODEQ:
      op = OPERATOR_MOD;
      break;
    case OPERATOR_LSHIFTEQ:
      op = OPERATOR_LSHIFT;
      break;
    case OPERATOR_RSHIFTEQ:
      op = OPERATOR_RSHIFT;
      break;
    case OPERATOR_ANDEQ:
      op = OPERATOR_AND;
      break;
    case OPERATOR_BITCLEAREQ:
      op = OPERATOR_BITCLEAR;
      break;
    default:
      go_unreachable();
    }

  Expression* binop = Expression::make_binary(op, lval, this->rhs_, loc);
  Statement* s = Statement::make_assignment(this->lhs_, binop, loc);
  if (b->statements()->empty())
    {
      delete b;
      return s;
    }
  else
    {
      b->add_statement(s);
      return Statement::make_block_statement(b, loc);
    }
}

// Dump the AST representation for an assignment operation statement

void
Assignment_operation_statement::do_dump_statement(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->dump_expression(this->lhs_);
  ast_dump_context->dump_operator(this->op_);
  ast_dump_context->dump_expression(this->rhs_);
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make an assignment operation statement.

Statement*
Statement::make_assignment_operation(Operator op, Expression* lhs,
				     Expression* rhs, Location location)
{
  return new Assignment_operation_statement(op, lhs, rhs, location);
}

// A tuple assignment statement.  This differs from an assignment
// statement in that the right-hand-side expressions are evaluated in
// parallel.

class Tuple_assignment_statement : public Statement
{
 public:
  Tuple_assignment_statement(Expression_list* lhs, Expression_list* rhs,
			     Location location)
    : Statement(STATEMENT_TUPLE_ASSIGNMENT, location),
      lhs_(lhs), rhs_(rhs)
  { }

 protected:
  int
  do_traverse(Traverse* traverse);

  bool
  do_traverse_assignments(Traverse_assignments*)
  { go_unreachable(); }

  Statement*
  do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);

  Bstatement*
  do_get_backend(Translate_context*)
  { go_unreachable(); }

  void
  do_dump_statement(Ast_dump_context*) const;

 private:
  // Left hand side--a list of lvalues.
  Expression_list* lhs_;
  // Right hand side--a list of rvalues.
  Expression_list* rhs_;
};

// Traversal.

int
Tuple_assignment_statement::do_traverse(Traverse* traverse)
{
  if (this->traverse_expression_list(traverse, this->lhs_) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return this->traverse_expression_list(traverse, this->rhs_);
}

// Lower a tuple assignment.  We use temporary variables to split it
// up into a set of single assignments.

Statement*
Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
				     Statement_inserter*)
{
  Location loc = this->location();

  Block* b = new Block(enclosing, loc);

  // First move out any subexpressions on the left hand side.  The
  // right hand side will be evaluated in the required order anyhow.
  Move_ordered_evals moe(b);
  for (Expression_list::iterator plhs = this->lhs_->begin();
       plhs != this->lhs_->end();
       ++plhs)
    Expression::traverse(&*plhs, &moe);

  std::vector<Temporary_statement*> temps;
  temps.reserve(this->lhs_->size());

  Expression_list::const_iterator prhs = this->rhs_->begin();
  for (Expression_list::const_iterator plhs = this->lhs_->begin();
       plhs != this->lhs_->end();
       ++plhs, ++prhs)
    {
      go_assert(prhs != this->rhs_->end());

      if ((*plhs)->is_error_expression()
	  || (*plhs)->type()->is_error()
	  || (*prhs)->is_error_expression()
	  || (*prhs)->type()->is_error())
	continue;

      if ((*plhs)->is_sink_expression())
	{
          if ((*prhs)->type()->is_nil_type())
            this->report_error(_("use of untyped nil"));
          else
            b->add_statement(Statement::make_statement(*prhs, true));
	  continue;
	}

      Temporary_statement* temp = Statement::make_temporary((*plhs)->type(),
							    *prhs, loc);
      b->add_statement(temp);
      temps.push_back(temp);

    }
  go_assert(prhs == this->rhs_->end());

  prhs = this->rhs_->begin();
  std::vector<Temporary_statement*>::const_iterator ptemp = temps.begin();
  for (Expression_list::const_iterator plhs = this->lhs_->begin();
       plhs != this->lhs_->end();
       ++plhs, ++prhs)
    {
      if ((*plhs)->is_error_expression()
	  || (*plhs)->type()->is_error()
	  || (*prhs)->is_error_expression()
	  || (*prhs)->type()->is_error())
	continue;

      if ((*plhs)->is_sink_expression())
	continue;

      Expression* ref = Expression::make_temporary_reference(*ptemp, loc);
      b->add_statement(Statement::make_assignment(*plhs, ref, loc));
      ++ptemp;
    }
  go_assert(ptemp == temps.end() || saw_errors());

  return Statement::make_block_statement(b, loc);
}

// Dump the AST representation for a tuple assignment statement.

void
Tuple_assignment_statement::do_dump_statement(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->dump_expression_list(this->lhs_);
  ast_dump_context->ostream() << " = ";
  ast_dump_context->dump_expression_list(this->rhs_);
  ast_dump_context->ostream()  << dsuffix(location()) << std::endl;
}

// Make a tuple assignment statement.

Statement*
Statement::make_tuple_assignment(Expression_list* lhs, Expression_list* rhs,
				 Location location)
{
  return new Tuple_assignment_statement(lhs, rhs, location);
}

// A tuple assignment from a map index expression.
//   v, ok = m[k]

class Tuple_map_assignment_statement : public Statement
{
public:
  Tuple_map_assignment_statement(Expression* val, Expression* present,
				 Expression* map_index,
				 Location location)
    : Statement(STATEMENT_TUPLE_MAP_ASSIGNMENT, location),
      val_(val), present_(present), map_index_(map_index)
  { }

 protected:
  int
  do_traverse(Traverse* traverse);

  bool
  do_traverse_assignments(Traverse_assignments*)
  { go_unreachable(); }

  Statement*
  do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);

  Bstatement*
  do_get_backend(Translate_context*)
  { go_unreachable(); }

  void
  do_dump_statement(Ast_dump_context*) const;

 private:
  // Lvalue which receives the value from the map.
  Expression* val_;
  // Lvalue which receives whether the key value was present.
  Expression* present_;
  // The map index expression.
  Expression* map_index_;
};

// Traversal.

int
Tuple_map_assignment_statement::do_traverse(Traverse* traverse)
{
  if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
      || this->traverse_expression(traverse, &this->present_) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return this->traverse_expression(traverse, &this->map_index_);
}

// Lower a tuple map assignment.

Statement*
Tuple_map_assignment_statement::do_lower(Gogo* gogo, Named_object*,
					 Block* enclosing, Statement_inserter*)
{
  Location loc = this->location();

  Map_index_expression* map_index = this->map_index_->map_index_expression();
  if (map_index == NULL)
    {
      this->report_error(_("expected map index on right hand side"));
      return Statement::make_error_statement(loc);
    }
  Map_type* map_type = map_index->get_map_type();
  if (map_type == NULL)
    return Statement::make_error_statement(loc);

  // Avoid copy for string([]byte) conversions used in map keys.
  // mapaccess doesn't keep the reference, so this is safe.
  Type_conversion_expression* ce = map_index->index()->conversion_expression();
  if (ce != NULL && ce->type()->is_string_type()
      && ce->expr()->type()->is_slice_type())
    ce->set_no_copy(true);

  Block* b = new Block(enclosing, loc);

  // Move out any subexpressions to make sure that functions are
  // called in the required order.
  Move_ordered_evals moe(b);
  this->val_->traverse_subexpressions(&moe);
  this->present_->traverse_subexpressions(&moe);

  // Copy the key value into a temporary so that we can take its
  // address without pushing the value onto the heap.

  // var key_temp KEY_TYPE = MAP_INDEX
  Temporary_statement* key_temp =
    Statement::make_temporary(map_type->key_type(), map_index->index(), loc);
  b->add_statement(key_temp);

  // var val_ptr_temp *VAL_TYPE
  Type* val_ptr_type = Type::make_pointer_type(map_type->val_type());
  Temporary_statement* val_ptr_temp = Statement::make_temporary(val_ptr_type,
								NULL, loc);
  b->add_statement(val_ptr_temp);

  // var present_temp bool
  Temporary_statement* present_temp =
    Statement::make_temporary((this->present_->type()->is_sink_type())
			      ? Type::make_boolean_type()
			      : this->present_->type(),
			      NULL, loc);
  b->add_statement(present_temp);

  // val_ptr_temp, present_temp = mapaccess2(DESCRIPTOR, MAP, &key_temp)
  Expression* a1 = Expression::make_type_descriptor(map_type, loc);
  Expression* a2 = map_index->map();
  Temporary_reference_expression* ref =
    Expression::make_temporary_reference(key_temp, loc);
  Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc);
  Expression* a4 = map_type->fat_zero_value(gogo);
  Call_expression* call;
  if (a4 == NULL)
    {
      Runtime::Function code;
      Map_type::Map_alg alg = map_type->algorithm(gogo);
      switch (alg)
        {
          case Map_type::MAP_ALG_FAST32:
          case Map_type::MAP_ALG_FAST32PTR:
            {
              code = Runtime::MAPACCESS2_FAST32;
              Type* uint32_type = Type::lookup_integer_type("uint32");
              Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
              a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3,
                                                loc);
              a3 = Expression::make_dereference(a3,
                                                Expression::NIL_CHECK_NOT_NEEDED,
                                                loc);
              break;
            }
          case Map_type::MAP_ALG_FAST64:
          case Map_type::MAP_ALG_FAST64PTR:
            {
              code = Runtime::MAPACCESS2_FAST64;
              Type* uint64_type = Type::lookup_integer_type("uint64");
              Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
              a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3,
                                                loc);
              a3 = Expression::make_dereference(a3,
                                                Expression::NIL_CHECK_NOT_NEEDED,
                                                loc);
              break;
            }
          case Map_type::MAP_ALG_FASTSTR:
            code = Runtime::MAPACCESS2_FASTSTR;
            a3 = ref;
            break;
          default:
            code = Runtime::MAPACCESS2;
            break;
        }
      call = Runtime::make_call(code, loc, 3, a1, a2, a3);
    }
  else
    call = Runtime::make_call(Runtime::MAPACCESS2_FAT, loc, 4, a1, a2, a3, a4);
  ref = Expression::make_temporary_reference(val_ptr_temp, loc);
  ref->set_is_lvalue();
  Expression* res = Expression::make_call_result(call, 0);
  res = Expression::make_unsafe_cast(val_ptr_type, res, loc);
  Statement* s = Statement::make_assignment(ref, res, loc);
  b->add_statement(s);
  ref = Expression::make_temporary_reference(present_temp, loc);
  ref->set_is_lvalue();
  res = Expression::make_call_result(call, 1);
  s = Statement::make_assignment(ref, res, loc);
  b->add_statement(s);

  // val = *val__ptr_temp
  ref = Expression::make_temporary_reference(val_ptr_temp, loc);
  Expression* ind =
      Expression::make_dereference(ref, Expression::NIL_CHECK_NOT_NEEDED, loc);
  s = Statement::make_assignment(this->val_, ind, loc);
  b->add_statement(s);

  // present = present_temp
  ref = Expression::make_temporary_reference(present_temp, loc);
  s = Statement::make_assignment(this->present_, ref, loc);
  b->add_statement(s);

  return Statement::make_block_statement(b, loc);
}

// Dump the AST representation for a tuple map assignment statement.

void
Tuple_map_assignment_statement::do_dump_statement(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->dump_expression(this->val_);
  ast_dump_context->ostream() << ", ";
  ast_dump_context->dump_expression(this->present_);
  ast_dump_context->ostream() << " = ";
  ast_dump_context->dump_expression(this->map_index_);
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make a map assignment statement which returns a pair of values.

Statement*
Statement::make_tuple_map_assignment(Expression* val, Expression* present,
				     Expression* map_index,
				     Location location)
{
  return new Tuple_map_assignment_statement(val, present, map_index, location);
}

// A tuple assignment from a receive statement.

class Tuple_receive_assignment_statement : public Statement
{
 public:
  Tuple_receive_assignment_statement(Expression* val, Expression* closed,
				     Expression* channel, Location location)
    : Statement(STATEMENT_TUPLE_RECEIVE_ASSIGNMENT, location),
      val_(val), closed_(closed), channel_(channel)
  { }

 protected:
  int
  do_traverse(Traverse* traverse);

  bool
  do_traverse_assignments(Traverse_assignments*)
  { go_unreachable(); }

  Statement*
  do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);

  Bstatement*
  do_get_backend(Translate_context*)
  { go_unreachable(); }

  void
  do_dump_statement(Ast_dump_context*) const;

 private:
  // Lvalue which receives the value from the channel.
  Expression* val_;
  // Lvalue which receives whether the channel is closed.
  Expression* closed_;
  // The channel on which we receive the value.
  Expression* channel_;
};

// Traversal.

int
Tuple_receive_assignment_statement::do_traverse(Traverse* traverse)
{
  if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
      || this->traverse_expression(traverse, &this->closed_) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return this->traverse_expression(traverse, &this->channel_);
}

// Lower to a function call.

Statement*
Tuple_receive_assignment_statement::do_lower(Gogo*, Named_object*,
					     Block* enclosing,
					     Statement_inserter*)
{
  Location loc = this->location();

  Channel_type* channel_type = this->channel_->type()->channel_type();
  if (channel_type == NULL)
    {
      this->report_error(_("expected channel"));
      return Statement::make_error_statement(loc);
    }
  if (!channel_type->may_receive())
    {
      this->report_error(_("invalid receive on send-only channel"));
      return Statement::make_error_statement(loc);
    }

  Block* b = new Block(enclosing, loc);

  // Make sure that any subexpressions on the left hand side are
  // evaluated in the right order.
  Move_ordered_evals moe(b);
  this->val_->traverse_subexpressions(&moe);
  this->closed_->traverse_subexpressions(&moe);

  // var val_temp ELEMENT_TYPE
  Temporary_statement* val_temp =
    Statement::make_temporary(channel_type->element_type(), NULL, loc);
  b->add_statement(val_temp);

  // var closed_temp bool
  Temporary_statement* closed_temp =
    Statement::make_temporary((this->closed_->type()->is_sink_type())
			      ? Type::make_boolean_type()
			      : this->closed_->type(),
			      NULL, loc);
  b->add_statement(closed_temp);

  // closed_temp = chanrecv2(channel, &val_temp)
  Temporary_reference_expression* ref =
    Expression::make_temporary_reference(val_temp, loc);
  Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
  Expression* call = Runtime::make_call(Runtime::CHANRECV2,
					loc, 2, this->channel_, p2);
  ref = Expression::make_temporary_reference(closed_temp, loc);
  ref->set_is_lvalue();
  Statement* s = Statement::make_assignment(ref, call, loc);
  b->add_statement(s);

  // val = val_temp
  ref = Expression::make_temporary_reference(val_temp, loc);
  s = Statement::make_assignment(this->val_, ref, loc);
  b->add_statement(s);

  // closed = closed_temp
  ref = Expression::make_temporary_reference(closed_temp, loc);
  s = Statement::make_assignment(this->closed_, ref, loc);
  b->add_statement(s);

  return Statement::make_block_statement(b, loc);
}

// Dump the AST representation for a tuple receive statement.

void
Tuple_receive_assignment_statement::do_dump_statement(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->dump_expression(this->val_);
  ast_dump_context->ostream() << ", ";
  ast_dump_context->dump_expression(this->closed_);
  ast_dump_context->ostream() << " <- ";
  ast_dump_context->dump_expression(this->channel_);
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make a nonblocking receive statement.

Statement*
Statement::make_tuple_receive_assignment(Expression* val, Expression* closed,
					 Expression* channel,
					 Location location)
{
  return new Tuple_receive_assignment_statement(val, closed, channel,
						location);
}

// An assignment to a pair of values from a type guard.  This is a
// conditional type guard.  v, ok = i.(type).

class Tuple_type_guard_assignment_statement : public Statement
{
 public:
  Tuple_type_guard_assignment_statement(Expression* val, Expression* ok,
					Expression* expr, Type* type,
					Location location)
    : Statement(STATEMENT_TUPLE_TYPE_GUARD_ASSIGNMENT, location),
      val_(val), ok_(ok), expr_(expr), type_(type)
  { }

 protected:
  int
  do_traverse(Traverse*);

  bool
  do_traverse_assignments(Traverse_assignments*)
  { go_unreachable(); }

  Statement*
  do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);

  Bstatement*
  do_get_backend(Translate_context*)
  { go_unreachable(); }

  void
  do_dump_statement(Ast_dump_context*) const;

 private:
  Call_expression*
  lower_to_type(Runtime::Function);

  void
  lower_to_object_type(Block*, Runtime::Function);

  // The variable which recieves the converted value.
  Expression* val_;
  // The variable which receives the indication of success.
  Expression* ok_;
  // The expression being converted.
  Expression* expr_;
  // The type to which the expression is being converted.
  Type* type_;
};

// Traverse a type guard tuple assignment.

int
Tuple_type_guard_assignment_statement::do_traverse(Traverse* traverse)
{
  if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
      || this->traverse_expression(traverse, &this->ok_) == TRAVERSE_EXIT
      || this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return this->traverse_expression(traverse, &this->expr_);
}

// Lower to a function call.

Statement*
Tuple_type_guard_assignment_statement::do_lower(Gogo*, Named_object*,
						Block* enclosing,
						Statement_inserter*)
{
  Location loc = this->location();

  Type* expr_type = this->expr_->type();
  if (expr_type->interface_type() == NULL)
    {
      if (!expr_type->is_error() && !this->type_->is_error())
	this->report_error(_("type assertion only valid for interface types"));
      return Statement::make_error_statement(loc);
    }

  Block* b = new Block(enclosing, loc);

  // Make sure that any subexpressions on the left hand side are
  // evaluated in the right order.
  Move_ordered_evals moe(b);
  this->val_->traverse_subexpressions(&moe);
  this->ok_->traverse_subexpressions(&moe);

  bool expr_is_empty = expr_type->interface_type()->is_empty();
  Call_expression* call;
  if (this->type_->interface_type() != NULL)
    {
      if (this->type_->interface_type()->is_empty())
	call = Runtime::make_call((expr_is_empty
				   ? Runtime::IFACEE2E2
				   : Runtime::IFACEI2E2),
				  loc, 1, this->expr_);
      else
	call = this->lower_to_type(expr_is_empty
				   ? Runtime::IFACEE2I2
				   : Runtime::IFACEI2I2);
    }
  else if (this->type_->points_to() != NULL)
    call = this->lower_to_type(expr_is_empty
			       ? Runtime::IFACEE2T2P
			       : Runtime::IFACEI2T2P);
  else
    {
      this->lower_to_object_type(b,
				 (expr_is_empty
				  ? Runtime::IFACEE2T2
				  : Runtime::IFACEI2T2));
      call = NULL;
    }

  if (call != NULL)
    {
      Expression* res = Expression::make_call_result(call, 0);
      res = Expression::make_unsafe_cast(this->type_, res, loc);
      Statement* s = Statement::make_assignment(this->val_, res, loc);
      b->add_statement(s);

      res = Expression::make_call_result(call, 1);
      s = Statement::make_assignment(this->ok_, res, loc);
      b->add_statement(s);
    }

  return Statement::make_block_statement(b, loc);
}

// Lower a conversion to a non-empty interface type or a pointer type.

Call_expression*
Tuple_type_guard_assignment_statement::lower_to_type(Runtime::Function code)
{
  Location loc = this->location();
  return Runtime::make_call(code, loc, 2,
			    Expression::make_type_descriptor(this->type_, loc),
			    this->expr_);
}

// Lower a conversion to a non-interface non-pointer type.

void
Tuple_type_guard_assignment_statement::lower_to_object_type(
    Block* b,
    Runtime::Function code)
{
  Location loc = this->location();

  // var val_temp TYPE
  Temporary_statement* val_temp = Statement::make_temporary(this->type_,
							    NULL, loc);
  b->add_statement(val_temp);

  // var ok_temp bool
  Temporary_statement* ok_temp = NULL;
  if (!this->ok_->is_sink_expression())
    {
      ok_temp = Statement::make_temporary(this->ok_->type(),
					  NULL, loc);
      b->add_statement(ok_temp);
    }

  // ok_temp = CODE(type_descriptor, expr, &val_temp)
  Expression* p1 = Expression::make_type_descriptor(this->type_, loc);
  Expression* ref = Expression::make_temporary_reference(val_temp, loc);
  Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
  Expression* call = Runtime::make_call(code, loc, 3, p1, this->expr_, p3);
  Statement* s;
  if (ok_temp == NULL)
    s = Statement::make_statement(call, true);
  else
    {
      Expression* ok_ref = Expression::make_temporary_reference(ok_temp, loc);
      s = Statement::make_assignment(ok_ref, call, loc);
    }
  b->add_statement(s);

  // val = val_temp
  ref = Expression::make_temporary_reference(val_temp, loc);
  s = Statement::make_assignment(this->val_, ref, loc);
  b->add_statement(s);

  // ok = ok_temp
  if (ok_temp != NULL)
    {
      ref = Expression::make_temporary_reference(ok_temp, loc);
      s = Statement::make_assignment(this->ok_, ref, loc);
      b->add_statement(s);
    }
}

// Dump the AST representation for a tuple type guard statement.

void
Tuple_type_guard_assignment_statement::do_dump_statement(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->dump_expression(this->val_);
  ast_dump_context->ostream() << ", ";
  ast_dump_context->dump_expression(this->ok_);
  ast_dump_context->ostream() << " = ";
  ast_dump_context->dump_expression(this->expr_);
  ast_dump_context->ostream() << " . ";
  ast_dump_context->dump_type(this->type_);
  ast_dump_context->ostream()  << dsuffix(location()) << std::endl;
}

// Make an assignment from a type guard to a pair of variables.

Statement*
Statement::make_tuple_type_guard_assignment(Expression* val, Expression* ok,
					    Expression* expr, Type* type,
					    Location location)
{
  return new Tuple_type_guard_assignment_statement(val, ok, expr, type,
						   location);
}

// Class Expression_statement.

// Constructor.

Expression_statement::Expression_statement(Expression* expr, bool is_ignored)
  : Statement(STATEMENT_EXPRESSION, expr->location()),
    expr_(expr), is_ignored_(is_ignored)
{
}

// Determine types.

void
Expression_statement::do_determine_types()
{
  this->expr_->determine_type_no_context();
}

// Check the types of an expression statement.  The only check we do
// is to possibly give an error about discarding the value of the
// expression.

void
Expression_statement::do_check_types(Gogo*)
{
  if (!this->is_ignored_)
    this->expr_->discarding_value();
}

// An expression statement is only a terminating statement if it is
// a call to panic.

bool
Expression_statement::do_may_fall_through() const
{
  const Call_expression* call = this->expr_->call_expression();
  if (call != NULL)
    {
      const Expression* fn = call->fn();
      // panic is still an unknown named object.
      const Unknown_expression* ue = fn->unknown_expression();
      if (ue != NULL)
	{
	  Named_object* no = ue->named_object();

          if (no->is_unknown())
            no = no->unknown_value()->real_named_object();
          if (no != NULL)
            {
              Function_type* fntype;
              if (no->is_function())
                fntype = no->func_value()->type();
              else if (no->is_function_declaration())
                fntype = no->func_declaration_value()->type();
              else
                fntype = NULL;

              // The builtin function panic does not return.
              if (fntype != NULL && fntype->is_builtin() && no->name() == "panic")
                return false;
            }
	}
    }
  return true;
}

// Export an expression statement.

void
Expression_statement::do_export_statement(Export_function_body* efb)
{
  this->expr_->export_expression(efb);
}

// Convert to backend representation.

Bstatement*
Expression_statement::do_get_backend(Translate_context* context)
{
  Bexpression* bexpr = this->expr_->get_backend(context);
  Bfunction* bfunction = context->function()->func_value()->get_decl();
  return context->backend()->expression_statement(bfunction, bexpr);
}

// Dump the AST representation for an expression statement

void
Expression_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    const
{
  ast_dump_context->print_indent();
  ast_dump_context->dump_expression(expr_);
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make an expression statement from an Expression.

Statement*
Statement::make_statement(Expression* expr, bool is_ignored)
{
  return new Expression_statement(expr, is_ignored);
}

// Export data for a block.

void
Block_statement::do_export_statement(Export_function_body* efb)
{
  Block_statement::export_block(efb, this->block_,
				this->is_lowered_for_statement_);
}

void
Block_statement::export_block(Export_function_body* efb, Block* block,
			      bool is_lowered_for_statement)
{
  // We are already indented to the right position.
  char buf[50];
  efb->write_c_string("{");
  if (is_lowered_for_statement)
    efb->write_c_string(" /*for*/");
  snprintf(buf, sizeof buf, " //%d\n",
	   Linemap::location_to_line(block->start_location()));
  efb->write_c_string(buf);

  block->export_block(efb);
  // The indentation is correct for the statements in the block, so
  // subtract one for the closing curly brace.
  efb->decrement_indent();
  efb->indent();
  efb->write_c_string("}");
  // Increment back to the value the caller thinks it has.
  efb->increment_indent();
}

// Import a block statement, returning the block.

Block*
Block_statement::do_import(Import_function_body* ifb, Location loc,
			   bool* is_lowered_for_statement)
{
  go_assert(ifb->match_c_string("{"));
  *is_lowered_for_statement = false;
  if (ifb->match_c_string(" /*for*/"))
    {
      ifb->advance(8);
      *is_lowered_for_statement = true;
    }
  size_t nl = ifb->body().find('\n', ifb->off());
  if (nl == std::string::npos)
    {
      if (!ifb->saw_error())
	go_error_at(ifb->location(),
		    "import error: no newline after %<{%> at %lu",
		    static_cast<unsigned long>(ifb->off()));
      ifb->set_saw_error();
      return NULL;
    }
  ifb->set_off(nl + 1);
  ifb->increment_indent();
  Block* block = new Block(ifb->block(), loc);
  ifb->begin_block(block);
  bool ok = Block::import_block(block, ifb, loc);
  ifb->finish_block();
  ifb->decrement_indent();
  if (!ok)
    return NULL;
  return block;
}

// Convert a block to the backend representation of a statement.

Bstatement*
Block_statement::do_get_backend(Translate_context* context)
{
  Bblock* bblock = this->block_->get_backend(context);
  return context->backend()->block_statement(bblock);
}

// Dump the AST for a block statement

void
Block_statement::do_dump_statement(Ast_dump_context*) const
{
  // block statement braces are dumped when traversing.
}

// Make a block statement.

Block_statement*
Statement::make_block_statement(Block* block, Location location)
{
  return new Block_statement(block, location);
}

// An increment or decrement statement.

class Inc_dec_statement : public Statement
{
 public:
  Inc_dec_statement(bool is_inc, Expression* expr)
    : Statement(STATEMENT_INCDEC, expr->location()),
      expr_(expr), is_inc_(is_inc)
  { }

 protected:
  int
  do_traverse(Traverse* traverse)
  { return this->traverse_expression(traverse, &this->expr_); }

  bool
  do_traverse_assignments(Traverse_assignments*)
  { go_unreachable(); }

  Statement*
  do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);

  Bstatement*
  do_get_backend(Translate_context*)
  { go_unreachable(); }

  void
  do_dump_statement(Ast_dump_context*) const;

 private:
  // The l-value to increment or decrement.
  Expression* expr_;
  // Whether to increment or decrement.
  bool is_inc_;
};

// Lower to += or -=.

Statement*
Inc_dec_statement::do_lower(Gogo*, Named_object*, Block*, Statement_inserter*)
{
  Location loc = this->location();
  if (!this->expr_->type()->is_numeric_type())
    {
      this->report_error("increment or decrement of non-numeric type");
      return Statement::make_error_statement(loc);
    }
  Expression* oexpr = Expression::make_integer_ul(1, this->expr_->type(), loc);
  Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ;
  return Statement::make_assignment_operation(op, this->expr_, oexpr, loc);
}

// Dump the AST representation for a inc/dec statement.

void
Inc_dec_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->dump_expression(expr_);
  ast_dump_context->ostream() << (is_inc_? "++": "--") << dsuffix(location()) << std::endl;
}

// Make an increment statement.

Statement*
Statement::make_inc_statement(Expression* expr)
{
  return new Inc_dec_statement(true, expr);
}

// Make a decrement statement.

Statement*
Statement::make_dec_statement(Expression* expr)
{
  return new Inc_dec_statement(false, expr);
}

// Class Thunk_statement.  This is the base class for go and defer
// statements.

// Constructor.

Thunk_statement::Thunk_statement(Statement_classification classification,
				 Call_expression* call,
				 Location location)
    : Statement(classification, location),
      call_(call), struct_type_(NULL)
{
}

// Return whether this is a simple statement which does not require a
// thunk.

bool
Thunk_statement::is_simple(Function_type* fntype) const
{
  // We need a thunk to call a method, or to pass a variable number of
  // arguments.
  if (fntype->is_method() || fntype->is_varargs())
    return false;

  // A defer statement requires a thunk to set up for whether the
  // function can call recover.
  if (this->classification() == STATEMENT_DEFER)
    return false;

  // We can only permit a single parameter of pointer type.
  const Typed_identifier_list* parameters = fntype->parameters();
  if (parameters != NULL
      && (parameters->size() > 1
	  || (parameters->size() == 1
	      && parameters->begin()->type()->points_to() == NULL)))
    return false;

  // If the function returns multiple values, or returns a type other
  // than integer, floating point, or pointer, then it may get a
  // hidden first parameter, in which case we need the more
  // complicated approach.  This is true even though we are going to
  // ignore the return value.
  const Typed_identifier_list* results = fntype->results();
  if (results != NULL
      && (results->size() > 1
	  || (results->size() == 1
	      && !results->begin()->type()->is_basic_type()
	      && results->begin()->type()->points_to() == NULL)))
    return false;

  // If this calls something that is not a simple function, then we
  // need a thunk.
  Expression* fn = this->call_->call_expression()->fn();
  if (fn->func_expression() == NULL)
    return false;

  // If the function uses a closure, then we need a thunk.  FIXME: We
  // could accept a zero argument function with a closure.
  if (fn->func_expression()->closure() != NULL)
    return false;

  return true;
}

// Traverse a thunk statement.

int
Thunk_statement::do_traverse(Traverse* traverse)
{
  return this->traverse_expression(traverse, &this->call_);
}

// We implement traverse_assignment for a thunk statement because it
// effectively copies the function call.

bool
Thunk_statement::do_traverse_assignments(Traverse_assignments* tassign)
{
  Expression* fn = this->call_->call_expression()->fn();
  Expression* fn2 = fn;
  tassign->value(&fn2, true, false);
  return true;
}

// Determine types in a thunk statement.

void
Thunk_statement::do_determine_types()
{
  this->call_->determine_type_no_context();

  // Now that we know the types of the call, build the struct used to
  // pass parameters.
  Call_expression* ce = this->call_->call_expression();
  if (ce == NULL)
    return;
  Function_type* fntype = ce->get_function_type();
  if (fntype != NULL && !this->is_simple(fntype))
    this->struct_type_ = this->build_struct(fntype);
}

// Check types in a thunk statement.

void
Thunk_statement::do_check_types(Gogo*)
{
  if (!this->call_->discarding_value())
    return;
  Call_expression* ce = this->call_->call_expression();
  if (ce == NULL)
    {
      if (!this->call_->is_error_expression())
	this->report_error("expected call expression");
      return;
    }
}

// The Traverse class used to find and simplify thunk statements.

class Simplify_thunk_traverse : public Traverse
{
 public:
  Simplify_thunk_traverse(Gogo* gogo)
    : Traverse(traverse_functions | traverse_blocks),
      gogo_(gogo), function_(NULL)
  { }

  int
  function(Named_object*);

  int
  block(Block*);

 private:
  // General IR.
  Gogo* gogo_;
  // The function we are traversing.
  Named_object* function_;
};

// Keep track of the current function while looking for thunks.

int
Simplify_thunk_traverse::function(Named_object* no)
{
  go_assert(this->function_ == NULL);
  this->function_ = no;
  int t = no->func_value()->traverse(this);
  this->function_ = NULL;
  if (t == TRAVERSE_EXIT)
    return t;
  return TRAVERSE_SKIP_COMPONENTS;
}

// Look for thunks in a block.

int
Simplify_thunk_traverse::block(Block* b)
{
  // The parser ensures that thunk statements always appear at the end
  // of a block.
  if (b->statements()->size() < 1)
    return TRAVERSE_CONTINUE;
  Thunk_statement* stat = b->statements()->back()->thunk_statement();
  if (stat == NULL)
    return TRAVERSE_CONTINUE;
  if (stat->simplify_statement(this->gogo_, this->function_, b))
    return TRAVERSE_SKIP_COMPONENTS;
  return TRAVERSE_CONTINUE;
}

// Simplify all thunk statements.

void
Gogo::simplify_thunk_statements()
{
  Simplify_thunk_traverse thunk_traverse(this);
  this->traverse(&thunk_traverse);
}

// Return true if the thunk function is a constant, which means that
// it does not need to be passed to the thunk routine.

bool
Thunk_statement::is_constant_function() const
{
  Call_expression* ce = this->call_->call_expression();
  Function_type* fntype = ce->get_function_type();
  if (fntype == NULL)
    {
      go_assert(saw_errors());
      return false;
    }
  if (fntype->is_builtin())
    return true;
  Expression* fn = ce->fn();
  if (fn->func_expression() != NULL)
    return fn->func_expression()->closure() == NULL;
  if (fn->interface_field_reference_expression() != NULL)
    return true;
  return false;
}

// Simplify complex thunk statements into simple ones.  A complicated
// thunk statement is one which takes anything other than zero
// parameters or a single pointer parameter.  We rewrite it into code
// which allocates a struct, stores the parameter values into the
// struct, and does a simple go or defer statement which passes the
// struct to a thunk.  The thunk does the real call.

bool
Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
				    Block* block)
{
  if (this->classification() == STATEMENT_ERROR)
    return false;
  if (this->call_->is_error_expression())
    return false;

  if (this->classification() == STATEMENT_DEFER)
    {
      // Make sure that the defer stack exists for the function.  We
      // will use when converting this statement to the backend
      // representation, but we want it to exist when we start
      // converting the function.
      function->func_value()->defer_stack(this->location());
    }

  Call_expression* ce = this->call_->call_expression();
  Function_type* fntype = ce->get_function_type();
  if (fntype == NULL)
    {
      go_assert(saw_errors());
      this->set_is_error();
      return false;
    }
  if (this->is_simple(fntype))
    return false;

  Expression* fn = ce->fn();
  Interface_field_reference_expression* interface_method =
    fn->interface_field_reference_expression();

  Location location = this->location();

  bool is_constant_function = this->is_constant_function();
  Temporary_statement* fn_temp = NULL;
  if (!is_constant_function)
    {
      fn_temp = Statement::make_temporary(NULL, fn, location);
      block->insert_statement_before(block->statements()->size() - 1, fn_temp);
      fn = Expression::make_temporary_reference(fn_temp, location);
    }

  std::string thunk_name = gogo->thunk_name();

  // Build the thunk.
  this->build_thunk(gogo, thunk_name);

  // Generate code to call the thunk.

  // Get the values to store into the struct which is the single
  // argument to the thunk.

  Expression_list* vals = new Expression_list();
  if (!is_constant_function)
    vals->push_back(fn);

  if (interface_method != NULL)
    vals->push_back(interface_method->expr());

  if (ce->args() != NULL)
    {
      for (Expression_list::const_iterator p = ce->args()->begin();
	   p != ce->args()->end();
	   ++p)
	{
	  if ((*p)->is_constant())
	    continue;
	  vals->push_back(*p);
	}
    }

  // Build the struct.
  Expression* constructor =
    Expression::make_struct_composite_literal(this->struct_type_, vals,
					      location);

  // Allocate the initialized struct on the heap.
  constructor = Expression::make_heap_expression(constructor, location);
  if ((Node::make_node(this)->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
    constructor->heap_expression()->set_allocate_on_stack();

  // Throw an error if the function is nil.  This is so that for `go
  // nil` we get a backtrace from the go statement, rather than a
  // useless backtrace from the brand new goroutine.
  Expression* param = constructor;
  if (!is_constant_function && this->classification() == STATEMENT_GO)
    {
      fn = Expression::make_temporary_reference(fn_temp, location);
      Expression* nil = Expression::make_nil(location);
      Expression* isnil = Expression::make_binary(OPERATOR_EQEQ, fn, nil,
						  location);
      Expression* crash = Runtime::make_call(Runtime::PANIC_GO_NIL,
					     location, 0);
      crash = Expression::make_conditional(isnil, crash,
					   Expression::make_nil(location),
					   location);
      param = Expression::make_compound(crash, constructor, location);
    }

  // Look up the thunk.
  Named_object* named_thunk = gogo->lookup(thunk_name, NULL);
  go_assert(named_thunk != NULL && named_thunk->is_function());

  // Build the call.
  Expression* func = Expression::make_func_reference(named_thunk, NULL,
						     location);
  Expression_list* params = new Expression_list();
  params->push_back(param);
  Call_expression* call = Expression::make_call(func, params, false, location);

  // Build the simple go or defer statement.
  Statement* s;
  if (this->classification() == STATEMENT_GO)
    s = Statement::make_go_statement(call, location);
  else if (this->classification() == STATEMENT_DEFER)
    {
      s = Statement::make_defer_statement(call, location);
      if ((Node::make_node(this)->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
        s->defer_statement()->set_on_stack();
    }
  else
    go_unreachable();

  // The current block should end with the go statement.
  go_assert(block->statements()->size() >= 1);
  go_assert(block->statements()->back() == this);
  block->replace_statement(block->statements()->size() - 1, s);

  // We already ran the determine_types pass, so we need to run it now
  // for the new statement.
  s->determine_types();

  // Sanity check.
  gogo->check_types_in_block(block);

  // Return true to tell the block not to keep looking at statements.
  return true;
}

// Set the name to use for thunk parameter N.

void
Thunk_statement::thunk_field_param(int n, char* buf, size_t buflen)
{
  snprintf(buf, buflen, "a%d", n);
}

// Build a new struct type to hold the parameters for a complicated
// thunk statement.  FNTYPE is the type of the function call.

Struct_type*
Thunk_statement::build_struct(Function_type* fntype)
{
  Location location = this->location();

  Struct_field_list* fields = new Struct_field_list();

  Call_expression* ce = this->call_->call_expression();
  Expression* fn = ce->fn();

  if (!this->is_constant_function())
    {
      // The function to call.
      fields->push_back(Struct_field(Typed_identifier("fn", fntype,
						      location)));
    }

  // If this thunk statement calls a method on an interface, we pass
  // the interface object to the thunk.
  Interface_field_reference_expression* interface_method =
    fn->interface_field_reference_expression();
  if (interface_method != NULL)
    {
      Typed_identifier tid("object", interface_method->expr()->type(),
			   location);
      fields->push_back(Struct_field(tid));
    }

  // The predeclared recover function has no argument.  However, we
  // add an argument when building recover thunks.  Handle that here.
  if (ce->is_recover_call())
    {
      fields->push_back(Struct_field(Typed_identifier("can_recover",
						      Type::lookup_bool_type(),
						      location)));
    }

  const Expression_list* args = ce->args();
  if (args != NULL)
    {
      int i = 0;
      for (Expression_list::const_iterator p = args->begin();
	   p != args->end();
	   ++p, ++i)
	{
	  if ((*p)->is_constant())
	    continue;

	  char buf[50];
	  this->thunk_field_param(i, buf, sizeof buf);
	  fields->push_back(Struct_field(Typed_identifier(buf, (*p)->type(),
							  location)));
	}
    }

  Struct_type *st = Type::make_struct_type(fields, location);
  st->set_is_struct_incomparable();
  return st;
}

// Build the thunk we are going to call.  This is a brand new, albeit
// artificial, function.

void
Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
{
  Location location = this->location();

  Call_expression* ce = this->call_->call_expression();

  bool may_call_recover = false;
  if (this->classification() == STATEMENT_DEFER)
    {
      Func_expression* fn = ce->fn()->func_expression();
      if (fn == NULL)
	may_call_recover = true;
      else
	{
	  const Named_object* no = fn->named_object();
	  if (!no->is_function())
	    may_call_recover = true;
	  else
	    may_call_recover = no->func_value()->calls_recover();
	}
    }

  // Build the type of the thunk.  The thunk takes a single parameter,
  // which is a pointer to the special structure we build.
  const char* const parameter_name = "__go_thunk_parameter";
  Typed_identifier_list* thunk_parameters = new Typed_identifier_list();
  Type* pointer_to_struct_type = Type::make_pointer_type(this->struct_type_);
  thunk_parameters->push_back(Typed_identifier(parameter_name,
					       pointer_to_struct_type,
					       location));

  Typed_identifier_list* thunk_results = NULL;
  if (may_call_recover)
    {
      // When deferring a function which may call recover, add a
      // return value, to disable tail call optimizations which will
      // break the way we check whether recover is permitted.
      thunk_results = new Typed_identifier_list();
      thunk_results->push_back(Typed_identifier("", Type::lookup_bool_type(),
						location));
    }

  Function_type* thunk_type = Type::make_function_type(NULL, thunk_parameters,
						       thunk_results,
						       location);

  // Start building the thunk.
  Named_object* function = gogo->start_function(thunk_name, thunk_type, true,
						location);

  gogo->start_block(location);

  // For a defer statement, start with a call to
  // __go_set_defer_retaddr.  */
  Label* retaddr_label = NULL;
  if (may_call_recover)
    {
      retaddr_label = gogo->add_label_reference("retaddr", location, false);
      Expression* arg = Expression::make_label_addr(retaddr_label, location);
      Expression* call = Runtime::make_call(Runtime::SETDEFERRETADDR,
					    location, 1, arg);

      // This is a hack to prevent the middle-end from deleting the
      // label.
      gogo->start_block(location);
      gogo->add_statement(Statement::make_goto_statement(retaddr_label,
							 location));
      Block* then_block = gogo->finish_block(location);
      then_block->determine_types();

      Statement* s = Statement::make_if_statement(call, then_block, NULL,
						  location);
      s->determine_types();
      gogo->add_statement(s);

      function->func_value()->set_calls_defer_retaddr();
    }

  // Get a reference to the parameter.
  Named_object* named_parameter = gogo->lookup(parameter_name, NULL);
  go_assert(named_parameter != NULL && named_parameter->is_variable());

  // Build the call.  Note that the field names are the same as the
  // ones used in build_struct.
  Expression* thunk_parameter = Expression::make_var_reference(named_parameter,
							       location);
  thunk_parameter =
      Expression::make_dereference(thunk_parameter,
                                   Expression::NIL_CHECK_NOT_NEEDED,
                                   location);

  Interface_field_reference_expression* interface_method =
    ce->fn()->interface_field_reference_expression();

  Expression* func_to_call;
  unsigned int next_index;
  if (this->is_constant_function())
    {
      func_to_call = ce->fn();
      next_index = 0;
    }
  else
    {
      func_to_call = Expression::make_field_reference(thunk_parameter,
						      0, location);
      next_index = 1;
    }

  if (interface_method != NULL)
    {
      // The main program passes the interface object.
      go_assert(next_index == 0);
      Expression* r = Expression::make_field_reference(thunk_parameter, 0,
						       location);
      const std::string& name(interface_method->name());
      func_to_call = Expression::make_interface_field_reference(r, name,
								location);
      next_index = 1;
    }

  Expression_list* call_params = new Expression_list();
  const Struct_field_list* fields = this->struct_type_->fields();
  Struct_field_list::const_iterator p = fields->begin();
  for (unsigned int i = 0; i < next_index; ++i)
    ++p;
  bool is_recover_call = ce->is_recover_call();
  Expression* recover_arg = NULL;

  const Expression_list* args = ce->args();
  if (args != NULL)
    {
      for (Expression_list::const_iterator arg = args->begin();
	   arg != args->end();
	   ++arg)
	{
	  Expression* param;
	  if ((*arg)->is_constant())
	    param = *arg;
	  else
	    {
	      Expression* thunk_param =
		Expression::make_var_reference(named_parameter, location);
             thunk_param =
                 Expression::make_dereference(thunk_param,
                                              Expression::NIL_CHECK_NOT_NEEDED,
                                              location);
	      param = Expression::make_field_reference(thunk_param,
						       next_index,
						       location);
	      ++next_index;
	    }

	  if (!is_recover_call)
	    call_params->push_back(param);
	  else
	    {
	      go_assert(call_params->empty());
	      recover_arg = param;
	    }
	}
    }

  if (call_params->empty())
    {
      delete call_params;
      call_params = NULL;
    }

  Call_expression* call = Expression::make_call(func_to_call, call_params,
						false, location);

  // This call expression was already lowered before entering the
  // thunk statement.  Don't try to lower varargs again, as that will
  // cause confusion for, e.g., method calls which already have a
  // receiver parameter.
  call->set_varargs_are_lowered();

  Statement* call_statement = Statement::make_statement(call, true);

  gogo->add_statement(call_statement);

  // If this is a defer statement, the label comes immediately after
  // the call.
  if (may_call_recover)
    {
      gogo->add_label_definition("retaddr", location);

      Expression_list* vals = new Expression_list();
      vals->push_back(Expression::make_boolean(false, location));
      gogo->add_statement(Statement::make_return_statement(vals, location));
    }

  Block* b = gogo->finish_block(location);

  gogo->add_block(b, location);

  gogo->lower_block(function, b);

  // We already ran the determine_types pass, so we need to run it
  // just for the call statement now.  The other types are known.
  call_statement->determine_types();

  gogo->add_conversions_in_block(b);

  if (may_call_recover
      || recover_arg != NULL
      || this->classification() == STATEMENT_GO)
    {
      // Dig up the call expression, which may have been changed
      // during lowering.
      go_assert(call_statement->classification() == STATEMENT_EXPRESSION);
      Expression_statement* es =
	static_cast<Expression_statement*>(call_statement);
      ce = es->expr()->call_expression();
      if (ce == NULL)
	go_assert(saw_errors());
      else
	{
	  if (may_call_recover)
	    ce->set_is_deferred();
	  if (this->classification() == STATEMENT_GO)
	    ce->set_is_concurrent();
	  if (recover_arg != NULL)
	    ce->set_recover_arg(recover_arg);
	}
    }

  gogo->flatten_block(function, b);

  // That is all the thunk has to do.
  gogo->finish_function(location);
}

// Get the function and argument expressions.

bool
Thunk_statement::get_fn_and_arg(Expression** pfn, Expression** parg)
{
  if (this->call_->is_error_expression())
    return false;

  Call_expression* ce = this->call_->call_expression();

  Expression* fn = ce->fn();
  Func_expression* fe = fn->func_expression();
  go_assert(fe != NULL);
  *pfn = Expression::make_func_code_reference(fe->named_object(),
					      fe->location());

  const Expression_list* args = ce->args();
  if (args == NULL || args->empty())
    *parg = Expression::make_nil(this->location());
  else
    {
      go_assert(args->size() == 1);
      *parg = args->front();
    }

  return true;
}

// Class Go_statement.

Bstatement*
Go_statement::do_get_backend(Translate_context* context)
{
  Expression* fn;
  Expression* arg;
  if (!this->get_fn_and_arg(&fn, &arg))
    return context->backend()->error_statement();

  Expression* call = Runtime::make_call(Runtime::GO, this->location(), 2,
					fn, arg);
  Bexpression* bcall = call->get_backend(context);
  Bfunction* bfunction = context->function()->func_value()->get_decl();
  return context->backend()->expression_statement(bfunction, bcall);
}

// Dump the AST representation for go statement.

void
Go_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << "go ";
  ast_dump_context->dump_expression(this->call());
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make a go statement.

Statement*
Statement::make_go_statement(Call_expression* call, Location location)
{
  return new Go_statement(call, location);
}

// Class Defer_statement.

Bstatement*
Defer_statement::do_get_backend(Translate_context* context)
{
  Expression* fn;
  Expression* arg;
  if (!this->get_fn_and_arg(&fn, &arg))
    return context->backend()->error_statement();

  Location loc = this->location();
  Expression* ds = context->function()->func_value()->defer_stack(loc);

  Expression* call;
  if (this->on_stack_)
    {
      if (context->gogo()->debug_optimization())
        go_debug(loc, "stack allocated defer");

      Type* defer_type = Defer_statement::defer_struct_type();
      Expression* defer = Expression::make_allocation(defer_type, loc);
      defer->allocation_expression()->set_allocate_on_stack();
      defer->allocation_expression()->set_no_zero();
      call = Runtime::make_call(Runtime::DEFERPROCSTACK, loc, 4,
                                defer, ds, fn, arg);
    }
  else
    call = Runtime::make_call(Runtime::DEFERPROC, loc, 3,
                              ds, fn, arg);
  Bexpression* bcall = call->get_backend(context);
  Bfunction* bfunction = context->function()->func_value()->get_decl();
  return context->backend()->expression_statement(bfunction, bcall);
}

Type*
Defer_statement::defer_struct_type()
{
  Type* ptr_type = Type::make_pointer_type(Type::make_void_type());
  Type* uintptr_type = Type::lookup_integer_type("uintptr");
  Type* bool_type = Type::make_boolean_type();
  return Type::make_builtin_struct_type(9,
                                        "link", ptr_type,
                                        "frame", ptr_type,
                                        "panicStack", ptr_type,
                                        "_panic", ptr_type,
                                        "pfn", uintptr_type,
                                        "arg", ptr_type,
                                        "retaddr", uintptr_type,
                                        "makefunccanrecover", bool_type,
                                        "heap", bool_type);
}

// Dump the AST representation for defer statement.

void
Defer_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << "defer ";
  ast_dump_context->dump_expression(this->call());
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make a defer statement.

Statement*
Statement::make_defer_statement(Call_expression* call,
				Location location)
{
  return new Defer_statement(call, location);
}

// Class Return_statement.

// Traverse assignments.  We treat each return value as a top level
// RHS in an expression.

bool
Return_statement::do_traverse_assignments(Traverse_assignments* tassign)
{
  Expression_list* vals = this->vals_;
  if (vals != NULL)
    {
      for (Expression_list::iterator p = vals->begin();
	   p != vals->end();
	   ++p)
	tassign->value(&*p, true, true);
    }
  return true;
}

// Lower a return statement.  If we are returning a function call
// which returns multiple values which match the current function,
// split up the call's results.  If the return statement lists
// explicit values, implement this statement by assigning the values
// to the result variables and change this statement to a naked
// return.  This lets panic/recover work correctly.

Statement*
Return_statement::do_lower(Gogo*, Named_object* function, Block* enclosing,
			   Statement_inserter*)
{
  if (this->is_lowered_)
    return this;

  Expression_list* vals = this->vals_;
  this->vals_ = NULL;
  this->is_lowered_ = true;

  Location loc = this->location();

  size_t vals_count = vals == NULL ? 0 : vals->size();
  Function::Results* results = function->func_value()->result_variables();
  size_t results_count = results == NULL ? 0 : results->size();

  if (vals_count == 0)
    {
      if (results_count > 0 && !function->func_value()->results_are_named())
	{
	  this->report_error(_("not enough arguments to return"));
	  return this;
	}
      return this;
    }

  if (results_count == 0)
    {
      this->report_error(_("return with value in function "
			   "with no return type"));
      return this;
    }

  // If the current function has multiple return values, and we are
  // returning a single call expression, split up the call expression.
  if (results_count > 1
      && vals->size() == 1
      && vals->front()->call_expression() != NULL)
    {
      Call_expression* call = vals->front()->call_expression();
      call->set_expected_result_count(results_count);
      delete vals;
      vals = new Expression_list;
      for (size_t i = 0; i < results_count; ++i)
	vals->push_back(Expression::make_call_result(call, i));
      vals_count = results_count;
    }

  if (vals_count < results_count)
    {
      this->report_error(_("not enough arguments to return"));
      return this;
    }

  if (vals_count > results_count)
    {
      this->report_error(_("too many values in return statement"));
      return this;
    }

  Block* b = new Block(enclosing, loc);

  Expression_list* lhs = new Expression_list();
  Expression_list* rhs = new Expression_list();

  Expression_list::const_iterator pe = vals->begin();
  int i = 1;
  for (Function::Results::const_iterator pr = results->begin();
       pr != results->end();
       ++pr, ++pe, ++i)
    {
      Named_object* rv = *pr;
      Expression* e = *pe;

      // Check types now so that we give a good error message.  The
      // result type is known.  We determine the expression type
      // early.

      Type *rvtype = rv->result_var_value()->type();
      Type_context type_context(rvtype, false);
      e->determine_type(&type_context);

      std::string reason;
      if (Type::are_assignable(rvtype, e->type(), &reason))
	{
	  Expression* ve = Expression::make_var_reference(rv, e->location());
	  lhs->push_back(ve);
	  rhs->push_back(e);
	}
      else
	{
	  if (reason.empty())
	    go_error_at(e->location(),
			"incompatible type for return value %d", i);
	  else
	    go_error_at(e->location(),
			"incompatible type for return value %d (%s)",
			i, reason.c_str());
	}
    }
  go_assert(lhs->size() == rhs->size());

  if (lhs->empty())
    ;
  else if (lhs->size() == 1)
    {
      b->add_statement(Statement::make_assignment(lhs->front(), rhs->front(),
						  loc));
      delete lhs;
      delete rhs;
    }
  else
    b->add_statement(Statement::make_tuple_assignment(lhs, rhs, loc));

  b->add_statement(this);

  delete vals;

  return Statement::make_block_statement(b, loc);
}

// Convert a return statement to the backend representation.

Bstatement*
Return_statement::do_get_backend(Translate_context* context)
{
  Location loc = this->location();

  Function* function = context->function()->func_value();
  Function::Results* results = function->result_variables();
  std::vector<Bexpression*> retvals;
  if (results != NULL && !results->empty())
    {
      retvals.reserve(results->size());
      for (Function::Results::const_iterator p = results->begin();
	   p != results->end();
	   p++)
	{
	  Expression* vr = Expression::make_var_reference(*p, loc);
	  retvals.push_back(vr->get_backend(context));
	}
    }

  return context->backend()->return_statement(function->get_decl(),
					      retvals, loc);
}

// Export a return statement.  At this point all the expressions have
// been converted to assignments to the result variables, so this is
// simple.

void
Return_statement::do_export_statement(Export_function_body* efb)
{
  efb->write_c_string("return");
}

// Dump the AST representation for a return statement.

void
Return_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << "return " ;
  ast_dump_context->dump_expression_list(this->vals_);
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make a return statement.

Return_statement*
Statement::make_return_statement(Expression_list* vals,
				 Location location)
{
  return new Return_statement(vals, location);
}

// Make a statement that returns the result of a call expression.

Statement*
Statement::make_return_from_call(Call_expression* call, Location location)
{
  size_t rc = call->result_count();
  if (rc == 0)
    return Statement::make_statement(call, true);
  else
    {
      Expression_list* vals = new Expression_list();
      if (rc == 1)
	vals->push_back(call);
      else
	{
	  for (size_t i = 0; i < rc; ++i)
	    vals->push_back(Expression::make_call_result(call, i));
	}
      return Statement::make_return_statement(vals, location);
    }
}

// A break or continue statement.

class Bc_statement : public Statement
{
 public:
  Bc_statement(bool is_break, Unnamed_label* label, Location location)
    : Statement(STATEMENT_BREAK_OR_CONTINUE, location),
      label_(label), is_break_(is_break)
  { }

  bool
  is_break() const
  { return this->is_break_; }

 protected:
  int
  do_traverse(Traverse*)
  { return TRAVERSE_CONTINUE; }

  bool
  do_may_fall_through() const
  { return false; }

  Bstatement*
  do_get_backend(Translate_context* context)
  { return this->label_->get_goto(context, this->location()); }

  void
  do_dump_statement(Ast_dump_context*) const;

 private:
  // The label that this branches to.
  Unnamed_label* label_;
  // True if this is "break", false if it is "continue".
  bool is_break_;
};

// Dump the AST representation for a break/continue statement

void
Bc_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << (this->is_break_ ? "break" : "continue");
  if (this->label_ != NULL)
    {
      ast_dump_context->ostream() << " ";
      ast_dump_context->dump_label_name(this->label_);
    }
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make a break statement.

Statement*
Statement::make_break_statement(Unnamed_label* label, Location location)
{
  return new Bc_statement(true, label, location);
}

// Make a continue statement.

Statement*
Statement::make_continue_statement(Unnamed_label* label,
				   Location location)
{
  return new Bc_statement(false, label, location);
}

// Class Goto_statement.

int
Goto_statement::do_traverse(Traverse*)
{
  return TRAVERSE_CONTINUE;
}

// Check types for a label.  There aren't any types per se, but we use
// this to give an error if the label was never defined.

void
Goto_statement::do_check_types(Gogo*)
{
  if (!this->label_->is_defined())
    {
      go_error_at(this->location(), "reference to undefined label %qs",
		  Gogo::message_name(this->label_->name()).c_str());
      this->set_is_error();
    }
}

// Convert the goto statement to the backend representation.

Bstatement*
Goto_statement::do_get_backend(Translate_context* context)
{
  Blabel* blabel = this->label_->get_backend_label(context);
  return context->backend()->goto_statement(blabel, this->location());
}

// Export a goto statement.

void
Goto_statement::do_export_statement(Export_function_body *efb)
{
  efb->write_c_string("goto ");
  efb->write_string(this->label_->name());
}

// Import a goto or goto unnamed statement.

Statement*
Goto_statement::do_import(Import_function_body* ifb, Location loc)
{
  ifb->require_c_string("goto ");
  std::string id = ifb->read_identifier();
  if (id[0] != '$')
    {
      Function* fn = ifb->function()->func_value();
      Label* label = fn->add_label_reference(ifb->gogo(), id, loc, false);
      return Statement::make_goto_statement(label, loc);
    }
  else
    {
      if (id[1] != 'l')
	{
	  if (!ifb->saw_error())
	    go_error_at(loc,
			("invalid export data for %qs: "
			 "bad unnamed label at %lu"),
			ifb->name().c_str(),
			static_cast<unsigned long>(ifb->off()));
	  ifb->set_saw_error();
	  return Statement::make_error_statement(loc);
	}
      const char* p = id.c_str();
      char* end;
      long idx = strtol(p + 2, &end, 10);
      if (*end != '\0' || idx > 0x7fffffff)
	{
	  if (!ifb->saw_error())
	    go_error_at(loc,
			("invalid export data for %qs: "
			 "bad unnamed label index at %lu"),
			ifb->name().c_str(),
			static_cast<unsigned long>(ifb->off()));
	  ifb->set_saw_error();
	  return Statement::make_error_statement(loc);
	}

      Unnamed_label* label = ifb->unnamed_label(idx, loc);
      return Statement::make_goto_unnamed_statement(label, loc);
    }
}

// Dump the AST representation for a goto statement.

void
Goto_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << "goto " << this->label_->name() << dsuffix(location()) << std::endl;
}

// Make a goto statement.

Statement*
Statement::make_goto_statement(Label* label, Location location)
{
  return new Goto_statement(label, location);
}

// Class Goto_unnamed_statement.

int
Goto_unnamed_statement::do_traverse(Traverse*)
{
  return TRAVERSE_CONTINUE;
}

// Convert the goto unnamed statement to the backend representation.

Bstatement*
Goto_unnamed_statement::do_get_backend(Translate_context* context)
{
  return this->label_->get_goto(context, this->location());
}

// Export a goto unnamed statement.

void
Goto_unnamed_statement::do_export_statement(Export_function_body *efb)
{
  unsigned int index = efb->unnamed_label_index(this->label_);
  char buf[100];
  snprintf(buf, sizeof buf, "goto $l%u", index);
  efb->write_c_string(buf);
}

// Dump the AST representation for an unnamed goto statement

void
Goto_unnamed_statement::do_dump_statement(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << "goto ";
  ast_dump_context->dump_label_name(this->label_);
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make a goto statement to an unnamed label.

Statement*
Statement::make_goto_unnamed_statement(Unnamed_label* label,
				       Location location)
{
  return new Goto_unnamed_statement(label, location);
}

// Class Label_statement.

// Traversal.

int
Label_statement::do_traverse(Traverse*)
{
  return TRAVERSE_CONTINUE;
}

// Return the backend representation of the statement defining this
// label.

Bstatement*
Label_statement::do_get_backend(Translate_context* context)
{
  if (this->label_->is_dummy_label())
    {
      Bexpression* bce = context->backend()->boolean_constant_expression(false);
      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);
}

// Export a label.

void
Label_statement::do_export_statement(Export_function_body* efb)
{
  if (this->label_->is_dummy_label())
    return;
  // We use a leading colon, not a trailing one, to simplify import.
  efb->write_c_string(":");
  efb->write_string(this->label_->name());
}

// Import a label or an unnamed label.

Statement*
Label_statement::do_import(Import_function_body* ifb, Location loc)
{
  ifb->require_c_string(":");
  std::string id = ifb->read_identifier();
  if (id[0] != '$')
    {
      Function* fn = ifb->function()->func_value();
      Label* label = fn->add_label_definition(ifb->gogo(), id, loc);
      return Statement::make_label_statement(label, loc);
    }
  else
    {
      if (id[1] != 'l')
	{
	  if (!ifb->saw_error())
	    go_error_at(loc,
			("invalid export data for %qs: "
			 "bad unnamed label at %lu"),
			ifb->name().c_str(),
			static_cast<unsigned long>(ifb->off()));
	  ifb->set_saw_error();
	  return Statement::make_error_statement(loc);
	}
      const char* p = id.c_str();
      char* end;
      long idx = strtol(p + 2, &end, 10);
      if (*end != '\0' || idx > 0x7fffffff)
	{
	  if (!ifb->saw_error())
	    go_error_at(loc,
			("invalid export data for %qs: "
			 "bad unnamed label index at %lu"),
			ifb->name().c_str(),
			static_cast<unsigned long>(ifb->off()));
	  ifb->set_saw_error();
	  return Statement::make_error_statement(loc);
	}

      Unnamed_label* label = ifb->unnamed_label(idx, loc);
      return Statement::make_unnamed_label_statement(label);
    }
}

// Dump the AST for a label definition statement.

void
Label_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << this->label_->name() << ":" << dsuffix(location()) << std::endl;
}

// Make a label statement.

Statement*
Statement::make_label_statement(Label* label, Location location)
{
  return new Label_statement(label, location);
}

// Class Unnamed_label_statement.

Unnamed_label_statement::Unnamed_label_statement(Unnamed_label* label)
  : Statement(STATEMENT_UNNAMED_LABEL, label->location()),
    label_(label)
{ }

int
Unnamed_label_statement::do_traverse(Traverse*)
{
  return TRAVERSE_CONTINUE;
}

// Get the backend definition for this unnamed label statement.

Bstatement*
Unnamed_label_statement::do_get_backend(Translate_context* context)
{
  return this->label_->get_definition(context);
}

// Export an unnamed label.

void
Unnamed_label_statement::do_export_statement(Export_function_body* efb)
{
  unsigned int index = efb->unnamed_label_index(this->label_);
  char buf[50];
  // We use a leading colon, not a trailing one, to simplify import.
  snprintf(buf, sizeof buf, ":$l%u", index);
  efb->write_c_string(buf);
}

// Dump the AST representation for an unnamed label definition statement.

void
Unnamed_label_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    const
{
  ast_dump_context->print_indent();
  ast_dump_context->dump_label_name(this->label_);
  ast_dump_context->ostream() << ":" << dsuffix(location()) << std::endl;
}

// Make an unnamed label statement.

Statement*
Statement::make_unnamed_label_statement(Unnamed_label* label)
{
  return new Unnamed_label_statement(label);
}

// Class If_statement.

// Traversal.

int
If_statement::do_traverse(Traverse* traverse)
{
  if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT
      || this->then_block_->traverse(traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (this->else_block_ != NULL)
    {
      if (this->else_block_->traverse(traverse) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  return TRAVERSE_CONTINUE;
}

void
If_statement::do_determine_types()
{
  Type_context context(Type::lookup_bool_type(), false);
  this->cond_->determine_type(&context);
  this->then_block_->determine_types();
  if (this->else_block_ != NULL)
    this->else_block_->determine_types();
}

// Check types.

void
If_statement::do_check_types(Gogo*)
{
  Type* type = this->cond_->type();
  if (type->is_error())
    this->set_is_error();
  else if (!type->is_boolean_type())
    this->report_error(_("expected boolean expression"));
}

// Whether the overall statement may fall through.

bool
If_statement::do_may_fall_through() const
{
  return (this->else_block_ == NULL
	  || this->then_block_->may_fall_through()
	  || this->else_block_->may_fall_through());
}

// Get the backend representation.

Bstatement*
If_statement::do_get_backend(Translate_context* context)
{
  go_assert(this->cond_->type()->is_boolean_type()
	     || this->cond_->type()->is_error());
  Bexpression* cond = this->cond_->get_backend(context);
  Bblock* then_block = this->then_block_->get_backend(context);
  Bblock* else_block = (this->else_block_ == NULL
			? NULL
			: this->else_block_->get_backend(context));
  Bfunction* bfunction = context->function()->func_value()->get_decl();
  return context->backend()->if_statement(bfunction,
                                          cond, then_block, else_block,
					  this->location());
}

// Export an if statement.

void
If_statement::do_export_statement(Export_function_body* efb)
{
  efb->write_c_string("if ");
  this->cond_->export_expression(efb);
  efb->write_c_string(" ");
  Block_statement::export_block(efb, this->then_block_, false);
  if (this->else_block_ != NULL)
    {
      efb->write_c_string(" else ");
      Block_statement::export_block(efb, this->else_block_, false);
    }
}

// Import an if statement.

Statement*
If_statement::do_import(Import_function_body* ifb, Location loc)
{
  ifb->require_c_string("if ");

  Expression* cond = Expression::import_expression(ifb, loc);
  ifb->require_c_string(" ");

  if (!ifb->match_c_string("{"))
    {
      if (!ifb->saw_error())
	go_error_at(ifb->location(),
		    "import error for %qs: no block for if statement at %lu",
		    ifb->name().c_str(),
		    static_cast<unsigned long>(ifb->off()));
      ifb->set_saw_error();
      return Statement::make_error_statement(loc);
    }

  bool is_lowered_for_statement;
  Block* then_block = Block_statement::do_import(ifb, loc,
						 &is_lowered_for_statement);
  if (then_block == NULL)
    return Statement::make_error_statement(loc);
  if (is_lowered_for_statement)
    {
      if (!ifb->saw_error())
	go_error_at(ifb->location(),
		    ("import error for %qs: "
		     "unexpected lowered for in if statement at %lu"),
		    ifb->name().c_str(),
		    static_cast<unsigned long>(ifb->off()));
      ifb->set_saw_error();
      return Statement::make_error_statement(loc);
    }

  Block* else_block = NULL;
  if (ifb->match_c_string(" else "))
    {
      ifb->advance(6);
      if (!ifb->match_c_string("{"))
	{
	  if (!ifb->saw_error())
	    go_error_at(ifb->location(),
			("import error for %qs: no else block "
			 "for if statement at %lu"),
			ifb->name().c_str(),
			static_cast<unsigned long>(ifb->off()));
	  ifb->set_saw_error();
	  return Statement::make_error_statement(loc);
	}

      else_block = Block_statement::do_import(ifb, loc,
					      &is_lowered_for_statement);
      if (else_block == NULL)
	return Statement::make_error_statement(loc);
      if (is_lowered_for_statement)
	{
	  if (!ifb->saw_error())
	    go_error_at(ifb->location(),
			("import error for %qs: "
			 "unexpected lowered for in if statement at %lu"),
			ifb->name().c_str(),
			static_cast<unsigned long>(ifb->off()));
	  ifb->set_saw_error();
	  return Statement::make_error_statement(loc);
	}
    }

  return Statement::make_if_statement(cond, then_block, else_block, loc);
}

// Dump the AST representation for an if statement

void
If_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << "if ";
  ast_dump_context->dump_expression(this->cond_);
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  if (ast_dump_context->dump_subblocks())
    {
      ast_dump_context->dump_block(this->then_block_);
      if (this->else_block_ != NULL)
	{
	  ast_dump_context->print_indent();
	  ast_dump_context->ostream() << "else" << std::endl;
	  ast_dump_context->dump_block(this->else_block_);
	}
    }
}

// Make an if statement.

Statement*
Statement::make_if_statement(Expression* cond, Block* then_block,
			     Block* else_block, Location location)
{
  return new If_statement(cond, then_block, else_block, location);
}

// Class Case_clauses::Hash_integer_value.

class Case_clauses::Hash_integer_value
{
 public:
  size_t
  operator()(Expression*) const;
};

size_t
Case_clauses::Hash_integer_value::operator()(Expression* pe) const
{
  Numeric_constant nc;
  mpz_t ival;
  if (!pe->numeric_constant_value(&nc) || !nc.to_int(&ival))
    go_unreachable();
  size_t ret = mpz_get_ui(ival);
  mpz_clear(ival);
  return ret;
}

// Class Case_clauses::Eq_integer_value.

class Case_clauses::Eq_integer_value
{
 public:
  bool
  operator()(Expression*, Expression*) const;
};

bool
Case_clauses::Eq_integer_value::operator()(Expression* a, Expression* b) const
{
  Numeric_constant anc;
  mpz_t aval;
  Numeric_constant bnc;
  mpz_t bval;
  if (!a->numeric_constant_value(&anc)
      || !anc.to_int(&aval)
      || !b->numeric_constant_value(&bnc)
      || !bnc.to_int(&bval))
    go_unreachable();
  bool ret = mpz_cmp(aval, bval) == 0;
  mpz_clear(aval);
  mpz_clear(bval);
  return ret;
}

// Class Case_clauses::Case_clause.

// Traversal.

int
Case_clauses::Case_clause::traverse(Traverse* traverse)
{
  if (this->cases_ != NULL
      && (traverse->traverse_mask()
	  & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
    {
      if (this->cases_->traverse(traverse) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  if (this->statements_ != NULL)
    {
      if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  return TRAVERSE_CONTINUE;
}

// Check whether all the case expressions are integer constants.

bool
Case_clauses::Case_clause::is_constant() const
{
  if (this->cases_ != NULL)
    {
      for (Expression_list::const_iterator p = this->cases_->begin();
	   p != this->cases_->end();
	   ++p)
	if (!(*p)->is_constant() || (*p)->type()->integer_type() == NULL)
	  return false;
    }
  return true;
}

// Lower a case clause for a nonconstant switch.  VAL_TEMP is the
// value we are switching on; it may be NULL.  If START_LABEL is not
// NULL, it goes at the start of the statements, after the condition
// test.  We branch to FINISH_LABEL at the end of the statements.

void
Case_clauses::Case_clause::lower(Block* b, Temporary_statement* val_temp,
				 Unnamed_label* start_label,
				 Unnamed_label* finish_label) const
{
  Location loc = this->location_;
  Unnamed_label* next_case_label;
  if (this->cases_ == NULL || this->cases_->empty())
    {
      go_assert(this->is_default_);
      next_case_label = NULL;
    }
  else
    {
      Expression* cond = NULL;

      for (Expression_list::const_iterator p = this->cases_->begin();
	   p != this->cases_->end();
	   ++p)
	{
	  Expression* ref = Expression::make_temporary_reference(val_temp,
								 loc);
	  Expression* this_cond = Expression::make_binary(OPERATOR_EQEQ, ref,
							  *p, loc);
	  if (cond == NULL)
	    cond = this_cond;
	  else
	    cond = Expression::make_binary(OPERATOR_OROR, cond, this_cond, loc);
	}

      Block* then_block = new Block(b, loc);
      next_case_label = new Unnamed_label(Linemap::unknown_location());
      Statement* s = Statement::make_goto_unnamed_statement(next_case_label,
							    loc);
      then_block->add_statement(s);

      // if !COND { goto NEXT_CASE_LABEL }
      cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
      s = Statement::make_if_statement(cond, then_block, NULL, loc);
      b->add_statement(s);
    }

  if (start_label != NULL)
    b->add_statement(Statement::make_unnamed_label_statement(start_label));

  if (this->statements_ != NULL)
    b->add_statement(Statement::make_block_statement(this->statements_, loc));

  Statement* s = Statement::make_goto_unnamed_statement(finish_label, loc);
  b->add_statement(s);

  if (next_case_label != NULL)
    b->add_statement(Statement::make_unnamed_label_statement(next_case_label));
}

// Determine types.

void
Case_clauses::Case_clause::determine_types(Type* type)
{
  if (this->cases_ != NULL)
    {
      Type_context case_context(type, false);
      for (Expression_list::iterator p = this->cases_->begin();
	   p != this->cases_->end();
	   ++p)
	(*p)->determine_type(&case_context);
    }
  if (this->statements_ != NULL)
    this->statements_->determine_types();
}

// Check types.  Returns false if there was an error.

bool
Case_clauses::Case_clause::check_types(Type* type)
{
  if (this->cases_ != NULL)
    {
      for (Expression_list::iterator p = this->cases_->begin();
	   p != this->cases_->end();
	   ++p)
	{
	  if (!Type::are_assignable(type, (*p)->type(), NULL)
	      && !Type::are_assignable((*p)->type(), type, NULL))
	    {
	      go_error_at((*p)->location(),
			  "type mismatch between switch value and case clause");
	      return false;
	    }
	}
    }
  return true;
}

// Return true if this clause may fall through to the following
// statements.  Note that this is not the same as whether the case
// uses the "fallthrough" keyword.

bool
Case_clauses::Case_clause::may_fall_through() const
{
  if (this->statements_ == NULL)
    return true;
  return this->statements_->may_fall_through();
}

// Convert the case values and statements to the backend
// representation.  BREAK_LABEL is the label which break statements
// should branch to.  CASE_CONSTANTS is used to detect duplicate
// constants.  *CASES should be passed as an empty vector; the values
// for this case will be added to it.  If this is the default case,
// *CASES will remain empty.  This returns the statement to execute if
// one of these cases is selected.

Bstatement*
Case_clauses::Case_clause::get_backend(Translate_context* context,
				       Unnamed_label* break_label,
				       Case_constants* case_constants,
				       std::vector<Bexpression*>* cases) const
{
  if (this->cases_ != NULL)
    {
      go_assert(!this->is_default_);
      for (Expression_list::const_iterator p = this->cases_->begin();
	   p != this->cases_->end();
	   ++p)
	{
	  Expression* e = *p;
	  if (e->classification() != Expression::EXPRESSION_INTEGER)
	    {
	      Numeric_constant nc;
	      mpz_t ival;
	      if (!(*p)->numeric_constant_value(&nc) || !nc.to_int(&ival))
		{
		  // Something went wrong.  This can happen with a
		  // negative constant and an unsigned switch value.
		  go_assert(saw_errors());
		  continue;
		}
	      go_assert(nc.type() != NULL);
	      e = Expression::make_integer_z(&ival, nc.type(), e->location());
	      mpz_clear(ival);
	    }

	  std::pair<Case_constants::iterator, bool> ins =
	    case_constants->insert(e);
	  if (!ins.second)
	    {
	      // Value was already present.
	      go_error_at(this->location_, "duplicate case in switch");
	      e = Expression::make_error(this->location_);
	    }
	  cases->push_back(e->get_backend(context));
	}
    }

  Bstatement* statements;
  if (this->statements_ == NULL)
    statements = NULL;
  else
    {
      Bblock* bblock = this->statements_->get_backend(context);
      statements = context->backend()->block_statement(bblock);
    }

  Bstatement* break_stat;
  if (this->is_fallthrough_)
    break_stat = NULL;
  else
    break_stat = break_label->get_goto(context, this->location_);

  if (statements == NULL)
    return break_stat;
  else if (break_stat == NULL)
    return statements;
  else
    return context->backend()->compound_statement(statements, break_stat);
}

// Dump the AST representation for a case clause

void
Case_clauses::Case_clause::dump_clause(Ast_dump_context* ast_dump_context)
    const
{
  ast_dump_context->print_indent();
  if (this->is_default_)
    {
      ast_dump_context->ostream() << "default:";
    }
  else
    {
      ast_dump_context->ostream() << "case ";
      ast_dump_context->dump_expression_list(this->cases_);
      ast_dump_context->ostream() << ":" ;
    }
  ast_dump_context->dump_block(this->statements_);
  if (this->is_fallthrough_)
    {
      ast_dump_context->print_indent();
      ast_dump_context->ostream() <<  " (fallthrough)" << dsuffix(location()) << std::endl;
    }
}

// Class Case_clauses.

// Traversal.

int
Case_clauses::traverse(Traverse* traverse)
{
  for (Clauses::iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    {
      if (p->traverse(traverse) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  return TRAVERSE_CONTINUE;
}

// Check whether all the case expressions are constant.

bool
Case_clauses::is_constant() const
{
  for (Clauses::const_iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    if (!p->is_constant())
      return false;
  return true;
}

// Lower case clauses for a nonconstant switch.

void
Case_clauses::lower(Block* b, Temporary_statement* val_temp,
		    Unnamed_label* break_label) const
{
  // The default case.
  const Case_clause* default_case = NULL;

  // The label for the fallthrough of the previous case.
  Unnamed_label* last_fallthrough_label = NULL;

  // The label for the start of the default case.  This is used if the
  // case before the default case falls through.
  Unnamed_label* default_start_label = NULL;

  // The label for the end of the default case.  This normally winds
  // up as BREAK_LABEL, but it will be different if the default case
  // falls through.
  Unnamed_label* default_finish_label = NULL;

  for (Clauses::const_iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    {
      // The label to use for the start of the statements for this
      // case.  This is NULL unless the previous case falls through.
      Unnamed_label* start_label = last_fallthrough_label;

      // The label to jump to after the end of the statements for this
      // case.
      Unnamed_label* finish_label = break_label;

      last_fallthrough_label = NULL;
      if (p->is_fallthrough() && p + 1 != this->clauses_.end())
	{
	  finish_label = new Unnamed_label(p->location());
	  last_fallthrough_label = finish_label;
	}

      if (!p->is_default())
	p->lower(b, val_temp, start_label, finish_label);
      else
	{
	  // We have to move the default case to the end, so that we
	  // only use it if all the other tests fail.
	  default_case = &*p;
	  default_start_label = start_label;
	  default_finish_label = finish_label;
	}
    }

  if (default_case != NULL)
    default_case->lower(b, val_temp, default_start_label,
			default_finish_label);
}

// Determine types.

void
Case_clauses::determine_types(Type* type)
{
  for (Clauses::iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    p->determine_types(type);
}

// Check types.  Returns false if there was an error.

bool
Case_clauses::check_types(Type* type)
{
  bool ret = true;
  for (Clauses::iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    {
      if (!p->check_types(type))
	ret = false;
    }
  return ret;
}

// Return true if these clauses may fall through to the statements
// following the switch statement.

bool
Case_clauses::may_fall_through() const
{
  bool found_default = false;
  for (Clauses::const_iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    {
      if (p->may_fall_through() && !p->is_fallthrough())
	return true;
      if (p->is_default())
	found_default = true;
    }
  return !found_default;
}

// Convert the cases to the backend representation.  This sets
// *ALL_CASES and *ALL_STATEMENTS.

void
Case_clauses::get_backend(Translate_context* context,
			  Unnamed_label* break_label,
			  std::vector<std::vector<Bexpression*> >* all_cases,
			  std::vector<Bstatement*>* all_statements) const
{
  Case_constants case_constants;

  size_t c = this->clauses_.size();
  all_cases->resize(c);
  all_statements->resize(c);

  size_t i = 0;
  for (Clauses::const_iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p, ++i)
    {
      std::vector<Bexpression*> cases;
      Bstatement* stat = p->get_backend(context, break_label, &case_constants,
					&cases);
      // The final clause can't fall through.
      if (i == c - 1 && p->is_fallthrough())
        {
          go_assert(saw_errors());
          stat = context->backend()->error_statement();
        }
      (*all_cases)[i].swap(cases);
      (*all_statements)[i] = stat;
    }
}

// Dump the AST representation for case clauses (from a switch statement)

void
Case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
{
  for (Clauses::const_iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    p->dump_clause(ast_dump_context);
}

// A constant switch statement.  A Switch_statement is lowered to this
// when all the cases are constants.

class Constant_switch_statement : public Statement
{
 public:
  Constant_switch_statement(Expression* val, Case_clauses* clauses,
			    Unnamed_label* break_label,
			    Location location)
    : Statement(STATEMENT_CONSTANT_SWITCH, location),
      val_(val), clauses_(clauses), break_label_(break_label)
  { }

 protected:
  int
  do_traverse(Traverse*);

  void
  do_determine_types();

  void
  do_check_types(Gogo*);

  Bstatement*
  do_get_backend(Translate_context*);

  void
  do_dump_statement(Ast_dump_context*) const;

 private:
  // The value to switch on.
  Expression* val_;
  // The case clauses.
  Case_clauses* clauses_;
  // The break label, if needed.
  Unnamed_label* break_label_;
};

// Traversal.

int
Constant_switch_statement::do_traverse(Traverse* traverse)
{
  if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return this->clauses_->traverse(traverse);
}

// Determine types.

void
Constant_switch_statement::do_determine_types()
{
  this->val_->determine_type_no_context();
  this->clauses_->determine_types(this->val_->type());
}

// Check types.

void
Constant_switch_statement::do_check_types(Gogo*)
{
  if (!this->clauses_->check_types(this->val_->type()))
    this->set_is_error();
}

// Convert to GENERIC.

Bstatement*
Constant_switch_statement::do_get_backend(Translate_context* context)
{
  Bexpression* switch_val_expr = this->val_->get_backend(context);

  Unnamed_label* break_label = this->break_label_;
  if (break_label == NULL)
    break_label = new Unnamed_label(this->location());

  std::vector<std::vector<Bexpression*> > all_cases;
  std::vector<Bstatement*> all_statements;
  this->clauses_->get_backend(context, break_label, &all_cases,
			      &all_statements);

  Bfunction* bfunction = context->function()->func_value()->get_decl();
  Bstatement* switch_statement;
  switch_statement = context->backend()->switch_statement(bfunction,
							  switch_val_expr,
							  all_cases,
							  all_statements,
							  this->location());
  Bstatement* ldef = break_label->get_definition(context);
  return context->backend()->compound_statement(switch_statement, ldef);
}

// Dump the AST representation for a constant switch statement.

void
Constant_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    const
{
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << "switch ";
  ast_dump_context->dump_expression(this->val_);

  if (ast_dump_context->dump_subblocks())
    {
      ast_dump_context->ostream() << " {" << std::endl;
      this->clauses_->dump_clauses(ast_dump_context);
      ast_dump_context->ostream() << "}";
    }

   ast_dump_context->ostream() << std::endl;
}

// Class Switch_statement.

// Traversal.

int
Switch_statement::do_traverse(Traverse* traverse)
{
  if (this->val_ != NULL)
    {
      if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  return this->clauses_->traverse(traverse);
}

// Lower a Switch_statement to a Constant_switch_statement or a series
// of if statements.

Statement*
Switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
			   Statement_inserter*)
{
  Location loc = this->location();

  if (this->val_ != NULL
      && (this->val_->is_error_expression()
	  || this->val_->type()->is_error()))
    {
      go_assert(saw_errors());
      return Statement::make_error_statement(loc);
    }

  if (this->val_ != NULL
      && this->val_->type()->integer_type() != NULL
      && !this->clauses_->empty()
      && this->clauses_->is_constant())
    return new Constant_switch_statement(this->val_, this->clauses_,
					 this->break_label_, loc);

  if (this->val_ != NULL
      && !this->val_->type()->is_comparable()
      && !Type::are_compatible_for_comparison(true, this->val_->type(),
					      Type::make_nil_type(), NULL))
    {
      go_error_at(this->val_->location(),
		  "cannot switch on value whose type that may not be compared");
      return Statement::make_error_statement(loc);
    }

  Block* b = new Block(enclosing, loc);

  if (this->clauses_->empty())
    {
      Expression* val = this->val_;
      if (val == NULL)
	val = Expression::make_boolean(true, loc);
      return Statement::make_statement(val, true);
    }

  // var val_temp VAL_TYPE = VAL
  Expression* val = this->val_;
  if (val == NULL)
    val = Expression::make_boolean(true, loc);

  Type* type = val->type();
  if (type->is_abstract())
    type = type->make_non_abstract_type();
  Temporary_statement* val_temp = Statement::make_temporary(type, val, loc);
  b->add_statement(val_temp);

  this->clauses_->lower(b, val_temp, this->break_label());

  Statement* s = Statement::make_unnamed_label_statement(this->break_label_);
  b->add_statement(s);

  return Statement::make_block_statement(b, loc);
}

// Return the break label for this switch statement, creating it if
// necessary.

Unnamed_label*
Switch_statement::break_label()
{
  if (this->break_label_ == NULL)
    this->break_label_ = new Unnamed_label(this->location());
  return this->break_label_;
}

// Dump the AST representation for a switch statement.

void
Switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << "switch ";
  if (this->val_ != NULL)
    {
      ast_dump_context->dump_expression(this->val_);
    }
  if (ast_dump_context->dump_subblocks())
    {
      ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
      this->clauses_->dump_clauses(ast_dump_context);
      ast_dump_context->print_indent();
      ast_dump_context->ostream() << "}";
    }
  ast_dump_context->ostream() << std::endl;
}

// Return whether this switch may fall through.

bool
Switch_statement::do_may_fall_through() const
{
  if (this->clauses_ == NULL)
    return true;

  // If we have a break label, then some case needed it.  That implies
  // that the switch statement as a whole can fall through.
  if (this->break_label_ != NULL)
    return true;

  return this->clauses_->may_fall_through();
}

// Make a switch statement.

Switch_statement*
Statement::make_switch_statement(Expression* val, Location location)
{
  return new Switch_statement(val, location);
}

// Class Type_case_clauses::Type_case_clause.

// Traversal.

int
Type_case_clauses::Type_case_clause::traverse(Traverse* traverse)
{
  if (!this->is_default_
      && ((traverse->traverse_mask()
	   & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
      && Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (this->statements_ != NULL)
    return this->statements_->traverse(traverse);
  return TRAVERSE_CONTINUE;
}

// Lower one clause in a type switch.  Add statements to the block B.
// The type descriptor we are switching on is in DESCRIPTOR_TEMP.
// BREAK_LABEL is the label at the end of the type switch.
// *STMTS_LABEL, if not NULL, is a label to put at the start of the
// statements.

void
Type_case_clauses::Type_case_clause::lower(Gogo* gogo,
					   Type* switch_val_type,
					   Block* b,
					   Temporary_statement* descriptor_temp,
					   Unnamed_label* break_label,
					   Unnamed_label** stmts_label) const
{
  Location loc = this->location_;

  Unnamed_label* next_case_label = NULL;
  if (!this->is_default_)
    {
      Type* type = this->type_;

      std::string reason;
      if (switch_val_type->interface_type() != NULL
	  && !type->is_nil_constant_as_type()
	  && type->interface_type() == NULL
	  && !switch_val_type->interface_type()->implements_interface(type,
								      &reason))
	{
	  if (reason.empty())
	    go_error_at(this->location_, "impossible type switch case");
	  else
	    go_error_at(this->location_, "impossible type switch case (%s)",
			reason.c_str());
	}

      Expression* ref = Expression::make_temporary_reference(descriptor_temp,
							     loc);

      Expression* cond;
      // The language permits case nil, which is of course a constant
      // rather than a type.  It will appear here as an invalid
      // forwarding type.
      if (type->is_nil_constant_as_type())
	cond = Expression::make_binary(OPERATOR_EQEQ, ref,
				       Expression::make_nil(loc),
				       loc);
      else if (type->interface_type() == NULL)
	{
	  if (!gogo->need_eqtype())
	    cond = Expression::make_binary(OPERATOR_EQEQ, ref,
				           Expression::make_type_descriptor(type, loc),
				           loc);
	  else
	    cond = Runtime::make_call(Runtime::EQTYPE, loc, 2,
				      Expression::make_type_descriptor(type, loc),
				      ref);
	}
      else
	cond = Runtime::make_call(Runtime::IFACET2IP, loc, 2,
				  Expression::make_type_descriptor(type, loc),
				  ref);

      Unnamed_label* dest;
      if (!this->is_fallthrough_)
	{
	  // if !COND { goto NEXT_CASE_LABEL }
	  next_case_label = new Unnamed_label(Linemap::unknown_location());
	  dest = next_case_label;
	  cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
	}
      else
	{
	  // if COND { goto STMTS_LABEL }
	  go_assert(stmts_label != NULL);
	  if (*stmts_label == NULL)
	    *stmts_label = new Unnamed_label(Linemap::unknown_location());
	  dest = *stmts_label;
	}
      Block* then_block = new Block(b, loc);
      Statement* s = Statement::make_goto_unnamed_statement(dest, loc);
      then_block->add_statement(s);
      s = Statement::make_if_statement(cond, then_block, NULL, loc);
      b->add_statement(s);
    }

  if (this->statements_ != NULL
      || (!this->is_fallthrough_
	  && stmts_label != NULL
	  && *stmts_label != NULL))
    {
      go_assert(!this->is_fallthrough_);
      if (stmts_label != NULL && *stmts_label != NULL)
	{
	  go_assert(!this->is_default_);
	  if (this->statements_ != NULL)
	    (*stmts_label)->set_location(this->statements_->start_location());
	  Statement* s = Statement::make_unnamed_label_statement(*stmts_label);
	  b->add_statement(s);
	  *stmts_label = NULL;
	}
      if (this->statements_ != NULL)
	b->add_statement(Statement::make_block_statement(this->statements_,
							 loc));
    }

  if (this->is_fallthrough_)
    go_assert(next_case_label == NULL);
  else
    {
      Location gloc = (this->statements_ == NULL
			      ? loc
			      : this->statements_->end_location());
      b->add_statement(Statement::make_goto_unnamed_statement(break_label,
							      gloc));
      if (next_case_label != NULL)
	{
	  Statement* s =
	    Statement::make_unnamed_label_statement(next_case_label);
	  b->add_statement(s);
	}
    }
}

// Return true if this type clause may fall through to the statements
// following the switch.

bool
Type_case_clauses::Type_case_clause::may_fall_through() const
{
  if (this->is_fallthrough_)
    {
      // This case means that we automatically fall through to the
      // next case (it's used for T1 in case T1, T2:).  It does not
      // mean that we fall through to the end of the type switch as a
      // whole.  There is sure to be a next case and that next case
      // will determine whether we fall through to the statements
      // after the type switch.
      return false;
    }
  if (this->statements_ == NULL)
    return true;
  return this->statements_->may_fall_through();
}

// Dump the AST representation for a type case clause

void
Type_case_clauses::Type_case_clause::dump_clause(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  if (this->is_default_)
    {
      ast_dump_context->ostream() << "default:";
    }
  else
    {
      ast_dump_context->ostream() << "case ";
      ast_dump_context->dump_type(this->type_);
      ast_dump_context->ostream() << ":" ;
    }
  ast_dump_context->dump_block(this->statements_);
  if (this->is_fallthrough_)
    {
      ast_dump_context->print_indent();
      ast_dump_context->ostream() <<  " (fallthrough)" << std::endl;
    }
}

// Class Type_case_clauses.

// Traversal.

int
Type_case_clauses::traverse(Traverse* traverse)
{
  for (Type_clauses::iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    {
      if (p->traverse(traverse) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  return TRAVERSE_CONTINUE;
}

// Check for duplicate types.

void
Type_case_clauses::check_duplicates() const
{
  typedef Unordered_set_hash(const Type*, Type_hash_identical,
			     Type_identical) Types_seen;
  Types_seen types_seen;
  for (Type_clauses::const_iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    {
      Type* t = p->type();
      if (t == NULL)
	continue;
      if (t->is_nil_constant_as_type())
	t = Type::make_nil_type();
      std::pair<Types_seen::iterator, bool> ins = types_seen.insert(t);
      if (!ins.second)
	go_error_at(p->location(), "duplicate type in switch");
    }
}

// Lower the clauses in a type switch.  Add statements to the block B.
// The type descriptor we are switching on is in DESCRIPTOR_TEMP.
// BREAK_LABEL is the label at the end of the type switch.

void
Type_case_clauses::lower(Gogo* gogo, Type* switch_val_type,
			 Block* b,
			 Temporary_statement* descriptor_temp,
			 Unnamed_label* break_label) const
{
  const Type_case_clause* default_case = NULL;

  Unnamed_label* stmts_label = NULL;
  for (Type_clauses::const_iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    {
      if (!p->is_default())
	p->lower(gogo, switch_val_type, b, descriptor_temp, break_label,
		 &stmts_label);
      else
	{
	  // We are generating a series of tests, which means that we
	  // need to move the default case to the end.
	  default_case = &*p;
	}
    }
  go_assert(stmts_label == NULL);

  if (default_case != NULL)
    default_case->lower(gogo, switch_val_type, b, descriptor_temp, break_label,
			NULL);
}

// Return true if these clauses may fall through to the statements
// following the switch statement.

bool
Type_case_clauses::may_fall_through() const
{
  bool found_default = false;
  for (Type_clauses::const_iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    {
      if (p->may_fall_through())
	return true;
      if (p->is_default())
	found_default = true;
    }
  return !found_default;
}

// Dump the AST representation for case clauses (from a switch statement)

void
Type_case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
{
  for (Type_clauses::const_iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    p->dump_clause(ast_dump_context);
}

// Class Type_switch_statement.

// Traversal.

int
Type_switch_statement::do_traverse(Traverse* traverse)
{
  if (this->traverse_expression(traverse, &this->expr_) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  if (this->clauses_ != NULL)
    return this->clauses_->traverse(traverse);
  return TRAVERSE_CONTINUE;
}

// Lower a type switch statement to a series of if statements.  The gc
// compiler is able to generate a table in some cases.  However, that
// does not work for us because we may have type descriptors in
// different shared libraries, so we can't compare them with simple
// equality testing.

Statement*
Type_switch_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
				Statement_inserter*)
{
  const Location loc = this->location();

  if (this->clauses_ != NULL)
    this->clauses_->check_duplicates();

  Block* b = new Block(enclosing, loc);

  Type* val_type = this->expr_->type();
  if (val_type->interface_type() == NULL)
    {
      if (!val_type->is_error())
	this->report_error(_("cannot type switch on non-interface value"));
      return Statement::make_error_statement(loc);
    }

  Temporary_statement* val_temp =
    Statement::make_temporary(NULL, this->expr_, loc);
  b->add_statement(val_temp);

  // var descriptor_temp DESCRIPTOR_TYPE
  Type* descriptor_type = Type::make_type_descriptor_ptr_type();
  Temporary_statement* descriptor_temp =
    Statement::make_temporary(descriptor_type, NULL, loc);
  b->add_statement(descriptor_temp);

  // descriptor_temp = ifacetype(val_temp)
  Expression* ref = Expression::make_temporary_reference(val_temp, loc);
  Expression* td = Expression::get_interface_type_descriptor(ref);
  Temporary_reference_expression* lhs =
    Expression::make_temporary_reference(descriptor_temp, loc);
  lhs->set_is_lvalue();
  Statement* s = Statement::make_assignment(lhs, td, loc);
  b->add_statement(s);

  if (this->clauses_ != NULL)
    this->clauses_->lower(gogo, val_type, b, descriptor_temp, this->break_label());

  s = Statement::make_unnamed_label_statement(this->break_label_);
  b->add_statement(s);

  return Statement::make_block_statement(b, loc);
}

// Return whether this switch may fall through.

bool
Type_switch_statement::do_may_fall_through() const
{
  if (this->clauses_ == NULL)
    return true;

  // If we have a break label, then some case needed it.  That implies
  // that the switch statement as a whole can fall through.
  if (this->break_label_ != NULL)
    return true;

  return this->clauses_->may_fall_through();
}

// Return the break label for this type switch statement, creating it
// if necessary.

Unnamed_label*
Type_switch_statement::break_label()
{
  if (this->break_label_ == NULL)
    this->break_label_ = new Unnamed_label(this->location());
  return this->break_label_;
}

// Dump the AST representation for a type switch statement

void
Type_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    const
{
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << "switch ";
  if (!this->name_.empty())
    ast_dump_context->ostream() << this->name_ << " = ";
  ast_dump_context->dump_expression(this->expr_);
  ast_dump_context->ostream() << " .(type)";
  if (ast_dump_context->dump_subblocks())
    {
      ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
      this->clauses_->dump_clauses(ast_dump_context);
      ast_dump_context->ostream() << "}";
    }
  ast_dump_context->ostream() << std::endl;
}

// Make a type switch statement.

Type_switch_statement*
Statement::make_type_switch_statement(const std::string& name, Expression* expr,
				      Location location)
{
  return new Type_switch_statement(name, expr, location);
}

// Class Send_statement.

// Traversal.

int
Send_statement::do_traverse(Traverse* traverse)
{
  if (this->traverse_expression(traverse, &this->channel_) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return this->traverse_expression(traverse, &this->val_);
}

// Determine types.

void
Send_statement::do_determine_types()
{
  this->channel_->determine_type_no_context();
  Type* type = this->channel_->type();
  Type_context context;
  if (type->channel_type() != NULL)
    context.type = type->channel_type()->element_type();
  this->val_->determine_type(&context);
}

// Check types.

void
Send_statement::do_check_types(Gogo*)
{
  Type* type = this->channel_->type();
  if (type->is_error())
    {
      this->set_is_error();
      return;
    }
  Channel_type* channel_type = type->channel_type();
  if (channel_type == NULL)
    {
      go_error_at(this->location(), "left operand of %<<-%> must be channel");
      this->set_is_error();
      return;
    }
  Type* element_type = channel_type->element_type();
  if (!Type::are_assignable(element_type, this->val_->type(), NULL))
    {
      this->report_error(_("incompatible types in send"));
      return;
    }
  if (!channel_type->may_send())
    {
      this->report_error(_("invalid send on receive-only channel"));
      return;
    }
}

// Flatten a send statement.  We may need a temporary for interface
// conversion.

Statement*
Send_statement::do_flatten(Gogo*, Named_object*, Block*,
			   Statement_inserter* inserter)
{
  if (this->channel_->is_error_expression()
      || this->channel_->type()->is_error_type())
    {
      go_assert(saw_errors());
      return Statement::make_error_statement(this->location());
    }

  Type* element_type = this->channel_->type()->channel_type()->element_type();
  if (!Type::are_identical(element_type, this->val_->type(),
			   Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
			   NULL)
      && this->val_->type()->interface_type() != NULL
      && !this->val_->is_variable())
    {
      Temporary_statement* temp =
	Statement::make_temporary(NULL, this->val_, this->location());
      inserter->insert(temp);
      this->val_ = Expression::make_temporary_reference(temp,
							this->location());
    }
  return this;
}

// Add explicit type conversions.

void
Send_statement::do_add_conversions()
{
  Type* lt = this->channel_->type()->channel_type()->element_type();
  Type* rt = this->val_->type();
  if (!Type::are_identical(lt, rt, 0, NULL)
      && lt->interface_type() != NULL)
    this->val_ = Expression::make_cast(lt, this->val_, this->location());
}

// Convert a send statement to the backend representation.

Bstatement*
Send_statement::do_get_backend(Translate_context* context)
{
  Location loc = this->location();

  Channel_type* channel_type = this->channel_->type()->channel_type();
  Type* element_type = channel_type->element_type();
  Expression* val = Expression::convert_for_assignment(context->gogo(),
						       element_type,
						       this->val_, loc);

  bool can_take_address;
  switch (element_type->base()->classification())
    {
    case Type::TYPE_BOOLEAN:
    case Type::TYPE_INTEGER:
    case Type::TYPE_FUNCTION:
    case Type::TYPE_POINTER:
    case Type::TYPE_MAP:
    case Type::TYPE_CHANNEL:
    case Type::TYPE_FLOAT:
    case Type::TYPE_COMPLEX:
    case Type::TYPE_STRING:
    case Type::TYPE_INTERFACE:
      can_take_address = false;
      break;

    case Type::TYPE_STRUCT:
      can_take_address = true;
      break;

    case Type::TYPE_ARRAY:
      can_take_address = !element_type->is_slice_type();
      break;

    default:
    case Type::TYPE_ERROR:
    case Type::TYPE_VOID:
    case Type::TYPE_SINK:
    case Type::TYPE_NIL:
    case Type::TYPE_NAMED:
    case Type::TYPE_FORWARD:
      go_assert(saw_errors());
      return context->backend()->error_statement();
    }

  // Only try to take the address of a variable.  We have already
  // moved variables to the heap, so this should not cause that to
  // happen unnecessarily.
  if (can_take_address
      && val->var_expression() == NULL
      && val->temporary_reference_expression() == NULL)
    can_take_address = false;

  Bstatement* btemp = NULL;
  if (can_take_address)
    {
      // The function doesn't change the value, so just take its
      // address directly.
      val = Expression::make_unary(OPERATOR_AND, val, loc);
    }
  else
    {
      // The value is not in a variable, or is small enough that it
      // might be in a register, and taking the address would push it
      // on the stack.  Copy it into a temporary variable to take the
      // address.
      Temporary_statement* temp = Statement::make_temporary(element_type,
							    val, loc);
      Expression* ref = Expression::make_temporary_reference(temp, loc);
      val = Expression::make_unary(OPERATOR_AND, ref, loc);
      btemp = temp->get_backend(context);
    }

  Expression* call = Runtime::make_call(Runtime::CHANSEND, loc, 2,
					this->channel_, val);

  context->gogo()->lower_expression(context->function(), NULL, &call);
  Bexpression* bcall = call->get_backend(context);
  Bfunction* bfunction = context->function()->func_value()->get_decl();
  Bstatement* s = context->backend()->expression_statement(bfunction, bcall);

  if (btemp == NULL)
    return s;
  else
    return context->backend()->compound_statement(btemp, s);
}

// Dump the AST representation for a send statement

void
Send_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->dump_expression(this->channel_);
  ast_dump_context->ostream() << " <- ";
  ast_dump_context->dump_expression(this->val_);
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make a send statement.

Send_statement*
Statement::make_send_statement(Expression* channel, Expression* val,
			       Location location)
{
  return new Send_statement(channel, val, location);
}

// Class Select_clauses::Select_clause.

// Traversal.

int
Select_clauses::Select_clause::traverse(Traverse* traverse)
{
  if (!this->is_lowered_
      && (traverse->traverse_mask()
	  & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
    {
      if (this->channel_ != NULL)
	{
	  if (Expression::traverse(&this->channel_, traverse) == TRAVERSE_EXIT)
	    return TRAVERSE_EXIT;
	}
      if (this->val_ != NULL)
	{
	  if (Expression::traverse(&this->val_, traverse) == TRAVERSE_EXIT)
	    return TRAVERSE_EXIT;
	}
      if (this->closed_ != NULL)
	{
	  if (Expression::traverse(&this->closed_, traverse) == TRAVERSE_EXIT)
	    return TRAVERSE_EXIT;
	}
    }
  if (this->statements_ != NULL)
    {
      if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  return TRAVERSE_CONTINUE;
}

// Lowering.  We call a function to register this clause, and arrange
// to set any variables in any receive clause.

void
Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
				     Block* b, Temporary_statement* scases,
				     size_t index, Temporary_statement* recvok)
{
  Location loc = this->location_;

  Expression* scase = Expression::make_temporary_reference(scases, loc);
  Expression* index_expr = Expression::make_integer_ul(index, NULL, loc);
  scase = Expression::make_array_index(scase, index_expr, NULL, NULL, loc);

  if (this->is_default_)
    {
      go_assert(this->channel_ == NULL && this->val_ == NULL);
      this->lower_default(b, scase);
      this->is_lowered_ = true;
      return;
    }

  // Evaluate the channel before the select statement.
  Temporary_statement* channel_temp = Statement::make_temporary(NULL,
								this->channel_,
								loc);
  b->add_statement(channel_temp);
  Expression* chanref = Expression::make_temporary_reference(channel_temp,
							     loc);

  if (this->is_send_)
    this->lower_send(b, scase, chanref);
  else
    this->lower_recv(gogo, function, b, scase, chanref, recvok);

  // Now all references should be handled through the statements, not
  // through here.
  this->is_lowered_ = true;
  this->val_ = NULL;
}

// Lower a default clause in a select statement.

void
Select_clauses::Select_clause::lower_default(Block* b, Expression* scase)
{
  Location loc = this->location_;
  this->set_case(b, scase, Expression::make_nil(loc), NULL, caseDefault);
}

// Lower a send clause in a select statement.

void
Select_clauses::Select_clause::lower_send(Block* b, Expression* scase,
					  Expression* chanref)
{
  Location loc = this->location_;

  Channel_type* ct = this->channel_->type()->channel_type();
  if (ct == NULL)
    return;

  Type* valtype = ct->element_type();

  // Note that copying the value to a temporary here means that we
  // evaluate the send values in the required order.
  Temporary_statement* val = Statement::make_temporary(valtype, this->val_,
						       loc);
  // The value here escapes, because it might be sent on a channel.
  // We record that via the Temporary_statement, so that the escape
  // analysis pass can pick it up.  The gc compiler lowers select
  // statements after escape analysis, so it doesn't have to worry
  // about this.
  val->set_value_escapes();
  b->add_statement(val);

  Expression* valref = Expression::make_temporary_reference(val, loc);
  Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
  Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
  valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);

  this->set_case(b, scase, chanref, valaddr, caseSend);
}

// Lower a receive clause in a select statement.

void
Select_clauses::Select_clause::lower_recv(Gogo* gogo, Named_object* function,
					  Block* b, Expression* scase,
					  Expression* chanref,
					  Temporary_statement* recvok)
{
  Location loc = this->location_;

  Channel_type* ct = this->channel_->type()->channel_type();
  if (ct == NULL)
    return;

  Type* valtype = ct->element_type();
  Temporary_statement* val = Statement::make_temporary(valtype, NULL, loc);
  b->add_statement(val);

  Expression* valref = Expression::make_temporary_reference(val, loc);
  Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
  Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
  valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);

  this->set_case(b, scase, chanref, valaddr, caseRecv);

  // If the block of statements is executed, arrange for the received
  // value to move from VAL to the place where the statements expect
  // it.

  Block* init = NULL;

  if (this->var_ != NULL)
    {
      go_assert(this->val_ == NULL);
      valref = Expression::make_temporary_reference(val, loc);
      this->var_->var_value()->set_init(valref);
      this->var_->var_value()->clear_type_from_chan_element();
    }
  else if (this->val_ != NULL && !this->val_->is_sink_expression())
    {
      init = new Block(b, loc);
      valref = Expression::make_temporary_reference(val, loc);
      init->add_statement(Statement::make_assignment(this->val_, valref, loc));
    }

  if (this->closedvar_ != NULL)
    {
      go_assert(this->closed_ == NULL);
      Expression* cref = Expression::make_temporary_reference(recvok, loc);
      this->closedvar_->var_value()->set_init(cref);
    }
  else if (this->closed_ != NULL && !this->closed_->is_sink_expression())
    {
      if (init == NULL)
	init = new Block(b, loc);
      Expression* cref = Expression::make_temporary_reference(recvok, loc);
      init->add_statement(Statement::make_assignment(this->closed_, cref,
						     loc));
    }

  if (init != NULL)
    {
      gogo->lower_block(function, init);

      if (this->statements_ != NULL)
	init->add_statement(Statement::make_block_statement(this->statements_,
							    loc));
      this->statements_ = init;
    }
}

// Set the fields of an scase struct, an element in the array that we
// pass to the runtime function selectgo.

void
Select_clauses::Select_clause::set_case(Block* b,
					Expression* scase,
					Expression* chanref,
					Expression* elem,
					int kind)
{
  Location loc = this->location_;
  Struct_type* scase_type = scase->type()->struct_type();

  int field_index = 0;
  go_assert(scase_type->field(field_index)->is_field_name("c"));
  Expression* ref = Expression::make_field_reference(scase, field_index, loc);
  Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
  chanref = Expression::make_unsafe_cast(unsafe_pointer_type, chanref, loc);
  Statement* s = Statement::make_assignment(ref, chanref, loc);
  b->add_statement(s);

  if (elem != NULL)
    {
      field_index = 1;
      go_assert(scase_type->field(field_index)->is_field_name("elem"));
      ref = Expression::make_field_reference(scase->copy(), field_index, loc);
      s = Statement::make_assignment(ref, elem, loc);
      b->add_statement(s);
    }

  field_index = 2;
  go_assert(scase_type->field(field_index)->is_field_name("kind"));
  Type* uint16_type = Type::lookup_integer_type("uint16");
  Expression* k = Expression::make_integer_ul(kind, uint16_type, loc);
  ref = Expression::make_field_reference(scase->copy(), field_index, loc);
  s = Statement::make_assignment(ref, k, loc);
  b->add_statement(s);
}

// Determine types.

void
Select_clauses::Select_clause::determine_types()
{
  go_assert(this->is_lowered_);
  if (this->statements_ != NULL)
    this->statements_->determine_types();
}

// Check types.

void
Select_clauses::Select_clause::check_types()
{
  if (this->is_default_)
    return;

  Channel_type* ct = this->channel_->type()->channel_type();
  if (ct == NULL)
    {
      go_error_at(this->channel_->location(), "expected channel");
      return;
    }

  if (this->is_send_ && !ct->may_send())
    go_error_at(this->location(), "invalid send on receive-only channel");
  else if (!this->is_send_ && !ct->may_receive())
    go_error_at(this->location(), "invalid receive on send-only channel");
}

// Whether this clause may fall through to the statement which follows
// the overall select statement.

bool
Select_clauses::Select_clause::may_fall_through() const
{
  if (this->statements_ == NULL)
    return true;
  return this->statements_->may_fall_through();
}

// Return the backend representation for the statements to execute.

Bstatement*
Select_clauses::Select_clause::get_statements_backend(
    Translate_context* context)
{
  if (this->statements_ == NULL)
    return NULL;
  Bblock* bblock = this->statements_->get_backend(context);
  return context->backend()->block_statement(bblock);
}

// Dump the AST representation for a select case clause

void
Select_clauses::Select_clause::dump_clause(
    Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  if (this->is_default_)
    {
      ast_dump_context->ostream() << "default:";
    }
  else
    {
      ast_dump_context->ostream() << "case "  ;
      if (this->is_send_)
        {
          ast_dump_context->dump_expression(this->channel_);
          ast_dump_context->ostream() << " <- " ;
	  if (this->val_ != NULL)
	    ast_dump_context->dump_expression(this->val_);
        }
      else
        {
	  if (this->val_ != NULL)
	    ast_dump_context->dump_expression(this->val_);
          if (this->closed_ != NULL)
            {
	      // FIXME: can val_ == NULL and closed_ ! = NULL?
              ast_dump_context->ostream() << " , " ;
              ast_dump_context->dump_expression(this->closed_);
            }
          if (this->closedvar_ != NULL || this->var_ != NULL)
            ast_dump_context->ostream() << " := " ;

          ast_dump_context->ostream() << " <- " ;
          ast_dump_context->dump_expression(this->channel_);
        }
      ast_dump_context->ostream() << ":" ;
    }
  ast_dump_context->dump_block(this->statements_);
}

// Class Select_clauses.

// Traversal.

int
Select_clauses::traverse(Traverse* traverse)
{
  for (Clauses::iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    {
      if (p->traverse(traverse) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  return TRAVERSE_CONTINUE;
}

// Lowering.  Here we pull out the channel and the send values, to
// enforce the order of evaluation.  We also add explicit send and
// receive statements to the clauses.

void
Select_clauses::lower(Gogo* gogo, Named_object* function, Block* b,
		      Temporary_statement* scases, Temporary_statement* recvok)
{
  size_t i = 0;
  for (Clauses::iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p, ++i)
    p->lower(gogo, function, b, scases, i, recvok);
}

// Determine types.

void
Select_clauses::determine_types()
{
  for (Clauses::iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    p->determine_types();
}

// Check types.

void
Select_clauses::check_types()
{
  for (Clauses::iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    p->check_types();
}

// Return whether these select clauses fall through to the statement
// following the overall select statement.

bool
Select_clauses::may_fall_through() const
{
  for (Clauses::const_iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    if (p->may_fall_through())
      return true;
  return false;
}

// Convert to the backend representation.  Assemble the clauses and
// build a switch statement on the index value returned by the call to
// selectgo.

Bstatement*
Select_clauses::get_backend(Translate_context* context,
			    Temporary_statement* index,
			    Unnamed_label *break_label,
			    Location location)
{
  size_t count = this->clauses_.size();
  std::vector<std::vector<Bexpression*> > cases(count + 1);
  std::vector<Bstatement*> clauses(count + 1);

  Type* int_type = Type::lookup_integer_type("int");

  int i = 0;
  for (Clauses::iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p, ++i)
    {
      Expression* index_expr = Expression::make_integer_ul(i, int_type,
							   location);
      cases[i].push_back(index_expr->get_backend(context));

      Bstatement* s = p->get_statements_backend(context);
      Location gloc = (p->statements() == NULL
		       ? p->location()
		       : p->statements()->end_location());
      Bstatement* g = break_label->get_goto(context, gloc);

      if (s == NULL)
	clauses[i] = g;
      else
        clauses[i] = context->backend()->compound_statement(s, g);
    }

  Expression* ref = Expression::make_temporary_reference(index, location);
  Bexpression* bindex = ref->get_backend(context);

  Bfunction* bfunction = context->function()->func_value()->get_decl();

  if (count == 0)
    return context->backend()->expression_statement(bfunction, bindex);

  Expression* crash = Runtime::make_call(Runtime::UNREACHABLE, location, 0);
  Bexpression* bcrash = crash->get_backend(context);
  clauses[count] = context->backend()->expression_statement(bfunction, bcrash);

  std::vector<Bstatement*> statements;
  statements.reserve(2);

  Bstatement* switch_stmt = context->backend()->switch_statement(bfunction,
								 bindex,
								 cases,
								 clauses,
								 location);
  statements.push_back(switch_stmt);

  Bstatement* ldef = break_label->get_definition(context);
  statements.push_back(ldef);

  return context->backend()->statement_list(statements);
}

// Dump the AST representation for select clauses.

void
Select_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
{
  for (Clauses::const_iterator p = this->clauses_.begin();
       p != this->clauses_.end();
       ++p)
    p->dump_clause(ast_dump_context);
}

// Class Select_statement.

// Return the break label for this switch statement, creating it if
// necessary.

Unnamed_label*
Select_statement::break_label()
{
  if (this->break_label_ == NULL)
    this->break_label_ = new Unnamed_label(this->location());
  return this->break_label_;
}

// Lower a select statement.  This will return a block containing this
// select statement.  The block will implement the order of evaluation
// rules, include the send and receive statements as explicit
// statements in the clauses, and call the runtime selectgo function.

Statement*
Select_statement::do_lower(Gogo* gogo, Named_object* function,
			   Block* enclosing, Statement_inserter*)
{
  if (this->is_lowered_)
    return this;

  Location loc = this->location();

  Block* b = new Block(enclosing, loc);

  int ncases = this->clauses_->size();

  // Zero-case select.  Just block the execution.
  if (ncases == 0)
    {
      Expression* call = Runtime::make_call(Runtime::BLOCK, loc, 0);
      Statement *s = Statement::make_statement(call, false);
      b->add_statement(s);
      this->is_lowered_ = true;
      return Statement::make_block_statement(b, loc);
    }

  // One-case select.  It is mostly just to run the case.
  if (ncases == 1)
    return this->lower_one_case(b);

  // Two-case select with one default case.  It is a non-blocking
  // send/receive.
  if (ncases == 2
      && (this->clauses_->at(0).is_default()
          || this->clauses_->at(1).is_default()))
    return this->lower_two_case(b);

  Type* scase_type = Channel_type::select_case_type();
  Expression* ncases_expr =
    Expression::make_integer_ul(ncases, NULL,
				Linemap::predeclared_location());
  Array_type* scases_type = Type::make_array_type(scase_type, ncases_expr);
  scases_type->set_is_array_incomparable();

  Temporary_statement* scases = Statement::make_temporary(scases_type, NULL,
							  loc);
  b->add_statement(scases);

  Expression* ncases2_expr =
    Expression::make_integer_ul(ncases * 2, NULL,
				Linemap::predeclared_location());
  Type* uint16_type = Type::lookup_integer_type("uint16");
  Array_type* order_type = Type::make_array_type(uint16_type, ncases2_expr);
  order_type->set_is_array_incomparable();

  Temporary_statement* order = Statement::make_temporary(order_type, NULL,
							 loc);
  b->add_statement(order);

  Type* int_type = Type::lookup_integer_type("int");
  this->index_ = Statement::make_temporary(int_type, NULL, loc);
  b->add_statement(this->index_);

  Type* bool_type = Type::lookup_bool_type();
  Temporary_statement* recvok = Statement::make_temporary(bool_type, NULL,
							  loc);
  b->add_statement(recvok);

  // Initialize the scases array.
  this->clauses_->lower(gogo, function, b, scases, recvok);

  // Build the call to selectgo.  Later, in do_get_backend, we will
  // build a switch on the result that branches to the various cases.

  Expression* scases_ref = Expression::make_temporary_reference(scases, loc);
  scases_ref = Expression::make_unary(OPERATOR_AND, scases_ref, loc);
  Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
  scases_ref = Expression::make_cast(unsafe_pointer_type, scases_ref, loc);

  Expression* order_ref = Expression::make_temporary_reference(order, loc);
  order_ref = Expression::make_unary(OPERATOR_AND, order_ref, loc);
  order_ref = Expression::make_cast(unsafe_pointer_type, order_ref, loc);

  Expression* count_expr = Expression::make_integer_ul(ncases, int_type, loc);

  Call_expression* call = Runtime::make_call(Runtime::SELECTGO, loc, 3,
					     scases_ref, order_ref,
					     count_expr);

  Expression* result = Expression::make_call_result(call, 0);
  Expression* ref = Expression::make_temporary_reference(this->index_, loc);
  Statement* s = Statement::make_assignment(ref, result, loc);
  b->add_statement(s);

  result = Expression::make_call_result(call, 1);
  ref = Expression::make_temporary_reference(recvok, loc);
  s = Statement::make_assignment(ref, result, loc);
  b->add_statement(s);

  this->is_lowered_ = true;
  b->add_statement(this);

  return Statement::make_block_statement(b, loc);
}

// Lower a one-case select statement.

Statement*
Select_statement::lower_one_case(Block* b)
{
  Select_clauses::Select_clause& scase = this->clauses_->at(0);
  Location loc = this->location();
  Expression* chan = scase.channel();
  if (chan != NULL)
    {
      // Lower this to
      //   if chan == nil { block() }; send/recv; body
      Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc);
      b->add_statement(chantmp);
      Expression* chanref = Expression::make_temporary_reference(chantmp, loc);

      Expression* nil = Expression::make_nil(loc);
      Expression* cond = Expression::make_binary(OPERATOR_EQEQ, chanref, nil, loc);
      Block* bnil = new Block(b, loc);
      Expression* call = Runtime::make_call(Runtime::BLOCK, loc, 0);
      Statement* s = Statement::make_statement(call, false);
      bnil->add_statement(s);
      Statement* ifs = Statement::make_if_statement(cond, bnil, NULL, loc);
      b->add_statement(ifs);

      chanref = chanref->copy();
      Location cloc = scase.location();
      if (scase.is_send())
        {
          s = Statement::make_send_statement(chanref, scase.val(), cloc);
          b->add_statement(s);
        }
      else
        {
          if (scase.closed() == NULL && scase.closedvar() == NULL)
            {
              // Simple receive.
              Expression* recv = Expression::make_receive(chanref, cloc);
              if (scase.val() != NULL)
                s = Statement::make_assignment(scase.val(), recv, cloc);
              else if (scase.var() != NULL)
                {
                  Temporary_statement *ts =
                    Statement::make_temporary(NULL, recv, cloc);
                  Expression* ref =
                    Expression::make_temporary_reference(ts, cloc);
                  s = ts;
                  scase.var()->var_value()->set_init(ref);
                  scase.var()->var_value()->clear_type_from_chan_element();
                }
              else
                s = Statement::make_statement(recv, false);
              b->add_statement(s);
            }
          else
            {
              // Tuple receive.
              Expression* lhs;
              if (scase.val() != NULL)
                lhs = scase.val();
              else
                {
                  Type* valtype = chan->type()->channel_type()->element_type();
                  Temporary_statement *ts =
                    Statement::make_temporary(valtype, NULL, cloc);
                  lhs = Expression::make_temporary_reference(ts, cloc);
                  b->add_statement(ts);
                }

              Expression* lhs2;
              if (scase.closed() != NULL)
                lhs2 = scase.closed();
              else
                {
                  Type* booltype = Type::make_boolean_type();
                  Temporary_statement *ts =
                    Statement::make_temporary(booltype, NULL, cloc);
                  lhs2 = Expression::make_temporary_reference(ts, cloc);
                  b->add_statement(ts);
                }

              s = Statement::make_tuple_receive_assignment(lhs, lhs2, chanref, cloc);
              b->add_statement(s);

              if (scase.var() != NULL)
                {
                  scase.var()->var_value()->set_init(lhs->copy());
                  scase.var()->var_value()->clear_type_from_chan_element();
                }

              if (scase.closedvar() != NULL)
                scase.closedvar()->var_value()->set_init(lhs2->copy());
            }
        }
    }

  Statement* bs =
    Statement::make_block_statement(scase.statements(), scase.location());
  b->add_statement(bs);

  Statement* label =
    Statement::make_unnamed_label_statement(this->break_label());
  b->add_statement(label);

  this->is_lowered_ = true;
  return Statement::make_block_statement(b, loc);
}

// Lower a two-case select statement with one default case.

Statement*
Select_statement::lower_two_case(Block* b)
{
  Select_clauses::Select_clause& chancase =
    (this->clauses_->at(0).is_default()
     ? this->clauses_->at(1)
     : this->clauses_->at(0));
  Select_clauses::Select_clause& defcase =
    (this->clauses_->at(0).is_default()
     ? this->clauses_->at(0)
     : this->clauses_->at(1));
  Location loc = this->location();
  Expression* chan = chancase.channel();
  Type* valtype = chan->type()->channel_type()->element_type();

  Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc);
  b->add_statement(chantmp);
  Expression* chanref = Expression::make_temporary_reference(chantmp, loc);

  Block* bchan;
  Expression* call;
  if (chancase.is_send())
    {
      // if selectnbsend(chan, &val) { body } else { default body }

      Temporary_statement* ts =
        Statement::make_temporary(valtype, chancase.val(), loc);
      // Tell the escape analysis that the value escapes, as it may be sent
      // to a channel.
      ts->set_value_escapes();
      b->add_statement(ts);

      Expression* ref = Expression::make_temporary_reference(ts, loc);
      Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
      call = Runtime::make_call(Runtime::SELECTNBSEND, loc, 2, chanref, addr);
      bchan = chancase.statements();
    }
  else
    {
      Temporary_statement* ts = Statement::make_temporary(valtype, NULL, loc);
      b->add_statement(ts);

      Expression* ref = Expression::make_temporary_reference(ts, loc);
      Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
      Expression* okref = NULL;
      if (chancase.closed() == NULL && chancase.closedvar() == NULL)
        {
          // Simple receive.
          // if selectnbrecv(&lhs, chan) { body } else { default body }
          call = Runtime::make_call(Runtime::SELECTNBRECV, loc, 2, addr, chanref);
        }
      else
        {
          // Tuple receive.
          // if selectnbrecv2(&lhs, &ok, chan) { body } else { default body }

          Type* booltype = Type::make_boolean_type();
          Temporary_statement* okts = Statement::make_temporary(booltype, NULL,
                                                                loc);
          b->add_statement(okts);

          okref = Expression::make_temporary_reference(okts, loc);
          Expression* okaddr = Expression::make_unary(OPERATOR_AND, okref, loc);
          call = Runtime::make_call(Runtime::SELECTNBRECV2, loc, 3, addr, okaddr,
                                    chanref);
        }

      Location cloc = chancase.location();
      bchan = new Block(b, loc);
      if (chancase.val() != NULL && !chancase.val()->is_sink_expression())
        {
          Statement* as = Statement::make_assignment(chancase.val(), ref->copy(),
                                                     cloc);
          bchan->add_statement(as);
        }
      else if (chancase.var() != NULL)
        {
          chancase.var()->var_value()->set_init(ref->copy());
          chancase.var()->var_value()->clear_type_from_chan_element();
        }

      if (chancase.closed() != NULL && !chancase.closed()->is_sink_expression())
        {
          Statement* as = Statement::make_assignment(chancase.closed(),
                                                     okref->copy(), cloc);
          bchan->add_statement(as);
        }
      else if (chancase.closedvar() != NULL)
        chancase.closedvar()->var_value()->set_init(okref->copy());

      Statement* bs = Statement::make_block_statement(chancase.statements(),
                                                      cloc);
      bchan->add_statement(bs);
    }

  Statement* ifs =
    Statement::make_if_statement(call, bchan, defcase.statements(), loc);
  b->add_statement(ifs);

  Statement* label =
    Statement::make_unnamed_label_statement(this->break_label());
  b->add_statement(label);

  this->is_lowered_ = true;
  return Statement::make_block_statement(b, loc);
}

// Whether the select statement itself may fall through to the following
// statement.

bool
Select_statement::do_may_fall_through() const
{
  // A select statement is terminating if no break statement
  // refers to it and all of its clauses are terminating.
  if (this->break_label_ != NULL)
    return true;
  return this->clauses_->may_fall_through();
}

// Return the backend representation for a select statement.

Bstatement*
Select_statement::do_get_backend(Translate_context* context)
{
  return this->clauses_->get_backend(context, this->index_,
				     this->break_label(), this->location());
}

// Dump the AST representation for a select statement.

void
Select_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << "select";
  if (ast_dump_context->dump_subblocks())
    {
      ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
      this->clauses_->dump_clauses(ast_dump_context);
      ast_dump_context->print_indent();
      ast_dump_context->ostream() << "}";
    }
  ast_dump_context->ostream() << std::endl;
}

// Make a select statement.

Select_statement*
Statement::make_select_statement(Location location)
{
  return new Select_statement(location);
}

// Class For_statement.

// Traversal.

int
For_statement::do_traverse(Traverse* traverse)
{
  if (this->init_ != NULL)
    {
      if (this->init_->traverse(traverse) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  if (this->cond_ != NULL)
    {
      if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  if (this->post_ != NULL)
    {
      if (this->post_->traverse(traverse) == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  return this->statements_->traverse(traverse);
}

// Lower a For_statement into if statements and gotos.  Getting rid of
// complex statements make it easier to handle garbage collection.

Statement*
For_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
			Statement_inserter*)
{
  Statement* s;
  Location loc = this->location();

  Block* b = new Block(enclosing, this->location());
  if (this->init_ != NULL)
    {
      s = Statement::make_block_statement(this->init_,
					  this->init_->start_location());
      b->add_statement(s);
    }

  Unnamed_label* entry = NULL;
  if (this->cond_ != NULL)
    {
      entry = new Unnamed_label(this->location());
      b->add_statement(Statement::make_goto_unnamed_statement(entry, loc));
    }

  Unnamed_label* top = new Unnamed_label(this->location());
  top->set_derived_from(this);
  b->add_statement(Statement::make_unnamed_label_statement(top));

  s = Statement::make_block_statement(this->statements_,
				      this->statements_->start_location());
  b->add_statement(s);

  Location end_loc = this->statements_->end_location();

  Unnamed_label* cont = this->continue_label_;
  if (cont != NULL)
    b->add_statement(Statement::make_unnamed_label_statement(cont));

  if (this->post_ != NULL)
    {
      s = Statement::make_block_statement(this->post_,
					  this->post_->start_location());
      b->add_statement(s);
      end_loc = this->post_->end_location();
    }

  if (this->cond_ == NULL)
    b->add_statement(Statement::make_goto_unnamed_statement(top, end_loc));
  else
    {
      b->add_statement(Statement::make_unnamed_label_statement(entry));

      Location cond_loc = this->cond_->location();
      Block* then_block = new Block(b, cond_loc);
      s = Statement::make_goto_unnamed_statement(top, cond_loc);
      then_block->add_statement(s);

      s = Statement::make_if_statement(this->cond_, then_block, NULL, cond_loc);
      b->add_statement(s);
    }

  Unnamed_label* brk = this->break_label_;
  if (brk != NULL)
    b->add_statement(Statement::make_unnamed_label_statement(brk));

  b->set_end_location(end_loc);

  Statement* bs = Statement::make_block_statement(b, loc);
  bs->block_statement()->set_is_lowered_for_statement();
  return bs;
}

// Return the break label, creating it if necessary.

Unnamed_label*
For_statement::break_label()
{
  if (this->break_label_ == NULL)
    this->break_label_ = new Unnamed_label(this->location());
  return this->break_label_;
}

// Return the continue LABEL_EXPR.

Unnamed_label*
For_statement::continue_label()
{
  if (this->continue_label_ == NULL)
    this->continue_label_ = new Unnamed_label(this->location());
  return this->continue_label_;
}

// Set the break and continue labels a for statement.  This is used
// when lowering a for range statement.

void
For_statement::set_break_continue_labels(Unnamed_label* break_label,
					 Unnamed_label* continue_label)
{
  go_assert(this->break_label_ == NULL && this->continue_label_ == NULL);
  this->break_label_ = break_label;
  this->continue_label_ = continue_label;
}

// Whether the overall statement may fall through.

bool
For_statement::do_may_fall_through() const
{
  // A for loop is terminating if it has no condition and
  // no break statement.
  if(this->cond_ != NULL)
    return true;
  if(this->break_label_ != NULL)
    return true;
  return false;
}

// Dump the AST representation for a for statement.

void
For_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{
  if (this->init_ != NULL && ast_dump_context->dump_subblocks())
    {
      ast_dump_context->print_indent();
      ast_dump_context->indent();
      ast_dump_context->ostream() << "// INIT  " << std::endl;
      ast_dump_context->dump_block(this->init_);
      ast_dump_context->unindent();
    }
  ast_dump_context->print_indent();
  ast_dump_context->ostream() << "for ";
  if (this->cond_ != NULL)
    ast_dump_context->dump_expression(this->cond_);

  if (ast_dump_context->dump_subblocks())
    {
      ast_dump_context->ostream() << " {" << std::endl;
      ast_dump_context->dump_block(this->statements_);
      if (this->init_ != NULL)
	{
	  ast_dump_context->print_indent();
	  ast_dump_context->ostream() << "// POST " << std::endl;
	  ast_dump_context->dump_block(this->post_);
	}
      ast_dump_context->unindent();

      ast_dump_context->print_indent();
      ast_dump_context->ostream() << "}";
    }

  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make a for statement.

For_statement*
Statement::make_for_statement(Block* init, Expression* cond, Block* post,
			      Location location)
{
  return new For_statement(init, cond, post, location);
}

// Class For_range_statement.

// Traversal.

int
For_range_statement::do_traverse(Traverse* traverse)
{
  if (this->index_var_ != NULL)
    {
      if (this->traverse_expression(traverse, &this->index_var_)
	  == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  if (this->value_var_ != NULL)
    {
      if (this->traverse_expression(traverse, &this->value_var_)
	  == TRAVERSE_EXIT)
	return TRAVERSE_EXIT;
    }
  if (this->traverse_expression(traverse, &this->range_) == TRAVERSE_EXIT)
    return TRAVERSE_EXIT;
  return this->statements_->traverse(traverse);
}

// Lower a for range statement.  For simplicity we lower this into a
// for statement, which will then be lowered in turn to goto
// statements.

Statement*
For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
			      Statement_inserter*)
{
  Type* range_type = this->range_->type();
  if (range_type->points_to() != NULL
      && range_type->points_to()->array_type() != NULL
      && !range_type->points_to()->is_slice_type())
    range_type = range_type->points_to();

  Type* index_type;
  Type* value_type = NULL;
  if (range_type->array_type() != NULL)
    {
      index_type = Type::lookup_integer_type("int");
      value_type = range_type->array_type()->element_type();
    }
  else if (range_type->is_string_type())
    {
      index_type = Type::lookup_integer_type("int");
      value_type = Type::lookup_integer_type("rune");
    }
  else if (range_type->map_type() != NULL)
    {
      index_type = range_type->map_type()->key_type();
      value_type = range_type->map_type()->val_type();
    }
  else if (range_type->channel_type() != NULL)
    {
      index_type = range_type->channel_type()->element_type();
      if (this->value_var_ != NULL)
	{
	  if (!this->value_var_->type()->is_error())
	    this->report_error(_("too many variables for range clause "
				 "with channel"));
	  return Statement::make_error_statement(this->location());
	}
    }
  else
    {
      this->report_error(_("range clause must have "
			   "array, slice, string, map, or channel type"));
      return Statement::make_error_statement(this->location());
    }

  // If there is only one iteration variable, and len(this->range_) is
  // constant, then we do not evaluate the range variable.  len(x) is
  // a contant if x is a string constant or if x is an array.  If x is
  // a constant then evaluating it won't make any difference, so the
  // only case to consider is when x is an array whose length is constant.
  bool eval = true;
  if ((this->value_var_ == NULL || this->value_var_->is_sink_expression())
      && range_type->array_type() != NULL
      && !range_type->is_slice_type()
      && Builtin_call_expression::array_len_is_constant(this->range_))
    eval = false;

  Location loc = this->location();
  Block* temp_block = new Block(enclosing, loc);

  Expression* orig_range_expr = this->range_;
  Named_object* range_object = NULL;
  Temporary_statement* range_temp = NULL;
  if (eval)
    {
      Var_expression* ve = this->range_->var_expression();
      if (ve != NULL)
	range_object = ve->named_object();
      else
	{
	  range_temp = Statement::make_temporary(NULL, this->range_, loc);
	  temp_block->add_statement(range_temp);
	  this->range_ = NULL;
	}
    }

  // Try to match "range clear" patterns and rewrite to simple runtime
  // calls.
  if (range_type->map_type() != NULL)
    {
      Statement* clear = this->lower_map_range_clear(range_type,
                                                     enclosing,
                                                     orig_range_expr,
                                                     range_object,
                                                     range_temp, loc);
      if (clear != NULL)
        {
          if (gogo->debug_optimization())
            go_debug(loc, "map range clear");
          temp_block->add_statement(clear);
          return Statement::make_block_statement(temp_block, loc);
        }
    }
  else if (range_type->array_type() != NULL)
    {
      // Slice or array.
      Statement* clear = this->lower_array_range_clear(gogo,
                                                       range_type,
                                                       orig_range_expr,
                                                       temp_block,
                                                       range_object,
                                                       range_temp, loc);
      if (clear != NULL)
        {
          if (gogo->debug_optimization())
            go_debug(loc, "array range clear");
          temp_block->add_statement(clear);
          return Statement::make_block_statement(temp_block, loc);
        }
    }

  Temporary_statement* index_temp = Statement::make_temporary(index_type,
							      NULL, loc);
  temp_block->add_statement(index_temp);

  Temporary_statement* value_temp = NULL;
  if (this->value_var_ != NULL && !this->value_var_->is_sink_expression())
    {
      value_temp = Statement::make_temporary(value_type, NULL, loc);
      temp_block->add_statement(value_temp);
    }

  Block* body = new Block(temp_block, loc);

  Block* init;
  Expression* cond;
  Block* iter_init;
  Block* post;

  // Arrange to do a loop appropriate for the type.  We will produce
  //   for INIT ; COND ; POST {
  //           ITER_INIT
  //           INDEX = INDEX_TEMP
  //           VALUE = VALUE_TEMP // If there is a value
  //           original statements
  //   }

  if (range_type->is_slice_type())
    this->lower_range_slice(gogo, temp_block, body, range_object, range_temp,
			    index_temp, value_temp, &init, &cond, &iter_init,
			    &post);
  else if (range_type->array_type() != NULL)
    this->lower_range_array(gogo, temp_block, body, range_object, range_temp,
			    index_temp, value_temp, &init, &cond, &iter_init,
			    &post);
  else if (range_type->is_string_type())
    this->lower_range_string(gogo, temp_block, body, range_object, range_temp,
			     index_temp, value_temp, &init, &cond, &iter_init,
			     &post);
  else if (range_type->map_type() != NULL)
    this->lower_range_map(gogo, range_type->map_type(), temp_block, body,
			  range_object, range_temp, index_temp, value_temp,
			  &init, &cond, &iter_init, &post);
  else if (range_type->channel_type() != NULL)
    this->lower_range_channel(gogo, temp_block, body, range_object, range_temp,
			      index_temp, value_temp, &init, &cond, &iter_init,
			      &post);
  else
    go_unreachable();

  if (iter_init != NULL)
    body->add_statement(Statement::make_block_statement(iter_init, loc));

  if (this->index_var_ != NULL)
    {
      Statement* assign;
      Expression* index_ref =
	Expression::make_temporary_reference(index_temp, loc);
      if (this->value_var_ == NULL || this->value_var_->is_sink_expression())
	assign = Statement::make_assignment(this->index_var_, index_ref, loc);
      else
	{
	  Expression_list* lhs = new Expression_list();
	  lhs->push_back(this->index_var_);
	  lhs->push_back(this->value_var_);

	  Expression_list* rhs = new Expression_list();
	  rhs->push_back(index_ref);
	  rhs->push_back(Expression::make_temporary_reference(value_temp, loc));

	  assign = Statement::make_tuple_assignment(lhs, rhs, loc);
	}
      body->add_statement(assign);
    }

  body->add_statement(Statement::make_block_statement(this->statements_, loc));

  body->set_end_location(this->statements_->end_location());

  For_statement* loop = Statement::make_for_statement(init, cond, post,
						      this->location());
  loop->add_statements(body);
  loop->set_break_continue_labels(this->break_label_, this->continue_label_);

  temp_block->add_statement(loop);

  return Statement::make_block_statement(temp_block, loc);
}

// Return a reference to the range, which may be in RANGE_OBJECT or in
// RANGE_TEMP.

Expression*
For_range_statement::make_range_ref(Named_object* range_object,
				    Temporary_statement* range_temp,
				    Location loc)
{
  if (range_object != NULL)
    return Expression::make_var_reference(range_object, loc);
  else
    return Expression::make_temporary_reference(range_temp, loc);
}

// Return a call to the predeclared function FUNCNAME passing a
// reference to the temporary variable ARG.

Call_expression*
For_range_statement::call_builtin(Gogo* gogo, const char* funcname,
				  Expression* arg,
				  Location loc)
{
  Named_object* no = gogo->lookup_global(funcname);
  go_assert(no != NULL && no->is_function_declaration());
  Expression* func = Expression::make_func_reference(no, NULL, loc);
  Expression_list* params = new Expression_list();
  params->push_back(arg);
  return Expression::make_call(func, params, false, loc);
}

// Lower a for range over an array.

void
For_range_statement::lower_range_array(Gogo* gogo,
				       Block* enclosing,
				       Block* body_block,
				       Named_object* range_object,
				       Temporary_statement* range_temp,
				       Temporary_statement* index_temp,
				       Temporary_statement* value_temp,
				       Block** pinit,
				       Expression** pcond,
				       Block** piter_init,
				       Block** ppost)
{
  Location loc = this->location();

  // The loop we generate:
  //   len_temp := len(range)
  //   range_temp := range
  //   for index_temp = 0; index_temp < len_temp; index_temp++ {
  //           value_temp = range_temp[index_temp]
  //           index = index_temp
  //           value = value_temp
  //           original body
  //   }

  // Set *PINIT to
  //   var len_temp int
  //   len_temp = len(range)
  //   index_temp = 0

  Block* init = new Block(enclosing, loc);

  Expression* len_arg;
  if (range_object == NULL && range_temp == NULL)
    {
      // Don't evaluate this->range_, just get its length.
      len_arg = this->range_;
    }
  else
    {
      Expression* ref = this->make_range_ref(range_object, range_temp, loc);
      range_temp = Statement::make_temporary(NULL, ref, loc);
      init->add_statement(range_temp);
      len_arg = ref;
    }
  Expression* len_call = this->call_builtin(gogo, "len", len_arg, loc);
  Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
							    len_call, loc);
  init->add_statement(len_temp);

  Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);

  Temporary_reference_expression* tref =
    Expression::make_temporary_reference(index_temp, loc);
  tref->set_is_lvalue();
  Statement* s = Statement::make_assignment(tref, zexpr, loc);
  init->add_statement(s);

  *pinit = init;

  // Set *PCOND to
  //   index_temp < len_temp

  Expression* ref = Expression::make_temporary_reference(index_temp, loc);
  Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
  Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);

  *pcond = lt;

  // Set *PITER_INIT to
  //   value_temp = range[index_temp]

  Block* iter_init = NULL;
  if (value_temp != NULL)
    {
      iter_init = new Block(body_block, loc);

      ref = Expression::make_temporary_reference(range_temp, loc);
      ref2 = Expression::make_temporary_reference(index_temp, loc);
      Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);

      tref = Expression::make_temporary_reference(value_temp, loc);
      tref->set_is_lvalue();
      s = Statement::make_assignment(tref, index, loc);

      iter_init->add_statement(s);
    }
  *piter_init = iter_init;

  // Set *PPOST to
  //   index_temp++

  Block* post = new Block(enclosing, loc);
  tref = Expression::make_temporary_reference(index_temp, loc);
  tref->set_is_lvalue();
  s = Statement::make_inc_statement(tref);
  post->add_statement(s);
  *ppost = post;
}

// Lower a for range over a slice.

void
For_range_statement::lower_range_slice(Gogo* gogo,
				       Block* enclosing,
				       Block* body_block,
				       Named_object* range_object,
				       Temporary_statement* range_temp,
				       Temporary_statement* index_temp,
				       Temporary_statement* value_temp,
				       Block** pinit,
				       Expression** pcond,
				       Block** piter_init,
				       Block** ppost)
{
  Location loc = this->location();

  // The loop we generate:
  //   for_temp := range
  //   len_temp := len(for_temp)
  //   for index_temp = 0; index_temp < len_temp; index_temp++ {
  //           value_temp = for_temp[index_temp]
  //           index = index_temp
  //           value = value_temp
  //           original body
  //   }
  //
  // Using for_temp means that we don't need to check bounds when
  // fetching range_temp[index_temp].

  // Set *PINIT to
  //   range_temp := range
  //   var len_temp int
  //   len_temp = len(range_temp)
  //   index_temp = 0

  Block* init = new Block(enclosing, loc);

  Expression* ref = this->make_range_ref(range_object, range_temp, loc);
  Temporary_statement* for_temp = Statement::make_temporary(NULL, ref, loc);
  init->add_statement(for_temp);

  ref = Expression::make_temporary_reference(for_temp, loc);
  Expression* len_call = this->call_builtin(gogo, "len", ref, loc);
  Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
							    len_call, loc);
  init->add_statement(len_temp);

  Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);

  Temporary_reference_expression* tref =
    Expression::make_temporary_reference(index_temp, loc);
  tref->set_is_lvalue();
  Statement* s = Statement::make_assignment(tref, zexpr, loc);
  init->add_statement(s);

  *pinit = init;

  // Set *PCOND to
  //   index_temp < len_temp

  ref = Expression::make_temporary_reference(index_temp, loc);
  Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
  Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);

  *pcond = lt;

  // Set *PITER_INIT to
  //   value_temp = range[index_temp]

  Block* iter_init = NULL;
  if (value_temp != NULL)
    {
      iter_init = new Block(body_block, loc);

      ref = Expression::make_temporary_reference(for_temp, loc);
      ref2 = Expression::make_temporary_reference(index_temp, loc);
      Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);

      tref = Expression::make_temporary_reference(value_temp, loc);
      tref->set_is_lvalue();
      s = Statement::make_assignment(tref, index, loc);

      iter_init->add_statement(s);
    }
  *piter_init = iter_init;

  // Set *PPOST to
  //   index_temp++

  Block* post = new Block(enclosing, loc);
  tref = Expression::make_temporary_reference(index_temp, loc);
  tref->set_is_lvalue();
  s = Statement::make_inc_statement(tref);
  post->add_statement(s);
  *ppost = post;
}

// Lower a for range over a string.

void
For_range_statement::lower_range_string(Gogo* gogo,
					Block* enclosing,
					Block* body_block,
					Named_object* range_object,
					Temporary_statement* range_temp,
					Temporary_statement* index_temp,
					Temporary_statement* value_temp,
					Block** pinit,
					Expression** pcond,
					Block** piter_init,
					Block** ppost)
{
  Location loc = this->location();

  // The loop we generate:
  //   len_temp := len(range)
  //   var next_index_temp int
  //   for index_temp = 0; index_temp < len_temp; index_temp = next_index_temp {
  //           value_temp = rune(range[index_temp])
  //           if value_temp < utf8.RuneSelf {
  //                   next_index_temp = index_temp + 1
  //           } else {
  //                   value_temp, next_index_temp = decoderune(range, index_temp)
  //           }
  //           index = index_temp
  //           value = value_temp
  //           // original body
  //   }

  // Set *PINIT to
  //   len_temp := len(range)
  //   var next_index_temp int
  //   index_temp = 0
  //   var value_temp rune // if value_temp not passed in

  Block* init = new Block(enclosing, loc);

  Expression* ref = this->make_range_ref(range_object, range_temp, loc);
  Call_expression* call = this->call_builtin(gogo, "len", ref, loc);
  Temporary_statement* len_temp =
    Statement::make_temporary(index_temp->type(), call, loc);
  init->add_statement(len_temp);

  Temporary_statement* next_index_temp =
    Statement::make_temporary(index_temp->type(), NULL, loc);
  init->add_statement(next_index_temp);

  Temporary_reference_expression* index_ref =
    Expression::make_temporary_reference(index_temp, loc);
  index_ref->set_is_lvalue();
  Expression* zexpr = Expression::make_integer_ul(0, index_temp->type(), loc);
  Statement* s = Statement::make_assignment(index_ref, zexpr, loc);
  init->add_statement(s);

  Type* rune_type;
  if (value_temp != NULL)
    rune_type = value_temp->type();
  else
    {
      rune_type = Type::lookup_integer_type("rune");
      value_temp = Statement::make_temporary(rune_type, NULL, loc);
      init->add_statement(value_temp);
    }

  *pinit = init;

  // Set *PCOND to
  //   index_temp < len_temp

  index_ref = Expression::make_temporary_reference(index_temp, loc);
  Expression* len_ref =
    Expression::make_temporary_reference(len_temp, loc);
  *pcond = Expression::make_binary(OPERATOR_LT, index_ref, len_ref, loc);

  // Set *PITER_INIT to
  //   value_temp = rune(range[index_temp])
  //   if value_temp < utf8.RuneSelf {
  //           next_index_temp = index_temp + 1
  //   } else {
  //           value_temp, next_index_temp = decoderune(range, index_temp)
  //   }

  Block* iter_init = new Block(body_block, loc);

  ref = this->make_range_ref(range_object, range_temp, loc);
  index_ref = Expression::make_temporary_reference(index_temp, loc);
  ref = Expression::make_string_index(ref, index_ref, NULL, loc);
  ref = Expression::make_cast(rune_type, ref, loc);
  Temporary_reference_expression* value_ref =
    Expression::make_temporary_reference(value_temp, loc);
  value_ref->set_is_lvalue();
  s = Statement::make_assignment(value_ref, ref, loc);
  iter_init->add_statement(s);

  value_ref = Expression::make_temporary_reference(value_temp, loc);
  Expression* rune_self = Expression::make_integer_ul(0x80, rune_type, loc);
  Expression* cond = Expression::make_binary(OPERATOR_LT, value_ref, rune_self,
					     loc);

  Block* then_block = new Block(iter_init, loc);

  Temporary_reference_expression* lhs =
    Expression::make_temporary_reference(next_index_temp, loc);
  lhs->set_is_lvalue();
  index_ref = Expression::make_temporary_reference(index_temp, loc);
  Expression* one = Expression::make_integer_ul(1, index_temp->type(), loc);
  Expression* sum = Expression::make_binary(OPERATOR_PLUS, index_ref, one,
					    loc);
  s = Statement::make_assignment(lhs, sum, loc);
  then_block->add_statement(s);

  Block* else_block = new Block(iter_init, loc);

  ref = this->make_range_ref(range_object, range_temp, loc);
  index_ref = Expression::make_temporary_reference(index_temp, loc);
  call = Runtime::make_call(Runtime::DECODERUNE, loc, 2, ref, index_ref);

  value_ref = Expression::make_temporary_reference(value_temp, loc);
  value_ref->set_is_lvalue();
  Expression* res = Expression::make_call_result(call, 0);
  s = Statement::make_assignment(value_ref, res, loc);
  else_block->add_statement(s);

  lhs = Expression::make_temporary_reference(next_index_temp, loc);
  lhs->set_is_lvalue();
  res = Expression::make_call_result(call, 1);
  s = Statement::make_assignment(lhs, res, loc);
  else_block->add_statement(s);

  s = Statement::make_if_statement(cond, then_block, else_block, loc);
  iter_init->add_statement(s);

  *piter_init = iter_init;

  // Set *PPOST to
  //   index_temp = next_index_temp

  Block* post = new Block(enclosing, loc);

  index_ref = Expression::make_temporary_reference(index_temp, loc);
  index_ref->set_is_lvalue();
  ref = Expression::make_temporary_reference(next_index_temp, loc);
  s = Statement::make_assignment(index_ref, ref, loc);

  post->add_statement(s);
  *ppost = post;
}

// Lower a for range over a map.

void
For_range_statement::lower_range_map(Gogo* gogo,
				     Map_type* map_type,
				     Block* enclosing,
				     Block* body_block,
				     Named_object* range_object,
				     Temporary_statement* range_temp,
				     Temporary_statement* index_temp,
				     Temporary_statement* value_temp,
				     Block** pinit,
				     Expression** pcond,
				     Block** piter_init,
				     Block** ppost)
{
  Location loc = this->location();

  // The runtime uses a struct to handle ranges over a map.  The
  // struct is built by Map_type::hiter_type for a specific map type.

  // The loop we generate:
  //   var hiter map_iteration_struct
  //   for mapiterinit(type, range, &hiter); hiter.key != nil; mapiternext(&hiter) {
  //           index_temp = *hiter.key
  //           value_temp = *hiter.val
  //           index = index_temp
  //           value = value_temp
  //           original body
  //   }

  // Set *PINIT to
  //   var hiter map_iteration_struct
  //   runtime.mapiterinit(type, range, &hiter)

  Block* init = new Block(enclosing, loc);

  Type* map_iteration_type = map_type->hiter_type(gogo);
  Temporary_statement* hiter = Statement::make_temporary(map_iteration_type,
							 NULL, loc);
  init->add_statement(hiter);

  Expression* p1 = Expression::make_type_descriptor(map_type, loc);
  Expression* p2 = this->make_range_ref(range_object, range_temp, loc);
  Expression* ref = Expression::make_temporary_reference(hiter, loc);
  Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
  Expression* call = Runtime::make_call(Runtime::MAPITERINIT, loc, 3,
					p1, p2, p3);
  init->add_statement(Statement::make_statement(call, true));

  *pinit = init;

  // Set *PCOND to
  //   hiter.key != nil

  ref = Expression::make_temporary_reference(hiter, loc);
  ref = Expression::make_field_reference(ref, 0, loc);
  Expression* ne = Expression::make_binary(OPERATOR_NOTEQ, ref,
					   Expression::make_nil(loc),
					   loc);
  *pcond = ne;

  // Set *PITER_INIT to
  //   index_temp = *hiter.key
  //   value_temp = *hiter.val

  Block* iter_init = new Block(body_block, loc);

  Expression* lhs = Expression::make_temporary_reference(index_temp, loc);
  Expression* rhs = Expression::make_temporary_reference(hiter, loc);
  rhs = Expression::make_field_reference(ref, 0, loc);
  rhs = Expression::make_dereference(ref, Expression::NIL_CHECK_NOT_NEEDED,
                                     loc);
  Statement* set = Statement::make_assignment(lhs, rhs, loc);
  iter_init->add_statement(set);

  if (value_temp != NULL)
    {
      lhs = Expression::make_temporary_reference(value_temp, loc);
      rhs = Expression::make_temporary_reference(hiter, loc);
      rhs = Expression::make_field_reference(rhs, 1, loc);
      rhs = Expression::make_dereference(rhs, Expression::NIL_CHECK_NOT_NEEDED,
                                         loc);
      set = Statement::make_assignment(lhs, rhs, loc);
      iter_init->add_statement(set);
    }

  *piter_init = iter_init;

  // Set *PPOST to
  //   mapiternext(&hiter)

  Block* post = new Block(enclosing, loc);

  ref = Expression::make_temporary_reference(hiter, loc);
  p1 = Expression::make_unary(OPERATOR_AND, ref, loc);
  call = Runtime::make_call(Runtime::MAPITERNEXT, loc, 1, p1);
  post->add_statement(Statement::make_statement(call, true));

  *ppost = post;
}

// Lower a for range over a channel.

void
For_range_statement::lower_range_channel(Gogo*,
					 Block*,
					 Block* body_block,
					 Named_object* range_object,
					 Temporary_statement* range_temp,
					 Temporary_statement* index_temp,
					 Temporary_statement* value_temp,
					 Block** pinit,
					 Expression** pcond,
					 Block** piter_init,
					 Block** ppost)
{
  go_assert(value_temp == NULL);

  Location loc = this->location();

  // The loop we generate:
  //   for {
  //           index_temp, ok_temp = <-range
  //           if !ok_temp {
  //                   break
  //           }
  //           index = index_temp
  //           original body
  //   }

  // We have no initialization code, no condition, and no post code.

  *pinit = NULL;
  *pcond = NULL;
  *ppost = NULL;

  // Set *PITER_INIT to
  //   index_temp, ok_temp = <-range
  //   if !ok_temp {
  //           break
  //   }

  Block* iter_init = new Block(body_block, loc);

  Temporary_statement* ok_temp =
    Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
  iter_init->add_statement(ok_temp);

  Expression* cref = this->make_range_ref(range_object, range_temp, loc);
  Temporary_reference_expression* iref =
    Expression::make_temporary_reference(index_temp, loc);
  iref->set_is_lvalue();
  Temporary_reference_expression* oref =
    Expression::make_temporary_reference(ok_temp, loc);
  oref->set_is_lvalue();
  Statement* s = Statement::make_tuple_receive_assignment(iref, oref, cref,
							  loc);
  iter_init->add_statement(s);

  Block* then_block = new Block(iter_init, loc);
  s = Statement::make_break_statement(this->break_label(), loc);
  then_block->add_statement(s);

  oref = Expression::make_temporary_reference(ok_temp, loc);
  Expression* cond = Expression::make_unary(OPERATOR_NOT, oref, loc);
  s = Statement::make_if_statement(cond, then_block, NULL, loc);
  iter_init->add_statement(s);

  *piter_init = iter_init;
}

// Match
//
//   for k := range m { delete(m, k) }
//
// Lower it to runtime.mapclear(TYPE, m) on match, return the statement
// containing the call.  Return NULL otherwise.

Statement*
For_range_statement::lower_map_range_clear(Type* map_type,
                                           Block* enclosing,
                                           Expression* orig_range_expr,
                                           Named_object* range_object,
                                           Temporary_statement* range_temp,
                                           Location loc)
{
  if (this->value_var_ != NULL)
    return NULL;
  if (this->index_var_ == NULL)
    return NULL;

  // Require the loop index be a new variable.  We cannot rewrite
  // if it is used outside of the loop.
  Var_expression* index_ve = this->index_var_->var_expression();
  if (index_ve == NULL)
    return NULL;
  Named_object* index_no = index_ve->named_object();
  if (enclosing->bindings()->lookup_local(index_no->name()) != index_no)
    return NULL;

  // Match the body, a single call statement delete(m, k).
  const std::vector<Statement*>* statements = this->statements_->statements();
  if (statements->size() != 1)
    return NULL;
  Expression_statement* es = statements->at(0)->expression_statement();
  if (es == NULL)
    return NULL;
  Call_expression* call = es->expr()->call_expression();
  if (call == NULL || !call->is_builtin()
      || call->builtin_call_expression()->code()
         != Builtin_call_expression::BUILTIN_DELETE)
    return NULL;
  if (!Expression::is_same_variable(call->args()->at(0), orig_range_expr)
      || !Expression::is_same_variable(call->args()->at(1), this->index_var_))
    return NULL;

  // Everything matches. Rewrite to mapclear(TYPE, MAP).
  Expression* e1 = Expression::make_type_descriptor(map_type, loc);
  Expression* e2 = this->make_range_ref(range_object, range_temp, loc);
  call = Runtime::make_call(Runtime::MAPCLEAR, loc, 2, e1, e2);
  return Statement::make_statement(call, true);
}

// Match
//
//   for i := range a { a[i] = zero }
//
// Lower it to call memclr on match, and return the statement.  Return
// NULL otherwise.

Statement*
For_range_statement::lower_array_range_clear(Gogo* gogo,
                                             Type* array_type,
                                             Expression* orig_range_expr,
                                             Block* temp_block,
                                             Named_object* range_object,
                                             Temporary_statement* range_temp,
                                             Location loc)
{
  if (this->value_var_ != NULL)
    return NULL;
  if (this->index_var_ == NULL)
    return NULL;

  // Match the body, a single assignment statement a[i] = zero.
  const std::vector<Statement*>* statements = this->statements_->statements();
  if (statements->size() != 1)
    return NULL;
  Assignment_statement* as = statements->at(0)->assignment_statement();
  if (as == NULL || !as->rhs()->is_zero_value())
    return NULL;
  if (as->lhs()->type()->interface_type() != NULL
      && as->rhs()->type()->interface_type() == NULL
      && !as->rhs()->type()->is_nil_type())
    // Implicit type conversion may change a zero value to non-zero, like
    // interface{}(0).
    return NULL;
  Array_index_expression* aie = as->lhs()->array_index_expression();
  if (aie == NULL || aie->end() != NULL
      || !Expression::is_same_variable(orig_range_expr, aie->array())
      || !Expression::is_same_variable(this->index_var_, aie->start()))
    return NULL;

  // Everything matches. Rewrite to
  //
  //   if len(a) != 0 {
  //     tmp1 = &a[0]
  //     tmp2 = len(a)*sizeof(elem(a))
  //     memclr{NoHeap,Has}Pointers(tmp1, tmp2)
  //     i = len(a) - 1
  //   }

  Type* elem_type = array_type->array_type()->element_type();
  int64_t elme_sz;
  bool ok = elem_type->backend_type_size(gogo, &elme_sz);
  if (!ok)
    return NULL;

  Block* b = new Block(temp_block, loc);

  Expression* ref;
  if (range_object == NULL && range_temp == NULL)
    // is_same_variable implies no side effect, so it is ok to copy.
    ref = orig_range_expr->copy();
  else
    ref = this->make_range_ref(range_object, range_temp, loc);
  Expression* len = this->call_builtin(gogo, "len", ref, loc);
  Temporary_statement* tslen = Statement::make_temporary(NULL, len, loc);
  temp_block->add_statement(tslen);

  Expression* zero = Expression::make_integer_ul(0, this->index_var_->type(), loc);
  ref = ref->copy();
  Expression* elem = Expression::make_array_index(ref, zero, NULL, NULL, loc);
  elem->array_index_expression()->set_needs_bounds_check(false);
  Expression* e1 = Expression::make_unary(OPERATOR_AND, elem, loc);
  Temporary_statement* ts1 = Statement::make_temporary(NULL, e1, loc);
  b->add_statement(ts1);

  len = Expression::make_temporary_reference(tslen, loc);
  Expression* sz = Expression::make_integer_int64(elme_sz, len->type(), loc);
  Expression* e2 = Expression::make_binary(OPERATOR_MULT, len, sz, loc);
  Temporary_statement* ts2 = Statement::make_temporary(NULL, e2, loc);
  b->add_statement(ts2);

  Expression* ptr_arg = Expression::make_temporary_reference(ts1, loc);
  Expression* sz_arg = Expression::make_temporary_reference(ts2, loc);
  Expression* call;
  if (elem_type->has_pointer())
    call = Runtime::make_call(Runtime::MEMCLRHASPTR, loc, 2, ptr_arg, sz_arg);
  else
    {
      Type* int32_type = Type::lookup_integer_type("int32");
      Expression* zero32 = Expression::make_integer_ul(0, int32_type, loc);
      call = Runtime::make_call(Runtime::BUILTIN_MEMSET, loc, 3, ptr_arg,
                                zero32, sz_arg);
    }
  Statement* cs3 = Statement::make_statement(call, true);
  b->add_statement(cs3);

  len = Expression::make_temporary_reference(tslen, loc);
  Expression* one = Expression::make_integer_ul(1, len->type(), loc);
  Expression* rhs = Expression::make_binary(OPERATOR_MINUS, len, one, loc);
  Expression* lhs = this->index_var_->copy();
  Statement* as4 = Statement::make_assignment(lhs, rhs, loc);
  b->add_statement(as4);

  len = Expression::make_temporary_reference(tslen, loc);
  zero = zero->copy();
  Expression* cond = Expression::make_binary(OPERATOR_NOTEQ, len, zero, loc);
  return Statement::make_if_statement(cond, b, NULL, loc);
}

// Return the break LABEL_EXPR.

Unnamed_label*
For_range_statement::break_label()
{
  if (this->break_label_ == NULL)
    this->break_label_ = new Unnamed_label(this->location());
  return this->break_label_;
}

// Return the continue LABEL_EXPR.

Unnamed_label*
For_range_statement::continue_label()
{
  if (this->continue_label_ == NULL)
    this->continue_label_ = new Unnamed_label(this->location());
  return this->continue_label_;
}

// Dump the AST representation for a for range statement.

void
For_range_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
{

  ast_dump_context->print_indent();
  ast_dump_context->ostream() << "for ";
  ast_dump_context->dump_expression(this->index_var_);
  if (this->value_var_ != NULL)
    {
      ast_dump_context->ostream() << ", ";
      ast_dump_context->dump_expression(this->value_var_);
    }

  ast_dump_context->ostream() << " = range ";
  ast_dump_context->dump_expression(this->range_);
  if (ast_dump_context->dump_subblocks())
    {
      ast_dump_context->ostream() << " {" << std::endl;

      ast_dump_context->indent();

      ast_dump_context->dump_block(this->statements_);

      ast_dump_context->unindent();
      ast_dump_context->print_indent();
      ast_dump_context->ostream() << "}";
    }
  ast_dump_context->ostream() << dsuffix(location()) << std::endl;
}

// Make a for statement with a range clause.

For_range_statement*
Statement::make_for_range_statement(Expression* index_var,
				    Expression* value_var,
				    Expression* range,
				    Location location)
{
  return new For_range_statement(index_var, value_var, range, location);
}
