// 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("{"))
    {
      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 Statement::make_error_statement(loc);
	}
      ifb->set_off(nl + 1);
      ifb->increment_indent();
      Block* block = new Block(ifb->block(), loc);
      bool ok = Block::import_block(block, ifb, loc);
      ifb->decrement_indent();
      if (!ok)
	return Statement::make_error_statement(loc);
      return Statement::make_block_statement(block, loc);
    }
  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);

  Expression* lhs = Expression::import_expression(ifb, loc);
  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);
      Type_context context(type, false);
      init->determine_type(&context);
    }
  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)
	{
	  Type_context context(type, false);
	  init->determine_type(&context);
	}
    }
  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;
    }

  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);

  // ok = 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 = Statement::make_assignment(this->ok_, 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);
}

// 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;
}

// 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)
{
  // We are already indented to the right position.
  char buf[50];
  snprintf(buf, sizeof buf, "{ //%d\n",
	   Linemap::location_to_line(this->block_->start_location()));
  efb->write_c_string(buf);

  this->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();
}

// 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.

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)
    {
      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 = gogo->runtime_error(RUNTIME_ERROR_GO_NIL, location);
      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);
  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);
      Call_expression* 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 = 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);
}

// 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());
}

// 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());
}

// 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);
}

// 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);
}

// 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());
}

// 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(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
	cond = Runtime::make_call((type->interface_type() == NULL
				   ? Runtime::IFACETYPEEQ
				   : 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(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(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(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*, 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);
    }

  // 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) FIXME: This should be
  // inlined.
  bool is_empty = val_type->interface_type()->is_empty();
  Expression* call = Runtime::make_call((is_empty
					 ? Runtime::EFACETYPE
					 : Runtime::IFACETYPE),
					loc, 1, this->expr_);
  Temporary_reference_expression* lhs =
    Expression::make_temporary_reference(descriptor_temp, loc);
  lhs->set_is_lvalue();
  Statement* s = Statement::make_assignment(lhs, call, loc);
  b->add_statement(s);

  if (this->clauses_ != NULL)
    this->clauses_->lower(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();
  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);
}

// 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->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 = gogo->lookup_global("rune")->type_value();
    }
  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_inform(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_inform(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);
      Expression* 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);
      Expression* 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 = gogo->lookup_global("rune")->type_value();
      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* arg1 = Expression::make_temporary_reference(ts1, loc);
  Expression* arg2 = Expression::make_temporary_reference(ts2, loc);
  Runtime::Function code = (elem_type->has_pointer()
                            ? Runtime::MEMCLRHASPTR
                            : Runtime::MEMCLRNOPTR);
  Expression* call = Runtime::make_call(code, loc, 2, arg1, arg2);
  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);
}
