github.com/kidsbmilk/gofrontend_all@v0.0.0-20220701224323-6479d5976c5d/go/statements.cc (about)

     1  // statements.cc -- Go frontend statements.
     2  
     3  // Copyright 2009 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  #include "go-system.h"
     8  
     9  #include "go-c.h"
    10  #include "go-diagnostics.h"
    11  #include "types.h"
    12  #include "expressions.h"
    13  #include "gogo.h"
    14  #include "export.h"
    15  #include "import.h"
    16  #include "runtime.h"
    17  #include "backend.h"
    18  #include "statements.h"
    19  #include "ast-dump.h"
    20  
    21  // Class Statement.
    22  
    23  Statement::Statement(Statement_classification classification,
    24  		     Location location)
    25    : classification_(classification), location_(location)
    26  {
    27  }
    28  
    29  Statement::~Statement()
    30  {
    31  }
    32  
    33  // Traverse the tree.  The work of walking the components is handled
    34  // by the subclasses.
    35  
    36  int
    37  Statement::traverse(Block* block, size_t* pindex, Traverse* traverse)
    38  {
    39    if (this->classification_ == STATEMENT_ERROR)
    40      return TRAVERSE_CONTINUE;
    41  
    42    unsigned int traverse_mask = traverse->traverse_mask();
    43  
    44    if ((traverse_mask & Traverse::traverse_statements) != 0)
    45      {
    46        int t = traverse->statement(block, pindex, this);
    47        if (t == TRAVERSE_EXIT)
    48  	return TRAVERSE_EXIT;
    49        else if (t == TRAVERSE_SKIP_COMPONENTS)
    50  	return TRAVERSE_CONTINUE;
    51      }
    52  
    53    // No point in checking traverse_mask here--a statement may contain
    54    // other blocks or statements, and if we got here we always want to
    55    // walk them.
    56    return this->do_traverse(traverse);
    57  }
    58  
    59  // Traverse the contents of a statement.
    60  
    61  int
    62  Statement::traverse_contents(Traverse* traverse)
    63  {
    64    return this->do_traverse(traverse);
    65  }
    66  
    67  // Traverse assignments.
    68  
    69  bool
    70  Statement::traverse_assignments(Traverse_assignments* tassign)
    71  {
    72    if (this->classification_ == STATEMENT_ERROR)
    73      return false;
    74    return this->do_traverse_assignments(tassign);
    75  }
    76  
    77  // Traverse an expression in a statement.  This is a helper function
    78  // for child classes.
    79  
    80  int
    81  Statement::traverse_expression(Traverse* traverse, Expression** expr)
    82  {
    83    if ((traverse->traverse_mask()
    84         & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
    85      return TRAVERSE_CONTINUE;
    86    return Expression::traverse(expr, traverse);
    87  }
    88  
    89  // Traverse an expression list in a statement.  This is a helper
    90  // function for child classes.
    91  
    92  int
    93  Statement::traverse_expression_list(Traverse* traverse,
    94  				    Expression_list* expr_list)
    95  {
    96    if (expr_list == NULL)
    97      return TRAVERSE_CONTINUE;
    98    if ((traverse->traverse_mask()
    99         & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
   100      return TRAVERSE_CONTINUE;
   101    return expr_list->traverse(traverse);
   102  }
   103  
   104  // Traverse a type in a statement.  This is a helper function for
   105  // child classes.
   106  
   107  int
   108  Statement::traverse_type(Traverse* traverse, Type* type)
   109  {
   110    if ((traverse->traverse_mask()
   111         & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
   112      return TRAVERSE_CONTINUE;
   113    return Type::traverse(type, traverse);
   114  }
   115  
   116  // Set type information for unnamed constants.  This is really done by
   117  // the child class.
   118  
   119  void
   120  Statement::determine_types()
   121  {
   122    this->do_determine_types();
   123  }
   124  
   125  // Read a statement from export data.
   126  
   127  Statement*
   128  Statement::import_statement(Import_function_body* ifb, Location loc)
   129  {
   130    if (ifb->match_c_string("{"))
   131      {
   132        bool is_lowered_for_statement;
   133        Block* block = Block_statement::do_import(ifb, loc,
   134  						&is_lowered_for_statement);
   135        if (block == NULL)
   136  	return Statement::make_error_statement(loc);
   137        Block_statement* s = Statement::make_block_statement(block, loc);
   138        if (is_lowered_for_statement)
   139  	s->set_is_lowered_for_statement();
   140        return s;
   141      }
   142    else if (ifb->match_c_string("return"))
   143      {
   144        // After lowering return statements have no expressions.  The
   145        // return expressions are assigned to result parameters.
   146        ifb->advance(6);
   147        return Statement::make_return_statement(NULL, loc);
   148      }
   149    else if (ifb->match_c_string("var $t"))
   150      return Temporary_statement::do_import(ifb, loc);
   151    else if (ifb->match_c_string("var "))
   152      return Variable_declaration_statement::do_import(ifb, loc);
   153    else if (ifb->match_c_string("if "))
   154      return If_statement::do_import(ifb, loc);
   155    else if (ifb->match_c_string(":"))
   156      return Label_statement::do_import(ifb, loc);
   157    else if (ifb->match_c_string("goto "))
   158      return Goto_statement::do_import(ifb, loc);
   159  
   160    Expression* lhs = Expression::import_expression(ifb, loc);
   161  
   162    if (ifb->match_c_string(" //"))
   163      return Statement::make_statement(lhs, true);
   164  
   165    ifb->require_c_string(" = ");
   166    Expression* rhs = Expression::import_expression(ifb, loc);
   167    return Statement::make_assignment(lhs, rhs, loc);
   168  }
   169  
   170  // If this is a thunk statement, return it.
   171  
   172  Thunk_statement*
   173  Statement::thunk_statement()
   174  {
   175    Thunk_statement* ret = this->convert<Thunk_statement, STATEMENT_GO>();
   176    if (ret == NULL)
   177      ret = this->convert<Thunk_statement, STATEMENT_DEFER>();
   178    return ret;
   179  }
   180  
   181  // Convert a Statement to the backend representation.  This is really
   182  // done by the child class.
   183  
   184  Bstatement*
   185  Statement::get_backend(Translate_context* context)
   186  {
   187    if (this->classification_ == STATEMENT_ERROR)
   188      return context->backend()->error_statement();
   189    return this->do_get_backend(context);
   190  }
   191  
   192  // Dump AST representation for a statement to a dump context.
   193  
   194  void
   195  Statement::dump_statement(Ast_dump_context* ast_dump_context) const
   196  {
   197    this->do_dump_statement(ast_dump_context);
   198  }
   199  
   200  // Note that this statement is erroneous.  This is called by children
   201  // when they discover an error.
   202  
   203  void
   204  Statement::set_is_error()
   205  {
   206    this->classification_ = STATEMENT_ERROR;
   207  }
   208  
   209  // For children to call to report an error conveniently.
   210  
   211  void
   212  Statement::report_error(const char* msg)
   213  {
   214    go_error_at(this->location_, "%s", msg);
   215    this->set_is_error();
   216  }
   217  
   218  // An error statement, used to avoid crashing after we report an
   219  // error.
   220  
   221  class Error_statement : public Statement
   222  {
   223   public:
   224    Error_statement(Location location)
   225      : Statement(STATEMENT_ERROR, location)
   226    { }
   227  
   228   protected:
   229    int
   230    do_traverse(Traverse*)
   231    { return TRAVERSE_CONTINUE; }
   232  
   233    Bstatement*
   234    do_get_backend(Translate_context*)
   235    { go_unreachable(); }
   236  
   237    void
   238    do_dump_statement(Ast_dump_context*) const;
   239  };
   240  
   241  //
   242  // Helper to tack on available source position information
   243  // at the end of a statement.
   244  //
   245  static std::string
   246  dsuffix(Location location)
   247  {
   248    std::string lstr = Linemap::location_to_string(location);
   249    if (lstr == "")
   250      return lstr;
   251    std::string rval(" // ");
   252    rval += lstr;
   253    return rval;
   254  }
   255  
   256  // Dump the AST representation for an error statement.
   257  
   258  void
   259  Error_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
   260  {
   261    ast_dump_context->print_indent();
   262    ast_dump_context->ostream() << "Error statement" << std::endl;
   263  }
   264  
   265  // Make an error statement.
   266  
   267  Statement*
   268  Statement::make_error_statement(Location location)
   269  {
   270    return new Error_statement(location);
   271  }
   272  
   273  // Class Variable_declaration_statement.
   274  
   275  Variable_declaration_statement::Variable_declaration_statement(
   276      Named_object* var)
   277    : Statement(STATEMENT_VARIABLE_DECLARATION, var->var_value()->location()),
   278      var_(var)
   279  {
   280  }
   281  
   282  // We don't actually traverse the variable here; it was traversed
   283  // while traversing the Block.
   284  
   285  int
   286  Variable_declaration_statement::do_traverse(Traverse*)
   287  {
   288    return TRAVERSE_CONTINUE;
   289  }
   290  
   291  // Traverse the assignments in a variable declaration.  Note that this
   292  // traversal is different from the usual traversal.
   293  
   294  bool
   295  Variable_declaration_statement::do_traverse_assignments(
   296      Traverse_assignments* tassign)
   297  {
   298    tassign->initialize_variable(this->var_);
   299    return true;
   300  }
   301  
   302  // Lower the variable's initialization expression.
   303  
   304  Statement*
   305  Variable_declaration_statement::do_lower(Gogo* gogo, Named_object* function,
   306  					 Block*, Statement_inserter* inserter)
   307  {
   308    this->var_->var_value()->lower_init_expression(gogo, function, inserter);
   309    return this;
   310  }
   311  
   312  // Flatten the variable's initialization expression.
   313  
   314  Statement*
   315  Variable_declaration_statement::do_flatten(Gogo* gogo, Named_object* function,
   316                                             Block*, Statement_inserter* inserter)
   317  {
   318    Variable* var = this->var_->var_value();
   319    if (var->type()->is_error_type()
   320        || (var->init() != NULL
   321            && var->init()->is_error_expression()))
   322      {
   323        go_assert(saw_errors());
   324        return Statement::make_error_statement(this->location());
   325      }
   326    this->var_->var_value()->flatten_init_expression(gogo, function, inserter);
   327    return this;
   328  }
   329  
   330  // Add explicit type conversions.
   331  
   332  void
   333  Variable_declaration_statement::do_add_conversions()
   334  {
   335    Variable* var = this->var_->var_value();
   336    Expression* init = var->init();
   337    if (init == NULL)
   338      return;
   339    Type* lt = var->type();
   340    Type* rt = init->type();
   341    if (!Type::are_identical(lt, rt, 0, NULL)
   342        && lt->interface_type() != NULL)
   343      var->set_init(Expression::make_cast(lt, init, this->location()));
   344  }
   345  
   346  // Convert a variable declaration to the backend representation.
   347  
   348  Bstatement*
   349  Variable_declaration_statement::do_get_backend(Translate_context* context)
   350  {
   351    Bfunction* bfunction = context->function()->func_value()->get_decl();
   352    Variable* var = this->var_->var_value();
   353    Bvariable* bvar = this->var_->get_backend_variable(context->gogo(),
   354  						     context->function());
   355    Bexpression* binit = var->get_init(context->gogo(), context->function());
   356  
   357    if (!var->is_in_heap())
   358      {
   359        go_assert(binit != NULL);
   360        return context->backend()->init_statement(bfunction, bvar, binit);
   361      }
   362  
   363    // Something takes the address of this variable, so the value is
   364    // stored in the heap.  Initialize it to newly allocated memory
   365    // space, and assign the initial value to the new space.
   366    Location loc = this->location();
   367    Named_object* newfn = context->gogo()->lookup_global("new");
   368    go_assert(newfn != NULL && newfn->is_function_declaration());
   369    Expression* func = Expression::make_func_reference(newfn, NULL, loc);
   370    Expression_list* params = new Expression_list();
   371    params->push_back(Expression::make_type(var->type(), loc));
   372    Expression* call = Expression::make_call(func, params, false, loc);
   373    context->gogo()->lower_expression(context->function(), NULL, &call);
   374    Temporary_statement* temp = Statement::make_temporary(NULL, call, loc);
   375    Bstatement* btemp = temp->get_backend(context);
   376  
   377    Bstatement* set = NULL;
   378    if (binit != NULL)
   379      {
   380        Expression* e = Expression::make_temporary_reference(temp, loc);
   381        e = Expression::make_dereference(e, Expression::NIL_CHECK_NOT_NEEDED,
   382                                         loc);
   383        Bexpression* be = e->get_backend(context);
   384        set = context->backend()->assignment_statement(bfunction, be, binit, loc);
   385      }
   386  
   387    Expression* ref = Expression::make_temporary_reference(temp, loc);
   388    Bexpression* bref = ref->get_backend(context);
   389    Bstatement* sinit = context->backend()->init_statement(bfunction, bvar, bref);
   390  
   391    std::vector<Bstatement*> stats;
   392    stats.reserve(3);
   393    stats.push_back(btemp);
   394    if (set != NULL)
   395      stats.push_back(set);
   396    stats.push_back(sinit);
   397    return context->backend()->statement_list(stats);
   398  }
   399  
   400  // Dump the AST representation for a variable declaration.
   401  
   402  void
   403  Variable_declaration_statement::do_dump_statement(
   404      Ast_dump_context* ast_dump_context) const
   405  {
   406    ast_dump_context->print_indent();
   407  
   408    go_assert(var_->is_variable());
   409    ast_dump_context->ostream() << "var " << this->var_->name() <<  " ";
   410    Variable* var = this->var_->var_value();
   411    if (var->has_type())
   412      {
   413        ast_dump_context->dump_type(var->type());
   414        ast_dump_context->ostream() << " ";
   415      }
   416    if (var->init() != NULL)
   417      {
   418        ast_dump_context->ostream() <<  "= ";
   419        ast_dump_context->dump_expression(var->init());
   420      }
   421    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
   422  }
   423  
   424  // Make a variable declaration.
   425  
   426  Statement*
   427  Statement::make_variable_declaration(Named_object* var)
   428  {
   429    return new Variable_declaration_statement(var);
   430  }
   431  
   432  // Export a variable declaration.
   433  
   434  void
   435  Variable_declaration_statement::do_export_statement(Export_function_body* efb)
   436  {
   437    efb->write_c_string("var ");
   438    efb->write_string(Gogo::unpack_hidden_name(this->var_->name()));
   439    efb->write_c_string(" ");
   440    Variable* var = this->var_->var_value();
   441    Type* type = var->type();
   442    efb->write_type(type);
   443    Expression* init = var->init();
   444    if (init != NULL)
   445      {
   446        efb->write_c_string(" = ");
   447  
   448        go_assert(efb->type_context() == NULL);
   449        efb->set_type_context(type);
   450  
   451        init->export_expression(efb);
   452  
   453        efb->set_type_context(NULL);
   454      }
   455  }
   456  
   457  // Import a variable declaration.
   458  
   459  Statement*
   460  Variable_declaration_statement::do_import(Import_function_body* ifb,
   461  					  Location loc)
   462  {
   463    ifb->require_c_string("var ");
   464    std::string id = ifb->read_identifier();
   465    ifb->require_c_string(" ");
   466    Type* type = ifb->read_type();
   467    Expression* init = NULL;
   468    if (ifb->match_c_string(" = "))
   469      {
   470        ifb->advance(3);
   471        init = Expression::import_expression(ifb, loc);
   472      }
   473    Variable* var = new Variable(type, init, false, false, false, loc);
   474    var->set_is_used();
   475    // FIXME: The package we are importing does not yet exist, so we
   476    // can't pass the correct package here.  It probably doesn't matter.
   477    Named_object* no = ifb->block()->bindings()->add_variable(id, NULL, var);
   478    return Statement::make_variable_declaration(no);
   479  }
   480  
   481  // Class Temporary_statement.
   482  
   483  // Return the type of the temporary variable.
   484  
   485  Type*
   486  Temporary_statement::type() const
   487  {
   488    Type* type = this->type_ != NULL ? this->type_ : this->init_->type();
   489  
   490    // Temporary variables cannot have a void type.
   491    if (type->is_void_type())
   492      {
   493        go_assert(saw_errors());
   494        return Type::make_error_type();
   495      }
   496    return type;
   497  }
   498  
   499  // Traversal.
   500  
   501  int
   502  Temporary_statement::do_traverse(Traverse* traverse)
   503  {
   504    if (this->type_ != NULL
   505        && this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
   506      return TRAVERSE_EXIT;
   507    if (this->init_ == NULL)
   508      return TRAVERSE_CONTINUE;
   509    else
   510      return this->traverse_expression(traverse, &this->init_);
   511  }
   512  
   513  // Traverse assignments.
   514  
   515  bool
   516  Temporary_statement::do_traverse_assignments(Traverse_assignments* tassign)
   517  {
   518    if (this->init_ == NULL)
   519      return false;
   520    tassign->value(&this->init_, true, true);
   521    return true;
   522  }
   523  
   524  // Determine types.
   525  
   526  void
   527  Temporary_statement::do_determine_types()
   528  {
   529    if (this->type_ != NULL && this->type_->is_abstract())
   530      this->type_ = this->type_->make_non_abstract_type();
   531  
   532    if (this->init_ != NULL)
   533      {
   534        if (this->type_ == NULL)
   535  	this->init_->determine_type_no_context();
   536        else
   537  	{
   538  	  Type_context context(this->type_, false);
   539  	  this->init_->determine_type(&context);
   540  	}
   541      }
   542  
   543    if (this->type_ == NULL)
   544      {
   545        this->type_ = this->init_->type();
   546        go_assert(!this->type_->is_abstract());
   547      }
   548  }
   549  
   550  // Check types.
   551  
   552  void
   553  Temporary_statement::do_check_types(Gogo*)
   554  {
   555    if (this->type_ != NULL && this->init_ != NULL)
   556      {
   557        std::string reason;
   558        if (!Type::are_assignable(this->type_, this->init_->type(), &reason))
   559  	{
   560  	  if (reason.empty())
   561  	    go_error_at(this->location(), "incompatible types in assignment");
   562  	  else
   563  	    go_error_at(this->location(), "incompatible types in assignment (%s)",
   564  		     reason.c_str());
   565  	  this->set_is_error();
   566  	}
   567      }
   568  }
   569  
   570  // Flatten a temporary statement: add another temporary when it might
   571  // be needed for interface conversion.
   572  
   573  Statement*
   574  Temporary_statement::do_flatten(Gogo*, Named_object*, Block*,
   575  				Statement_inserter* inserter)
   576  {
   577    if (this->type()->is_error_type()
   578        || (this->init_ != NULL
   579            && this->init_->is_error_expression()))
   580      {
   581        go_assert(saw_errors());
   582        return Statement::make_error_statement(this->location());
   583      }
   584  
   585    if (this->type_ != NULL
   586        && this->init_ != NULL
   587        && !Type::are_identical(this->type_, this->init_->type(),
   588  			      Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
   589  			      NULL)
   590        && this->init_->type()->interface_type() != NULL
   591        && !this->init_->is_multi_eval_safe())
   592      {
   593        Temporary_statement *temp =
   594  	Statement::make_temporary(NULL, this->init_, this->location());
   595        inserter->insert(temp);
   596        this->init_ = Expression::make_temporary_reference(temp,
   597  							 this->location());
   598      }
   599    return this;
   600  }
   601  
   602  // Add explicit type conversions.
   603  
   604  void
   605  Temporary_statement::do_add_conversions()
   606  {
   607    if (this->init_ == NULL)
   608      return;
   609    Type* lt = this->type();
   610    Type* rt = this->init_->type();
   611    if (!Type::are_identical(lt, rt, 0, NULL)
   612        && lt->interface_type() != NULL)
   613      this->init_ = Expression::make_cast(lt, this->init_, this->location());
   614  }
   615  
   616  // Convert to backend representation.
   617  
   618  Bstatement*
   619  Temporary_statement::do_get_backend(Translate_context* context)
   620  {
   621    go_assert(this->bvariable_ == NULL);
   622  
   623    Named_object* function = context->function();
   624    go_assert(function != NULL);
   625    Bfunction* bfunction = function->func_value()->get_decl();
   626    Btype* btype = this->type()->get_backend(context->gogo());
   627  
   628    Bexpression* binit;
   629    if (this->init_ == NULL)
   630      binit = NULL;
   631    else if (this->type_ == NULL)
   632      binit = this->init_->get_backend(context);
   633    else
   634      {
   635        Expression* init = Expression::convert_for_assignment(context->gogo(),
   636  							    this->type_,
   637  							    this->init_,
   638  							    this->location());
   639        binit = init->get_backend(context);
   640      }
   641  
   642    if (binit != NULL)
   643      binit = context->backend()->convert_expression(btype, binit,
   644                                                     this->location());
   645  
   646    unsigned int flags = 0;
   647    if (this->is_address_taken_)
   648      flags |= Backend::variable_address_is_taken;
   649    Bstatement* statement;
   650    this->bvariable_ =
   651      context->backend()->temporary_variable(bfunction, context->bblock(),
   652  					   btype, binit, flags,
   653  					   this->location(), &statement);
   654    return statement;
   655  }
   656  
   657  // Return the backend variable.
   658  
   659  Bvariable*
   660  Temporary_statement::get_backend_variable(Translate_context* context) const
   661  {
   662    if (this->bvariable_ == NULL)
   663      {
   664        go_assert(saw_errors());
   665        return context->backend()->error_variable();
   666      }
   667    return this->bvariable_;
   668  }
   669  
   670  // Dump the AST represemtation for a temporary statement
   671  
   672  void
   673  Temporary_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
   674  {
   675    ast_dump_context->print_indent();
   676    ast_dump_context->dump_temp_variable_name(this);
   677    if (this->type_ != NULL)
   678      {
   679        ast_dump_context->ostream() << " ";
   680        ast_dump_context->dump_type(this->type_);
   681      }
   682    if (this->init_ != NULL)
   683      {
   684        ast_dump_context->ostream() << " = ";
   685        ast_dump_context->dump_expression(this->init_);
   686      }
   687    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
   688  }
   689  
   690  // Make and initialize a temporary variable in BLOCK.
   691  
   692  Temporary_statement*
   693  Statement::make_temporary(Type* type, Expression* init,
   694  			  Location location)
   695  {
   696    return new Temporary_statement(type, init, location);
   697  }
   698  
   699  // Export a temporary statement.
   700  
   701  void
   702  Temporary_statement::do_export_statement(Export_function_body* efb)
   703  {
   704    unsigned int idx = efb->record_temporary(this);
   705    char buf[100];
   706    snprintf(buf, sizeof buf, "var $t%u", idx);
   707    efb->write_c_string(buf);
   708    if (this->type_ != NULL)
   709      {
   710        efb->write_c_string(" ");
   711        efb->write_type(this->type_);
   712      }
   713    if (this->init_ != NULL)
   714      {
   715        efb->write_c_string(" = ");
   716  
   717        go_assert(efb->type_context() == NULL);
   718        efb->set_type_context(this->type_);
   719  
   720        this->init_->export_expression(efb);
   721  
   722        efb->set_type_context(NULL);
   723      }
   724  }
   725  
   726  // Import a temporary statement.
   727  
   728  Statement*
   729  Temporary_statement::do_import(Import_function_body* ifb, Location loc)
   730  {
   731    ifb->require_c_string("var ");
   732    std::string id = ifb->read_identifier();
   733    go_assert(id[0] == '$' && id[1] == 't');
   734    const char *p = id.c_str();
   735    char *end;
   736    long idx = strtol(p + 2, &end, 10);
   737    if (*end != '\0' || idx > 0x7fffffff)
   738      {
   739        if (!ifb->saw_error())
   740  	go_error_at(loc,
   741  		    ("invalid export data for %qs: "
   742  		     "bad temporary statement index at %lu"),
   743  		    ifb->name().c_str(),
   744  		    static_cast<unsigned long>(ifb->off()));
   745        ifb->set_saw_error();
   746        return Statement::make_error_statement(loc);
   747      }
   748  
   749    Type* type = NULL;
   750    if (!ifb->match_c_string(" = "))
   751      {
   752        ifb->require_c_string(" ");
   753        type = ifb->read_type();
   754      }
   755    Expression* init = NULL;
   756    if (ifb->match_c_string(" = "))
   757      {
   758        ifb->advance(3);
   759        init = Expression::import_expression(ifb, loc);
   760      }
   761    if (type == NULL && init == NULL)
   762      {
   763        if (!ifb->saw_error())
   764  	go_error_at(loc,
   765  		    ("invalid export data for %qs: "
   766  		     "temporary statement has neither type nor init at %lu"),
   767  		    ifb->name().c_str(),
   768  		    static_cast<unsigned long>(ifb->off()));
   769        ifb->set_saw_error();
   770        return Statement::make_error_statement(loc);
   771      }
   772  
   773    Temporary_statement* temp = Statement::make_temporary(type, init, loc);
   774  
   775    ifb->record_temporary(temp, static_cast<unsigned int>(idx));
   776  
   777    return temp;
   778  }
   779  
   780  // The Move_subexpressions class is used to move all top-level
   781  // subexpressions of an expression.  This is used for things like
   782  // index expressions in which we must evaluate the index value before
   783  // it can be changed by a multiple assignment.
   784  
   785  class Move_subexpressions : public Traverse
   786  {
   787   public:
   788    Move_subexpressions(int skip, Block* block)
   789      : Traverse(traverse_expressions),
   790        skip_(skip), block_(block)
   791    { }
   792  
   793   protected:
   794    int
   795    expression(Expression**);
   796  
   797   private:
   798    // The number of subexpressions to skip moving.  This is used to
   799    // avoid moving the array itself, as we only need to move the index.
   800    int skip_;
   801    // The block where new temporary variables should be added.
   802    Block* block_;
   803  };
   804  
   805  int
   806  Move_subexpressions::expression(Expression** pexpr)
   807  {
   808    if (this->skip_ > 0)
   809      --this->skip_;
   810    else if ((*pexpr)->temporary_reference_expression() == NULL
   811  	   && !(*pexpr)->is_nil_expression()
   812             && !(*pexpr)->is_constant())
   813      {
   814        Location loc = (*pexpr)->location();
   815        Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
   816        this->block_->add_statement(temp);
   817        *pexpr = Expression::make_temporary_reference(temp, loc);
   818      }
   819    // We only need to move top-level subexpressions.
   820    return TRAVERSE_SKIP_COMPONENTS;
   821  }
   822  
   823  // The Move_ordered_evals class is used to find any subexpressions of
   824  // an expression that have an evaluation order dependency.  It creates
   825  // temporary variables to hold them.
   826  
   827  class Move_ordered_evals : public Traverse
   828  {
   829   public:
   830    Move_ordered_evals(Block* block)
   831      : Traverse(traverse_expressions),
   832        block_(block)
   833    { }
   834  
   835   protected:
   836    int
   837    expression(Expression**);
   838  
   839   private:
   840    // The block where new temporary variables should be added.
   841    Block* block_;
   842  };
   843  
   844  int
   845  Move_ordered_evals::expression(Expression** pexpr)
   846  {
   847    // We have to look at subexpressions first.
   848    if ((*pexpr)->traverse_subexpressions(this) == TRAVERSE_EXIT)
   849      return TRAVERSE_EXIT;
   850  
   851    int i;
   852    if ((*pexpr)->must_eval_subexpressions_in_order(&i))
   853      {
   854        Move_subexpressions ms(i, this->block_);
   855        if ((*pexpr)->traverse_subexpressions(&ms) == TRAVERSE_EXIT)
   856  	return TRAVERSE_EXIT;
   857      }
   858  
   859    if ((*pexpr)->must_eval_in_order())
   860      {
   861        Call_expression* call = (*pexpr)->call_expression();
   862        if (call != NULL && call->is_multi_value_arg())
   863  	{
   864  	  // A call expression which returns multiple results as an argument
   865  	  // to another call must be handled specially.  We can't create a
   866  	  // temporary because there is no type to give it.  Instead, group
   867  	  // the caller and this multi-valued call argument and use a temporary
   868  	  // variable to hold them.
   869  	  return TRAVERSE_SKIP_COMPONENTS;
   870  	}
   871  
   872        Location loc = (*pexpr)->location();
   873        Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
   874        this->block_->add_statement(temp);
   875        *pexpr = Expression::make_temporary_reference(temp, loc);
   876      }
   877    return TRAVERSE_SKIP_COMPONENTS;
   878  }
   879  
   880  // Class Assignment_statement.
   881  
   882  // Traversal.
   883  
   884  int
   885  Assignment_statement::do_traverse(Traverse* traverse)
   886  {
   887    if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
   888      return TRAVERSE_EXIT;
   889    return this->traverse_expression(traverse, &this->rhs_);
   890  }
   891  
   892  bool
   893  Assignment_statement::do_traverse_assignments(Traverse_assignments* tassign)
   894  {
   895    tassign->assignment(&this->lhs_, &this->rhs_);
   896    return true;
   897  }
   898  
   899  // Lower an assignment to a map index expression to a runtime function
   900  // call.  Mark some slice assignments as not requiring a write barrier.
   901  
   902  Statement*
   903  Assignment_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
   904  			       Statement_inserter*)
   905  {
   906    Map_index_expression* mie = this->lhs_->map_index_expression();
   907    if (mie != NULL)
   908      {
   909        Location loc = this->location();
   910  
   911        Expression* map = mie->map();
   912        Map_type* mt = map->type()->map_type();
   913        if (mt == NULL)
   914  	{
   915  	  go_assert(saw_errors());
   916  	  return Statement::make_error_statement(loc);
   917  	}
   918  
   919        Block* b = new Block(enclosing, loc);
   920  
   921        // Move out any subexpressions on the left hand side to make
   922        // sure that functions are called in the required order.
   923        Move_ordered_evals moe(b);
   924        mie->traverse_subexpressions(&moe);
   925  
   926        // Copy the key into a temporary so that we can take its address
   927        // without pushing the value onto the heap.
   928  
   929        // var key_temp KEY_TYPE = MAP_INDEX
   930        Temporary_statement* key_temp = Statement::make_temporary(mt->key_type(),
   931  								mie->index(),
   932  								loc);
   933        b->add_statement(key_temp);
   934  
   935        // Copy the value into a temporary to ensure that it is
   936        // evaluated before we add the key to the map.  This may matter
   937        // if the value is itself a reference to the map.
   938  
   939        // var val_temp VAL_TYPE = RHS
   940        Temporary_statement* val_temp = Statement::make_temporary(mt->val_type(),
   941  								this->rhs_,
   942  								loc);
   943        b->add_statement(val_temp);
   944  
   945        // *mapassign(TYPE, MAP, &key_temp) = RHS
   946        Expression* a1 = Expression::make_type_descriptor(mt, loc);
   947        Expression* a2 = mie->map();
   948        Temporary_reference_expression* ref =
   949  	Expression::make_temporary_reference(key_temp, loc);
   950        Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc);
   951        Runtime::Function code;
   952        Map_type::Map_alg alg = mt->algorithm(gogo);
   953        switch (alg)
   954          {
   955            case Map_type::MAP_ALG_FAST32:
   956              {
   957                code = Runtime::MAPASSIGN_FAST32;
   958                Type* uint32_type = Type::lookup_integer_type("uint32");
   959                Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
   960                a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3,
   961                                                  loc);
   962                a3 = Expression::make_dereference(a3,
   963                                                  Expression::NIL_CHECK_NOT_NEEDED,
   964                                                  loc);
   965                break;
   966              }
   967            case Map_type::MAP_ALG_FAST64:
   968              {
   969                code = Runtime::MAPASSIGN_FAST64;
   970                Type* uint64_type = Type::lookup_integer_type("uint64");
   971                Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
   972                a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3,
   973                                                  loc);
   974                a3 = Expression::make_dereference(a3,
   975                                                  Expression::NIL_CHECK_NOT_NEEDED,
   976                                                  loc);
   977                break;
   978              }
   979            case Map_type::MAP_ALG_FAST32PTR:
   980            case Map_type::MAP_ALG_FAST64PTR:
   981              {
   982                code = (alg == Map_type::MAP_ALG_FAST32PTR
   983                        ? Runtime::MAPASSIGN_FAST32PTR
   984                        : Runtime::MAPASSIGN_FAST64PTR);
   985                Type* ptr_type =
   986                  Type::make_pointer_type(Type::make_void_type());
   987                Type* ptr_ptr_type = Type::make_pointer_type(ptr_type);
   988                a3 = Expression::make_unsafe_cast(ptr_ptr_type, a3,
   989                                                  loc);
   990                a3 = Expression::make_dereference(a3,
   991                                                  Expression::NIL_CHECK_NOT_NEEDED,
   992                                                  loc);
   993                break;
   994              }
   995            case Map_type::MAP_ALG_FASTSTR:
   996              code = Runtime::MAPASSIGN_FASTSTR;
   997              a3 = ref;
   998              break;
   999            default:
  1000              code = Runtime::MAPASSIGN;
  1001              break;
  1002          }
  1003        Expression* call = Runtime::make_call(code, loc, 3,
  1004  					    a1, a2, a3);
  1005        Type* ptrval_type = Type::make_pointer_type(mt->val_type());
  1006        call = Expression::make_cast(ptrval_type, call, loc);
  1007        Expression* indir =
  1008            Expression::make_dereference(call, Expression::NIL_CHECK_NOT_NEEDED,
  1009                                         loc);
  1010        ref = Expression::make_temporary_reference(val_temp, loc);
  1011        b->add_statement(Statement::make_assignment(indir, ref, loc));
  1012  
  1013        return Statement::make_block_statement(b, loc);
  1014      }
  1015  
  1016    // An assignment of the form s = s[:n] does not require a write
  1017    // barrier, because the pointer value will not change.
  1018    Array_index_expression* aie = this->rhs_->array_index_expression();
  1019    if (aie != NULL
  1020        && aie->end() != NULL
  1021        && Expression::is_same_variable(this->lhs_, aie->array()))
  1022      {
  1023        Numeric_constant nc;
  1024        unsigned long ival;
  1025        if (aie->start()->numeric_constant_value(&nc)
  1026  	  && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID
  1027  	  && ival == 0)
  1028  	this->omit_write_barrier_ = true;
  1029      }
  1030    String_index_expression* sie = this->rhs_->string_index_expression();
  1031    if (sie != NULL
  1032        && sie->end() != NULL
  1033        && Expression::is_same_variable(this->lhs_, sie->string()))
  1034      {
  1035        Numeric_constant nc;
  1036        unsigned long ival;
  1037        if (sie->start()->numeric_constant_value(&nc)
  1038  	  && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID
  1039  	  && ival == 0)
  1040          this->omit_write_barrier_ = true;
  1041      }
  1042  
  1043    return this;
  1044  }
  1045  
  1046  // Set types for the assignment.
  1047  
  1048  void
  1049  Assignment_statement::do_determine_types()
  1050  {
  1051    this->lhs_->determine_type_no_context();
  1052    Type* rhs_context_type = this->lhs_->type();
  1053    if (rhs_context_type->is_sink_type())
  1054      rhs_context_type = NULL;
  1055    Type_context context(rhs_context_type, false);
  1056    this->rhs_->determine_type(&context);
  1057  }
  1058  
  1059  // Check types for an assignment.
  1060  
  1061  void
  1062  Assignment_statement::do_check_types(Gogo*)
  1063  {
  1064    // The left hand side must be either addressable, a map index
  1065    // expression, or the blank identifier.
  1066    if (!this->lhs_->is_addressable()
  1067        && this->lhs_->map_index_expression() == NULL
  1068        && !this->lhs_->is_sink_expression())
  1069      {
  1070        if (!this->lhs_->type()->is_error())
  1071  	this->report_error(_("invalid left hand side of assignment"));
  1072        return;
  1073      }
  1074  
  1075    Type* lhs_type = this->lhs_->type();
  1076    Type* rhs_type = this->rhs_->type();
  1077  
  1078    // Invalid assignment of nil to the blank identifier.
  1079    if (lhs_type->is_sink_type()
  1080        && rhs_type->is_nil_type())
  1081      {
  1082        this->report_error(_("use of untyped nil"));
  1083        return;
  1084      }
  1085  
  1086    std::string reason;
  1087    if (!Type::are_assignable(lhs_type, rhs_type, &reason))
  1088      {
  1089        if (reason.empty())
  1090  	go_error_at(this->location(), "incompatible types in assignment");
  1091        else
  1092  	go_error_at(this->location(), "incompatible types in assignment (%s)",
  1093  		    reason.c_str());
  1094        this->set_is_error();
  1095      }
  1096  
  1097    if (lhs_type->is_error() || rhs_type->is_error())
  1098      this->set_is_error();
  1099  }
  1100  
  1101  void
  1102  Assignment_statement::do_export_statement(Export_function_body* efb)
  1103  {
  1104    this->lhs_->export_expression(efb);
  1105    efb->write_c_string(" = ");
  1106    this->rhs_->export_expression(efb);
  1107  }
  1108  
  1109  // Flatten an assignment statement.  We may need a temporary for
  1110  // interface conversion.
  1111  
  1112  Statement*
  1113  Assignment_statement::do_flatten(Gogo*, Named_object*, Block*,
  1114  				 Statement_inserter* inserter)
  1115  {
  1116    if (this->lhs_->is_error_expression()
  1117        || this->lhs_->type()->is_error_type()
  1118        || this->rhs_->is_error_expression()
  1119        || this->rhs_->type()->is_error_type())
  1120      {
  1121        go_assert(saw_errors());
  1122        return Statement::make_error_statement(this->location());
  1123      }
  1124  
  1125    if (!this->lhs_->is_sink_expression()
  1126        && !Type::are_identical(this->lhs_->type(), this->rhs_->type(),
  1127  			      Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
  1128  			      NULL)
  1129        && this->rhs_->type()->interface_type() != NULL
  1130        && !this->rhs_->is_multi_eval_safe())
  1131      {
  1132        Temporary_statement* temp =
  1133  	Statement::make_temporary(NULL, this->rhs_, this->location());
  1134        inserter->insert(temp);
  1135        this->rhs_ = Expression::make_temporary_reference(temp,
  1136  							this->location());
  1137      }
  1138    return this;
  1139  }
  1140  
  1141  // Add explicit type conversions.
  1142  
  1143  void
  1144  Assignment_statement::do_add_conversions()
  1145  {
  1146    Type* lt = this->lhs_->type();
  1147    Type* rt = this->rhs_->type();
  1148    if (!Type::are_identical(lt, rt, 0, NULL)
  1149        && lt->interface_type() != NULL)
  1150      this->rhs_ = Expression::make_cast(lt, this->rhs_, this->location());
  1151  }
  1152  
  1153  // Convert an assignment statement to the backend representation.
  1154  
  1155  Bstatement*
  1156  Assignment_statement::do_get_backend(Translate_context* context)
  1157  {
  1158    if (this->lhs_->is_sink_expression())
  1159      {
  1160        Bexpression* rhs = this->rhs_->get_backend(context);
  1161        Bfunction* bfunction = context->function()->func_value()->get_decl();
  1162        return context->backend()->expression_statement(bfunction, rhs);
  1163      }
  1164  
  1165    Bexpression* lhs = this->lhs_->get_backend(context);
  1166    Expression* conv =
  1167        Expression::convert_for_assignment(context->gogo(), this->lhs_->type(),
  1168                                           this->rhs_, this->location());
  1169    Bexpression* rhs = conv->get_backend(context);
  1170    Bfunction* bfunction = context->function()->func_value()->get_decl();
  1171    return context->backend()->assignment_statement(bfunction, lhs, rhs,
  1172                                                    this->location());
  1173  }
  1174  
  1175  // Dump the AST representation for an assignment statement.
  1176  
  1177  void
  1178  Assignment_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
  1179      const
  1180  {
  1181    ast_dump_context->print_indent();
  1182    ast_dump_context->dump_expression(this->lhs_);
  1183    ast_dump_context->ostream() << " = " ;
  1184    ast_dump_context->dump_expression(this->rhs_);
  1185    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  1186  }
  1187  
  1188  // Make an assignment statement.
  1189  
  1190  Assignment_statement*
  1191  Statement::make_assignment(Expression* lhs, Expression* rhs,
  1192  			   Location location)
  1193  {
  1194    Temporary_reference_expression* tre = lhs->temporary_reference_expression();
  1195    if (tre != NULL)
  1196      tre->statement()->set_assigned();
  1197    return new Assignment_statement(lhs, rhs, location);
  1198  }
  1199  
  1200  // An assignment operation statement.
  1201  
  1202  class Assignment_operation_statement : public Statement
  1203  {
  1204   public:
  1205    Assignment_operation_statement(Operator op, Expression* lhs, Expression* rhs,
  1206  				 Location location)
  1207      : Statement(STATEMENT_ASSIGNMENT_OPERATION, location),
  1208        op_(op), lhs_(lhs), rhs_(rhs)
  1209    { }
  1210  
  1211   protected:
  1212    int
  1213    do_traverse(Traverse*);
  1214  
  1215    bool
  1216    do_traverse_assignments(Traverse_assignments*)
  1217    { go_unreachable(); }
  1218  
  1219    Statement*
  1220    do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
  1221  
  1222    Bstatement*
  1223    do_get_backend(Translate_context*)
  1224    { go_unreachable(); }
  1225  
  1226    void
  1227    do_dump_statement(Ast_dump_context*) const;
  1228  
  1229   private:
  1230    // The operator (OPERATOR_PLUSEQ, etc.).
  1231    Operator op_;
  1232    // Left hand side.
  1233    Expression* lhs_;
  1234    // Right hand side.
  1235    Expression* rhs_;
  1236  };
  1237  
  1238  // Traversal.
  1239  
  1240  int
  1241  Assignment_operation_statement::do_traverse(Traverse* traverse)
  1242  {
  1243    if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
  1244      return TRAVERSE_EXIT;
  1245    return this->traverse_expression(traverse, &this->rhs_);
  1246  }
  1247  
  1248  // Lower an assignment operation statement to a regular assignment
  1249  // statement.
  1250  
  1251  Statement*
  1252  Assignment_operation_statement::do_lower(Gogo*, Named_object*,
  1253  					 Block* enclosing, Statement_inserter*)
  1254  {
  1255    Location loc = this->location();
  1256  
  1257    // We have to evaluate the left hand side expression only once.  We
  1258    // do this by moving out any expression with side effects.
  1259    Block* b = new Block(enclosing, loc);
  1260    Move_ordered_evals moe(b);
  1261    this->lhs_->traverse_subexpressions(&moe);
  1262  
  1263    // We can still be left with subexpressions that have to be loaded
  1264    // even if they don't have side effects themselves, in case the RHS
  1265    // changes variables named on the LHS.
  1266    int i;
  1267    if (this->lhs_->must_eval_subexpressions_in_order(&i))
  1268      {
  1269        Move_subexpressions ms(i, b);
  1270        this->lhs_->traverse_subexpressions(&ms);
  1271      }
  1272  
  1273    Expression* lval = this->lhs_->copy();
  1274  
  1275    Operator op;
  1276    switch (this->op_)
  1277      {
  1278      case OPERATOR_PLUSEQ:
  1279        op = OPERATOR_PLUS;
  1280        break;
  1281      case OPERATOR_MINUSEQ:
  1282        op = OPERATOR_MINUS;
  1283        break;
  1284      case OPERATOR_OREQ:
  1285        op = OPERATOR_OR;
  1286        break;
  1287      case OPERATOR_XOREQ:
  1288        op = OPERATOR_XOR;
  1289        break;
  1290      case OPERATOR_MULTEQ:
  1291        op = OPERATOR_MULT;
  1292        break;
  1293      case OPERATOR_DIVEQ:
  1294        op = OPERATOR_DIV;
  1295        break;
  1296      case OPERATOR_MODEQ:
  1297        op = OPERATOR_MOD;
  1298        break;
  1299      case OPERATOR_LSHIFTEQ:
  1300        op = OPERATOR_LSHIFT;
  1301        break;
  1302      case OPERATOR_RSHIFTEQ:
  1303        op = OPERATOR_RSHIFT;
  1304        break;
  1305      case OPERATOR_ANDEQ:
  1306        op = OPERATOR_AND;
  1307        break;
  1308      case OPERATOR_BITCLEAREQ:
  1309        op = OPERATOR_BITCLEAR;
  1310        break;
  1311      default:
  1312        go_unreachable();
  1313      }
  1314  
  1315    Expression* binop = Expression::make_binary(op, lval, this->rhs_, loc);
  1316    Statement* s = Statement::make_assignment(this->lhs_, binop, loc);
  1317    if (b->statements()->empty())
  1318      {
  1319        delete b;
  1320        return s;
  1321      }
  1322    else
  1323      {
  1324        b->add_statement(s);
  1325        return Statement::make_block_statement(b, loc);
  1326      }
  1327  }
  1328  
  1329  // Dump the AST representation for an assignment operation statement
  1330  
  1331  void
  1332  Assignment_operation_statement::do_dump_statement(
  1333      Ast_dump_context* ast_dump_context) const
  1334  {
  1335    ast_dump_context->print_indent();
  1336    ast_dump_context->dump_expression(this->lhs_);
  1337    ast_dump_context->dump_operator(this->op_);
  1338    ast_dump_context->dump_expression(this->rhs_);
  1339    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  1340  }
  1341  
  1342  // Make an assignment operation statement.
  1343  
  1344  Statement*
  1345  Statement::make_assignment_operation(Operator op, Expression* lhs,
  1346  				     Expression* rhs, Location location)
  1347  {
  1348    return new Assignment_operation_statement(op, lhs, rhs, location);
  1349  }
  1350  
  1351  // A tuple assignment statement.  This differs from an assignment
  1352  // statement in that the right-hand-side expressions are evaluated in
  1353  // parallel.
  1354  
  1355  class Tuple_assignment_statement : public Statement
  1356  {
  1357   public:
  1358    Tuple_assignment_statement(Expression_list* lhs, Expression_list* rhs,
  1359  			     Location location)
  1360      : Statement(STATEMENT_TUPLE_ASSIGNMENT, location),
  1361        lhs_(lhs), rhs_(rhs)
  1362    { }
  1363  
  1364   protected:
  1365    int
  1366    do_traverse(Traverse* traverse);
  1367  
  1368    bool
  1369    do_traverse_assignments(Traverse_assignments*)
  1370    { go_unreachable(); }
  1371  
  1372    Statement*
  1373    do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
  1374  
  1375    Bstatement*
  1376    do_get_backend(Translate_context*)
  1377    { go_unreachable(); }
  1378  
  1379    void
  1380    do_dump_statement(Ast_dump_context*) const;
  1381  
  1382   private:
  1383    // Left hand side--a list of lvalues.
  1384    Expression_list* lhs_;
  1385    // Right hand side--a list of rvalues.
  1386    Expression_list* rhs_;
  1387  };
  1388  
  1389  // Traversal.
  1390  
  1391  int
  1392  Tuple_assignment_statement::do_traverse(Traverse* traverse)
  1393  {
  1394    if (this->traverse_expression_list(traverse, this->lhs_) == TRAVERSE_EXIT)
  1395      return TRAVERSE_EXIT;
  1396    return this->traverse_expression_list(traverse, this->rhs_);
  1397  }
  1398  
  1399  // Lower a tuple assignment.  We use temporary variables to split it
  1400  // up into a set of single assignments.
  1401  
  1402  Statement*
  1403  Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
  1404  				     Statement_inserter*)
  1405  {
  1406    Location loc = this->location();
  1407  
  1408    Block* b = new Block(enclosing, loc);
  1409  
  1410    // First move out any subexpressions on the left hand side.  The
  1411    // right hand side will be evaluated in the required order anyhow.
  1412    Move_ordered_evals moe(b);
  1413    for (Expression_list::iterator plhs = this->lhs_->begin();
  1414         plhs != this->lhs_->end();
  1415         ++plhs)
  1416      Expression::traverse(&*plhs, &moe);
  1417  
  1418    std::vector<Temporary_statement*> temps;
  1419    temps.reserve(this->lhs_->size());
  1420  
  1421    Expression_list::const_iterator prhs = this->rhs_->begin();
  1422    for (Expression_list::const_iterator plhs = this->lhs_->begin();
  1423         plhs != this->lhs_->end();
  1424         ++plhs, ++prhs)
  1425      {
  1426        go_assert(prhs != this->rhs_->end());
  1427  
  1428        if ((*plhs)->is_error_expression()
  1429  	  || (*plhs)->type()->is_error()
  1430  	  || (*prhs)->is_error_expression()
  1431  	  || (*prhs)->type()->is_error())
  1432  	continue;
  1433  
  1434        if ((*plhs)->is_sink_expression())
  1435  	{
  1436            if ((*prhs)->type()->is_nil_type())
  1437              this->report_error(_("use of untyped nil"));
  1438            else
  1439              b->add_statement(Statement::make_statement(*prhs, true));
  1440  	  continue;
  1441  	}
  1442  
  1443        Temporary_statement* temp = Statement::make_temporary((*plhs)->type(),
  1444  							    *prhs, loc);
  1445        b->add_statement(temp);
  1446        temps.push_back(temp);
  1447  
  1448      }
  1449    go_assert(prhs == this->rhs_->end());
  1450  
  1451    prhs = this->rhs_->begin();
  1452    std::vector<Temporary_statement*>::const_iterator ptemp = temps.begin();
  1453    for (Expression_list::const_iterator plhs = this->lhs_->begin();
  1454         plhs != this->lhs_->end();
  1455         ++plhs, ++prhs)
  1456      {
  1457        if ((*plhs)->is_error_expression()
  1458  	  || (*plhs)->type()->is_error()
  1459  	  || (*prhs)->is_error_expression()
  1460  	  || (*prhs)->type()->is_error())
  1461  	continue;
  1462  
  1463        if ((*plhs)->is_sink_expression())
  1464  	continue;
  1465  
  1466        Expression* ref = Expression::make_temporary_reference(*ptemp, loc);
  1467        b->add_statement(Statement::make_assignment(*plhs, ref, loc));
  1468        ++ptemp;
  1469      }
  1470    go_assert(ptemp == temps.end() || saw_errors());
  1471  
  1472    return Statement::make_block_statement(b, loc);
  1473  }
  1474  
  1475  // Dump the AST representation for a tuple assignment statement.
  1476  
  1477  void
  1478  Tuple_assignment_statement::do_dump_statement(
  1479      Ast_dump_context* ast_dump_context) const
  1480  {
  1481    ast_dump_context->print_indent();
  1482    ast_dump_context->dump_expression_list(this->lhs_);
  1483    ast_dump_context->ostream() << " = ";
  1484    ast_dump_context->dump_expression_list(this->rhs_);
  1485    ast_dump_context->ostream()  << dsuffix(location()) << std::endl;
  1486  }
  1487  
  1488  // Make a tuple assignment statement.
  1489  
  1490  Statement*
  1491  Statement::make_tuple_assignment(Expression_list* lhs, Expression_list* rhs,
  1492  				 Location location)
  1493  {
  1494    return new Tuple_assignment_statement(lhs, rhs, location);
  1495  }
  1496  
  1497  // A tuple assignment from a map index expression.
  1498  //   v, ok = m[k]
  1499  
  1500  class Tuple_map_assignment_statement : public Statement
  1501  {
  1502  public:
  1503    Tuple_map_assignment_statement(Expression* val, Expression* present,
  1504  				 Expression* map_index,
  1505  				 Location location)
  1506      : Statement(STATEMENT_TUPLE_MAP_ASSIGNMENT, location),
  1507        val_(val), present_(present), map_index_(map_index)
  1508    { }
  1509  
  1510   protected:
  1511    int
  1512    do_traverse(Traverse* traverse);
  1513  
  1514    bool
  1515    do_traverse_assignments(Traverse_assignments*)
  1516    { go_unreachable(); }
  1517  
  1518    Statement*
  1519    do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
  1520  
  1521    Bstatement*
  1522    do_get_backend(Translate_context*)
  1523    { go_unreachable(); }
  1524  
  1525    void
  1526    do_dump_statement(Ast_dump_context*) const;
  1527  
  1528   private:
  1529    // Lvalue which receives the value from the map.
  1530    Expression* val_;
  1531    // Lvalue which receives whether the key value was present.
  1532    Expression* present_;
  1533    // The map index expression.
  1534    Expression* map_index_;
  1535  };
  1536  
  1537  // Traversal.
  1538  
  1539  int
  1540  Tuple_map_assignment_statement::do_traverse(Traverse* traverse)
  1541  {
  1542    if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
  1543        || this->traverse_expression(traverse, &this->present_) == TRAVERSE_EXIT)
  1544      return TRAVERSE_EXIT;
  1545    return this->traverse_expression(traverse, &this->map_index_);
  1546  }
  1547  
  1548  // Lower a tuple map assignment.
  1549  
  1550  Statement*
  1551  Tuple_map_assignment_statement::do_lower(Gogo* gogo, Named_object*,
  1552  					 Block* enclosing, Statement_inserter*)
  1553  {
  1554    Location loc = this->location();
  1555  
  1556    Map_index_expression* map_index = this->map_index_->map_index_expression();
  1557    if (map_index == NULL)
  1558      {
  1559        this->report_error(_("expected map index on right hand side"));
  1560        return Statement::make_error_statement(loc);
  1561      }
  1562    Map_type* map_type = map_index->get_map_type();
  1563    if (map_type == NULL)
  1564      return Statement::make_error_statement(loc);
  1565  
  1566    // Avoid copy for string([]byte) conversions used in map keys.
  1567    // mapaccess doesn't keep the reference, so this is safe.
  1568    Type_conversion_expression* ce = map_index->index()->conversion_expression();
  1569    if (ce != NULL && ce->type()->is_string_type()
  1570        && ce->expr()->type()->is_slice_type())
  1571      ce->set_no_copy(true);
  1572  
  1573    Block* b = new Block(enclosing, loc);
  1574  
  1575    // Move out any subexpressions to make sure that functions are
  1576    // called in the required order.
  1577    Move_ordered_evals moe(b);
  1578    this->val_->traverse_subexpressions(&moe);
  1579    this->present_->traverse_subexpressions(&moe);
  1580  
  1581    // Copy the key value into a temporary so that we can take its
  1582    // address without pushing the value onto the heap.
  1583  
  1584    // var key_temp KEY_TYPE = MAP_INDEX
  1585    Temporary_statement* key_temp =
  1586      Statement::make_temporary(map_type->key_type(), map_index->index(), loc);
  1587    b->add_statement(key_temp);
  1588  
  1589    // var val_ptr_temp *VAL_TYPE
  1590    Type* val_ptr_type = Type::make_pointer_type(map_type->val_type());
  1591    Temporary_statement* val_ptr_temp = Statement::make_temporary(val_ptr_type,
  1592  								NULL, loc);
  1593    b->add_statement(val_ptr_temp);
  1594  
  1595    // var present_temp bool
  1596    Temporary_statement* present_temp =
  1597      Statement::make_temporary((this->present_->type()->is_boolean_type()
  1598  			       ? this->present_->type()
  1599  			       : Type::lookup_bool_type()),
  1600  			      NULL, loc);
  1601    b->add_statement(present_temp);
  1602  
  1603    // val_ptr_temp, present_temp = mapaccess2(DESCRIPTOR, MAP, &key_temp)
  1604    Expression* a1 = Expression::make_type_descriptor(map_type, loc);
  1605    Expression* a2 = map_index->map();
  1606    Temporary_reference_expression* ref =
  1607      Expression::make_temporary_reference(key_temp, loc);
  1608    Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc);
  1609    Expression* a4 = map_type->fat_zero_value(gogo);
  1610    Call_expression* call;
  1611    if (a4 == NULL)
  1612      {
  1613        Runtime::Function code;
  1614        Map_type::Map_alg alg = map_type->algorithm(gogo);
  1615        switch (alg)
  1616          {
  1617            case Map_type::MAP_ALG_FAST32:
  1618            case Map_type::MAP_ALG_FAST32PTR:
  1619              {
  1620                code = Runtime::MAPACCESS2_FAST32;
  1621                Type* uint32_type = Type::lookup_integer_type("uint32");
  1622                Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
  1623                a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3,
  1624                                                  loc);
  1625                a3 = Expression::make_dereference(a3,
  1626                                                  Expression::NIL_CHECK_NOT_NEEDED,
  1627                                                  loc);
  1628                break;
  1629              }
  1630            case Map_type::MAP_ALG_FAST64:
  1631            case Map_type::MAP_ALG_FAST64PTR:
  1632              {
  1633                code = Runtime::MAPACCESS2_FAST64;
  1634                Type* uint64_type = Type::lookup_integer_type("uint64");
  1635                Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
  1636                a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3,
  1637                                                  loc);
  1638                a3 = Expression::make_dereference(a3,
  1639                                                  Expression::NIL_CHECK_NOT_NEEDED,
  1640                                                  loc);
  1641                break;
  1642              }
  1643            case Map_type::MAP_ALG_FASTSTR:
  1644              code = Runtime::MAPACCESS2_FASTSTR;
  1645              a3 = ref;
  1646              break;
  1647            default:
  1648              code = Runtime::MAPACCESS2;
  1649              break;
  1650          }
  1651        call = Runtime::make_call(code, loc, 3, a1, a2, a3);
  1652      }
  1653    else
  1654      call = Runtime::make_call(Runtime::MAPACCESS2_FAT, loc, 4, a1, a2, a3, a4);
  1655    ref = Expression::make_temporary_reference(val_ptr_temp, loc);
  1656    ref->set_is_lvalue();
  1657    Expression* res = Expression::make_call_result(call, 0);
  1658    res = Expression::make_unsafe_cast(val_ptr_type, res, loc);
  1659    Statement* s = Statement::make_assignment(ref, res, loc);
  1660    b->add_statement(s);
  1661    ref = Expression::make_temporary_reference(present_temp, loc);
  1662    ref->set_is_lvalue();
  1663    res = Expression::make_call_result(call, 1);
  1664    s = Statement::make_assignment(ref, res, loc);
  1665    b->add_statement(s);
  1666  
  1667    // val = *val__ptr_temp
  1668    ref = Expression::make_temporary_reference(val_ptr_temp, loc);
  1669    Expression* ind =
  1670        Expression::make_dereference(ref, Expression::NIL_CHECK_NOT_NEEDED, loc);
  1671    s = Statement::make_assignment(this->val_, ind, loc);
  1672    b->add_statement(s);
  1673  
  1674    // present = present_temp
  1675    ref = Expression::make_temporary_reference(present_temp, loc);
  1676    s = Statement::make_assignment(this->present_, ref, loc);
  1677    b->add_statement(s);
  1678  
  1679    return Statement::make_block_statement(b, loc);
  1680  }
  1681  
  1682  // Dump the AST representation for a tuple map assignment statement.
  1683  
  1684  void
  1685  Tuple_map_assignment_statement::do_dump_statement(
  1686      Ast_dump_context* ast_dump_context) const
  1687  {
  1688    ast_dump_context->print_indent();
  1689    ast_dump_context->dump_expression(this->val_);
  1690    ast_dump_context->ostream() << ", ";
  1691    ast_dump_context->dump_expression(this->present_);
  1692    ast_dump_context->ostream() << " = ";
  1693    ast_dump_context->dump_expression(this->map_index_);
  1694    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  1695  }
  1696  
  1697  // Make a map assignment statement which returns a pair of values.
  1698  
  1699  Statement*
  1700  Statement::make_tuple_map_assignment(Expression* val, Expression* present,
  1701  				     Expression* map_index,
  1702  				     Location location)
  1703  {
  1704    return new Tuple_map_assignment_statement(val, present, map_index, location);
  1705  }
  1706  
  1707  // A tuple assignment from a receive statement.
  1708  
  1709  class Tuple_receive_assignment_statement : public Statement
  1710  {
  1711   public:
  1712    Tuple_receive_assignment_statement(Expression* val, Expression* closed,
  1713  				     Expression* channel, Location location)
  1714      : Statement(STATEMENT_TUPLE_RECEIVE_ASSIGNMENT, location),
  1715        val_(val), closed_(closed), channel_(channel)
  1716    { }
  1717  
  1718   protected:
  1719    int
  1720    do_traverse(Traverse* traverse);
  1721  
  1722    bool
  1723    do_traverse_assignments(Traverse_assignments*)
  1724    { go_unreachable(); }
  1725  
  1726    Statement*
  1727    do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
  1728  
  1729    Bstatement*
  1730    do_get_backend(Translate_context*)
  1731    { go_unreachable(); }
  1732  
  1733    void
  1734    do_dump_statement(Ast_dump_context*) const;
  1735  
  1736   private:
  1737    // Lvalue which receives the value from the channel.
  1738    Expression* val_;
  1739    // Lvalue which receives whether the channel is closed.
  1740    Expression* closed_;
  1741    // The channel on which we receive the value.
  1742    Expression* channel_;
  1743  };
  1744  
  1745  // Traversal.
  1746  
  1747  int
  1748  Tuple_receive_assignment_statement::do_traverse(Traverse* traverse)
  1749  {
  1750    if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
  1751        || this->traverse_expression(traverse, &this->closed_) == TRAVERSE_EXIT)
  1752      return TRAVERSE_EXIT;
  1753    return this->traverse_expression(traverse, &this->channel_);
  1754  }
  1755  
  1756  // Lower to a function call.
  1757  
  1758  Statement*
  1759  Tuple_receive_assignment_statement::do_lower(Gogo*, Named_object*,
  1760  					     Block* enclosing,
  1761  					     Statement_inserter*)
  1762  {
  1763    Location loc = this->location();
  1764  
  1765    Channel_type* channel_type = this->channel_->type()->channel_type();
  1766    if (channel_type == NULL)
  1767      {
  1768        this->report_error(_("expected channel"));
  1769        return Statement::make_error_statement(loc);
  1770      }
  1771    if (!channel_type->may_receive())
  1772      {
  1773        this->report_error(_("invalid receive on send-only channel"));
  1774        return Statement::make_error_statement(loc);
  1775      }
  1776  
  1777    Block* b = new Block(enclosing, loc);
  1778  
  1779    // Make sure that any subexpressions on the left hand side are
  1780    // evaluated in the right order.
  1781    Move_ordered_evals moe(b);
  1782    this->val_->traverse_subexpressions(&moe);
  1783    this->closed_->traverse_subexpressions(&moe);
  1784  
  1785    // var val_temp ELEMENT_TYPE
  1786    Temporary_statement* val_temp =
  1787      Statement::make_temporary(channel_type->element_type(), NULL, loc);
  1788    b->add_statement(val_temp);
  1789  
  1790    // var closed_temp bool
  1791    Temporary_statement* closed_temp =
  1792      Statement::make_temporary((this->closed_->type()->is_boolean_type()
  1793  			       ? this->closed_->type()
  1794  			       : Type::lookup_bool_type()),
  1795  			      NULL, loc);
  1796    b->add_statement(closed_temp);
  1797  
  1798    // closed_temp = chanrecv2(channel, &val_temp)
  1799    Temporary_reference_expression* ref =
  1800      Expression::make_temporary_reference(val_temp, loc);
  1801    Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
  1802    Expression* call = Runtime::make_call(Runtime::CHANRECV2,
  1803  					loc, 2, this->channel_, p2);
  1804    ref = Expression::make_temporary_reference(closed_temp, loc);
  1805    ref->set_is_lvalue();
  1806    Statement* s = Statement::make_assignment(ref, call, loc);
  1807    b->add_statement(s);
  1808  
  1809    // val = val_temp
  1810    ref = Expression::make_temporary_reference(val_temp, loc);
  1811    s = Statement::make_assignment(this->val_, ref, loc);
  1812    b->add_statement(s);
  1813  
  1814    // closed = closed_temp
  1815    ref = Expression::make_temporary_reference(closed_temp, loc);
  1816    s = Statement::make_assignment(this->closed_, ref, loc);
  1817    b->add_statement(s);
  1818  
  1819    return Statement::make_block_statement(b, loc);
  1820  }
  1821  
  1822  // Dump the AST representation for a tuple receive statement.
  1823  
  1824  void
  1825  Tuple_receive_assignment_statement::do_dump_statement(
  1826      Ast_dump_context* ast_dump_context) const
  1827  {
  1828    ast_dump_context->print_indent();
  1829    ast_dump_context->dump_expression(this->val_);
  1830    ast_dump_context->ostream() << ", ";
  1831    ast_dump_context->dump_expression(this->closed_);
  1832    ast_dump_context->ostream() << " <- ";
  1833    ast_dump_context->dump_expression(this->channel_);
  1834    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  1835  }
  1836  
  1837  // Make a nonblocking receive statement.
  1838  
  1839  Statement*
  1840  Statement::make_tuple_receive_assignment(Expression* val, Expression* closed,
  1841  					 Expression* channel,
  1842  					 Location location)
  1843  {
  1844    return new Tuple_receive_assignment_statement(val, closed, channel,
  1845  						location);
  1846  }
  1847  
  1848  // An assignment to a pair of values from a type guard.  This is a
  1849  // conditional type guard.  v, ok = i.(type).
  1850  
  1851  class Tuple_type_guard_assignment_statement : public Statement
  1852  {
  1853   public:
  1854    Tuple_type_guard_assignment_statement(Expression* val, Expression* ok,
  1855  					Expression* expr, Type* type,
  1856  					Location location)
  1857      : Statement(STATEMENT_TUPLE_TYPE_GUARD_ASSIGNMENT, location),
  1858        val_(val), ok_(ok), expr_(expr), type_(type)
  1859    { }
  1860  
  1861   protected:
  1862    int
  1863    do_traverse(Traverse*);
  1864  
  1865    bool
  1866    do_traverse_assignments(Traverse_assignments*)
  1867    { go_unreachable(); }
  1868  
  1869    Statement*
  1870    do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
  1871  
  1872    Bstatement*
  1873    do_get_backend(Translate_context*)
  1874    { go_unreachable(); }
  1875  
  1876    void
  1877    do_dump_statement(Ast_dump_context*) const;
  1878  
  1879   private:
  1880    Call_expression*
  1881    lower_to_type(Runtime::Function);
  1882  
  1883    void
  1884    lower_to_object_type(Block*, Runtime::Function);
  1885  
  1886    // The variable which recieves the converted value.
  1887    Expression* val_;
  1888    // The variable which receives the indication of success.
  1889    Expression* ok_;
  1890    // The expression being converted.
  1891    Expression* expr_;
  1892    // The type to which the expression is being converted.
  1893    Type* type_;
  1894  };
  1895  
  1896  // Traverse a type guard tuple assignment.
  1897  
  1898  int
  1899  Tuple_type_guard_assignment_statement::do_traverse(Traverse* traverse)
  1900  {
  1901    if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
  1902        || this->traverse_expression(traverse, &this->ok_) == TRAVERSE_EXIT
  1903        || this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
  1904      return TRAVERSE_EXIT;
  1905    return this->traverse_expression(traverse, &this->expr_);
  1906  }
  1907  
  1908  // Lower to a function call.
  1909  
  1910  Statement*
  1911  Tuple_type_guard_assignment_statement::do_lower(Gogo*, Named_object*,
  1912  						Block* enclosing,
  1913  						Statement_inserter*)
  1914  {
  1915    Location loc = this->location();
  1916  
  1917    Type* expr_type = this->expr_->type();
  1918    if (expr_type->interface_type() == NULL)
  1919      {
  1920        if (!expr_type->is_error() && !this->type_->is_error())
  1921  	this->report_error(_("type assertion only valid for interface types"));
  1922        return Statement::make_error_statement(loc);
  1923      }
  1924  
  1925    Block* b = new Block(enclosing, loc);
  1926  
  1927    // Make sure that any subexpressions on the left hand side are
  1928    // evaluated in the right order.
  1929    Move_ordered_evals moe(b);
  1930    this->val_->traverse_subexpressions(&moe);
  1931    this->ok_->traverse_subexpressions(&moe);
  1932  
  1933    bool expr_is_empty = expr_type->interface_type()->is_empty();
  1934    Call_expression* call;
  1935    if (this->type_->interface_type() != NULL)
  1936      {
  1937        if (this->type_->interface_type()->is_empty())
  1938  	call = Runtime::make_call((expr_is_empty
  1939  				   ? Runtime::IFACEE2E2
  1940  				   : Runtime::IFACEI2E2),
  1941  				  loc, 1, this->expr_);
  1942        else
  1943  	call = this->lower_to_type(expr_is_empty
  1944  				   ? Runtime::IFACEE2I2
  1945  				   : Runtime::IFACEI2I2);
  1946      }
  1947    else if (this->type_->points_to() != NULL)
  1948      call = this->lower_to_type(expr_is_empty
  1949  			       ? Runtime::IFACEE2T2P
  1950  			       : Runtime::IFACEI2T2P);
  1951    else
  1952      {
  1953        this->lower_to_object_type(b,
  1954  				 (expr_is_empty
  1955  				  ? Runtime::IFACEE2T2
  1956  				  : Runtime::IFACEI2T2));
  1957        call = NULL;
  1958      }
  1959  
  1960    if (call != NULL)
  1961      {
  1962        Expression* res = Expression::make_call_result(call, 0);
  1963        res = Expression::make_unsafe_cast(this->type_, res, loc);
  1964        Statement* s = Statement::make_assignment(this->val_, res, loc);
  1965        b->add_statement(s);
  1966  
  1967        res = Expression::make_call_result(call, 1);
  1968        if (!this->ok_->type()->is_boolean_type())
  1969  	res = Expression::make_cast(Type::lookup_bool_type(), res, loc);
  1970        s = Statement::make_assignment(this->ok_, res, loc);
  1971        b->add_statement(s);
  1972      }
  1973  
  1974    return Statement::make_block_statement(b, loc);
  1975  }
  1976  
  1977  // Lower a conversion to a non-empty interface type or a pointer type.
  1978  
  1979  Call_expression*
  1980  Tuple_type_guard_assignment_statement::lower_to_type(Runtime::Function code)
  1981  {
  1982    Location loc = this->location();
  1983    return Runtime::make_call(code, loc, 2,
  1984  			    Expression::make_type_descriptor(this->type_, loc),
  1985  			    this->expr_);
  1986  }
  1987  
  1988  // Lower a conversion to a non-interface non-pointer type.
  1989  
  1990  void
  1991  Tuple_type_guard_assignment_statement::lower_to_object_type(
  1992      Block* b,
  1993      Runtime::Function code)
  1994  {
  1995    Location loc = this->location();
  1996  
  1997    // var val_temp TYPE
  1998    Temporary_statement* val_temp = Statement::make_temporary(this->type_,
  1999  							    NULL, loc);
  2000    b->add_statement(val_temp);
  2001  
  2002    // var ok_temp bool
  2003    Temporary_statement* ok_temp = NULL;
  2004    if (!this->ok_->is_sink_expression())
  2005      {
  2006        ok_temp = Statement::make_temporary((this->ok_->type()->is_boolean_type()
  2007  					   ? this->ok_->type()
  2008  					   : Type::lookup_bool_type()),
  2009  					  NULL, loc);
  2010        b->add_statement(ok_temp);
  2011      }
  2012  
  2013    // ok_temp = CODE(type_descriptor, expr, &val_temp)
  2014    Expression* p1 = Expression::make_type_descriptor(this->type_, loc);
  2015    Expression* ref = Expression::make_temporary_reference(val_temp, loc);
  2016    Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
  2017    Expression* call = Runtime::make_call(code, loc, 3, p1, this->expr_, p3);
  2018    Statement* s;
  2019    if (ok_temp == NULL)
  2020      s = Statement::make_statement(call, true);
  2021    else
  2022      {
  2023        Expression* ok_ref = Expression::make_temporary_reference(ok_temp, loc);
  2024        s = Statement::make_assignment(ok_ref, call, loc);
  2025      }
  2026    b->add_statement(s);
  2027  
  2028    // val = val_temp
  2029    ref = Expression::make_temporary_reference(val_temp, loc);
  2030    s = Statement::make_assignment(this->val_, ref, loc);
  2031    b->add_statement(s);
  2032  
  2033    // ok = ok_temp
  2034    if (ok_temp != NULL)
  2035      {
  2036        ref = Expression::make_temporary_reference(ok_temp, loc);
  2037        s = Statement::make_assignment(this->ok_, ref, loc);
  2038        b->add_statement(s);
  2039      }
  2040  }
  2041  
  2042  // Dump the AST representation for a tuple type guard statement.
  2043  
  2044  void
  2045  Tuple_type_guard_assignment_statement::do_dump_statement(
  2046      Ast_dump_context* ast_dump_context) const
  2047  {
  2048    ast_dump_context->print_indent();
  2049    ast_dump_context->dump_expression(this->val_);
  2050    ast_dump_context->ostream() << ", ";
  2051    ast_dump_context->dump_expression(this->ok_);
  2052    ast_dump_context->ostream() << " = ";
  2053    ast_dump_context->dump_expression(this->expr_);
  2054    ast_dump_context->ostream() << " . ";
  2055    ast_dump_context->dump_type(this->type_);
  2056    ast_dump_context->ostream()  << dsuffix(location()) << std::endl;
  2057  }
  2058  
  2059  // Make an assignment from a type guard to a pair of variables.
  2060  
  2061  Statement*
  2062  Statement::make_tuple_type_guard_assignment(Expression* val, Expression* ok,
  2063  					    Expression* expr, Type* type,
  2064  					    Location location)
  2065  {
  2066    return new Tuple_type_guard_assignment_statement(val, ok, expr, type,
  2067  						   location);
  2068  }
  2069  
  2070  // Class Expression_statement.
  2071  
  2072  // Constructor.
  2073  
  2074  Expression_statement::Expression_statement(Expression* expr, bool is_ignored)
  2075    : Statement(STATEMENT_EXPRESSION, expr->location()),
  2076      expr_(expr), is_ignored_(is_ignored)
  2077  {
  2078  }
  2079  
  2080  // Determine types.
  2081  
  2082  void
  2083  Expression_statement::do_determine_types()
  2084  {
  2085    this->expr_->determine_type_no_context();
  2086  }
  2087  
  2088  // Check the types of an expression statement.  The only check we do
  2089  // is to possibly give an error about discarding the value of the
  2090  // expression.
  2091  
  2092  void
  2093  Expression_statement::do_check_types(Gogo*)
  2094  {
  2095    if (!this->is_ignored_)
  2096      this->expr_->discarding_value();
  2097  }
  2098  
  2099  // An expression statement is only a terminating statement if it is
  2100  // a call to panic.
  2101  
  2102  bool
  2103  Expression_statement::do_may_fall_through() const
  2104  {
  2105    const Call_expression* call = this->expr_->call_expression();
  2106    if (call != NULL)
  2107      {
  2108        const Expression* fn = call->fn();
  2109        // panic is still an unknown named object.
  2110        const Unknown_expression* ue = fn->unknown_expression();
  2111        if (ue != NULL)
  2112  	{
  2113  	  Named_object* no = ue->named_object();
  2114  
  2115            if (no->is_unknown())
  2116              no = no->unknown_value()->real_named_object();
  2117            if (no != NULL)
  2118              {
  2119                Function_type* fntype;
  2120                if (no->is_function())
  2121                  fntype = no->func_value()->type();
  2122                else if (no->is_function_declaration())
  2123                  fntype = no->func_declaration_value()->type();
  2124                else
  2125                  fntype = NULL;
  2126  
  2127                // The builtin function panic does not return.
  2128                if (fntype != NULL && fntype->is_builtin() && no->name() == "panic")
  2129                  return false;
  2130              }
  2131  	}
  2132      }
  2133    return true;
  2134  }
  2135  
  2136  // Export an expression statement.
  2137  
  2138  void
  2139  Expression_statement::do_export_statement(Export_function_body* efb)
  2140  {
  2141    this->expr_->export_expression(efb);
  2142  }
  2143  
  2144  // Convert to backend representation.
  2145  
  2146  Bstatement*
  2147  Expression_statement::do_get_backend(Translate_context* context)
  2148  {
  2149    Bexpression* bexpr = this->expr_->get_backend(context);
  2150    Bfunction* bfunction = context->function()->func_value()->get_decl();
  2151    return context->backend()->expression_statement(bfunction, bexpr);
  2152  }
  2153  
  2154  // Dump the AST representation for an expression statement
  2155  
  2156  void
  2157  Expression_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
  2158      const
  2159  {
  2160    ast_dump_context->print_indent();
  2161    ast_dump_context->dump_expression(expr_);
  2162    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  2163  }
  2164  
  2165  // Make an expression statement from an Expression.
  2166  
  2167  Statement*
  2168  Statement::make_statement(Expression* expr, bool is_ignored)
  2169  {
  2170    return new Expression_statement(expr, is_ignored);
  2171  }
  2172  
  2173  // Export data for a block.
  2174  
  2175  void
  2176  Block_statement::do_export_statement(Export_function_body* efb)
  2177  {
  2178    Block_statement::export_block(efb, this->block_,
  2179  				this->is_lowered_for_statement_);
  2180  }
  2181  
  2182  void
  2183  Block_statement::export_block(Export_function_body* efb, Block* block,
  2184  			      bool is_lowered_for_statement)
  2185  {
  2186    // We are already indented to the right position.
  2187    char buf[50];
  2188    efb->write_c_string("{");
  2189    if (is_lowered_for_statement)
  2190      efb->write_c_string(" /*for*/");
  2191    snprintf(buf, sizeof buf, " //%d\n",
  2192  	   Linemap::location_to_line(block->start_location()));
  2193    efb->write_c_string(buf);
  2194  
  2195    block->export_block(efb);
  2196    // The indentation is correct for the statements in the block, so
  2197    // subtract one for the closing curly brace.
  2198    efb->decrement_indent();
  2199    efb->indent();
  2200    efb->write_c_string("}");
  2201    // Increment back to the value the caller thinks it has.
  2202    efb->increment_indent();
  2203  }
  2204  
  2205  // Import a block statement, returning the block.
  2206  
  2207  Block*
  2208  Block_statement::do_import(Import_function_body* ifb, Location loc,
  2209  			   bool* is_lowered_for_statement)
  2210  {
  2211    go_assert(ifb->match_c_string("{"));
  2212    *is_lowered_for_statement = false;
  2213    if (ifb->match_c_string(" /*for*/"))
  2214      {
  2215        ifb->advance(8);
  2216        *is_lowered_for_statement = true;
  2217      }
  2218    size_t nl = ifb->body().find('\n', ifb->off());
  2219    if (nl == std::string::npos)
  2220      {
  2221        if (!ifb->saw_error())
  2222  	go_error_at(ifb->location(),
  2223  		    "import error: no newline after %<{%> at %lu",
  2224  		    static_cast<unsigned long>(ifb->off()));
  2225        ifb->set_saw_error();
  2226        return NULL;
  2227      }
  2228    ifb->set_off(nl + 1);
  2229    ifb->increment_indent();
  2230    Block* block = new Block(ifb->block(), loc);
  2231    ifb->begin_block(block);
  2232    bool ok = Block::import_block(block, ifb, loc);
  2233    ifb->finish_block();
  2234    ifb->decrement_indent();
  2235    if (!ok)
  2236      return NULL;
  2237    return block;
  2238  }
  2239  
  2240  // Convert a block to the backend representation of a statement.
  2241  
  2242  Bstatement*
  2243  Block_statement::do_get_backend(Translate_context* context)
  2244  {
  2245    Bblock* bblock = this->block_->get_backend(context);
  2246    return context->backend()->block_statement(bblock);
  2247  }
  2248  
  2249  // Dump the AST for a block statement
  2250  
  2251  void
  2252  Block_statement::do_dump_statement(Ast_dump_context*) const
  2253  {
  2254    // block statement braces are dumped when traversing.
  2255  }
  2256  
  2257  // Make a block statement.
  2258  
  2259  Block_statement*
  2260  Statement::make_block_statement(Block* block, Location location)
  2261  {
  2262    return new Block_statement(block, location);
  2263  }
  2264  
  2265  // An increment or decrement statement.
  2266  
  2267  class Inc_dec_statement : public Statement
  2268  {
  2269   public:
  2270    Inc_dec_statement(bool is_inc, Expression* expr)
  2271      : Statement(STATEMENT_INCDEC, expr->location()),
  2272        expr_(expr), is_inc_(is_inc)
  2273    { }
  2274  
  2275   protected:
  2276    int
  2277    do_traverse(Traverse* traverse)
  2278    { return this->traverse_expression(traverse, &this->expr_); }
  2279  
  2280    bool
  2281    do_traverse_assignments(Traverse_assignments*)
  2282    { go_unreachable(); }
  2283  
  2284    Statement*
  2285    do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
  2286  
  2287    Bstatement*
  2288    do_get_backend(Translate_context*)
  2289    { go_unreachable(); }
  2290  
  2291    void
  2292    do_dump_statement(Ast_dump_context*) const;
  2293  
  2294   private:
  2295    // The l-value to increment or decrement.
  2296    Expression* expr_;
  2297    // Whether to increment or decrement.
  2298    bool is_inc_;
  2299  };
  2300  
  2301  // Lower to += or -=.
  2302  
  2303  Statement*
  2304  Inc_dec_statement::do_lower(Gogo*, Named_object*, Block*, Statement_inserter*)
  2305  {
  2306    Location loc = this->location();
  2307    if (!this->expr_->type()->is_numeric_type())
  2308      {
  2309        this->report_error("increment or decrement of non-numeric type");
  2310        return Statement::make_error_statement(loc);
  2311      }
  2312    Expression* oexpr = Expression::make_integer_ul(1, this->expr_->type(), loc);
  2313    Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ;
  2314    return Statement::make_assignment_operation(op, this->expr_, oexpr, loc);
  2315  }
  2316  
  2317  // Dump the AST representation for a inc/dec statement.
  2318  
  2319  void
  2320  Inc_dec_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
  2321  {
  2322    ast_dump_context->print_indent();
  2323    ast_dump_context->dump_expression(expr_);
  2324    ast_dump_context->ostream() << (is_inc_? "++": "--") << dsuffix(location()) << std::endl;
  2325  }
  2326  
  2327  // Make an increment statement.
  2328  
  2329  Statement*
  2330  Statement::make_inc_statement(Expression* expr)
  2331  {
  2332    return new Inc_dec_statement(true, expr);
  2333  }
  2334  
  2335  // Make a decrement statement.
  2336  
  2337  Statement*
  2338  Statement::make_dec_statement(Expression* expr)
  2339  {
  2340    return new Inc_dec_statement(false, expr);
  2341  }
  2342  
  2343  // Class Thunk_statement.  This is the base class for go and defer
  2344  // statements.
  2345  
  2346  // Constructor.
  2347  
  2348  Thunk_statement::Thunk_statement(Statement_classification classification,
  2349  				 Call_expression* call,
  2350  				 Location location)
  2351      : Statement(classification, location),
  2352        call_(call), struct_type_(NULL)
  2353  {
  2354  }
  2355  
  2356  // Return whether this is a simple statement which does not require a
  2357  // thunk.
  2358  
  2359  bool
  2360  Thunk_statement::is_simple(Function_type* fntype) const
  2361  {
  2362    // We need a thunk to call a method, or to pass a variable number of
  2363    // arguments.
  2364    if (fntype->is_method() || fntype->is_varargs())
  2365      return false;
  2366  
  2367    // A defer statement requires a thunk to set up for whether the
  2368    // function can call recover.
  2369    if (this->classification() == STATEMENT_DEFER)
  2370      return false;
  2371  
  2372    // We can only permit a single parameter of pointer type.
  2373    const Typed_identifier_list* parameters = fntype->parameters();
  2374    if (parameters != NULL
  2375        && (parameters->size() > 1
  2376  	  || (parameters->size() == 1
  2377  	      && parameters->begin()->type()->points_to() == NULL)))
  2378      return false;
  2379  
  2380    // If the function returns multiple values, or returns a type other
  2381    // than integer, floating point, or pointer, then it may get a
  2382    // hidden first parameter, in which case we need the more
  2383    // complicated approach.  This is true even though we are going to
  2384    // ignore the return value.
  2385    const Typed_identifier_list* results = fntype->results();
  2386    if (results != NULL
  2387        && (results->size() > 1
  2388  	  || (results->size() == 1
  2389  	      && !results->begin()->type()->is_basic_type()
  2390  	      && results->begin()->type()->points_to() == NULL)))
  2391      return false;
  2392  
  2393    // If this calls something that is not a simple function, then we
  2394    // need a thunk.
  2395    Expression* fn = this->call_->call_expression()->fn();
  2396    if (fn->func_expression() == NULL)
  2397      return false;
  2398  
  2399    // If the function uses a closure, then we need a thunk.  FIXME: We
  2400    // could accept a zero argument function with a closure.
  2401    if (fn->func_expression()->closure() != NULL)
  2402      return false;
  2403  
  2404    return true;
  2405  }
  2406  
  2407  // Traverse a thunk statement.
  2408  
  2409  int
  2410  Thunk_statement::do_traverse(Traverse* traverse)
  2411  {
  2412    return this->traverse_expression(traverse, &this->call_);
  2413  }
  2414  
  2415  // We implement traverse_assignment for a thunk statement because it
  2416  // effectively copies the function call.
  2417  
  2418  bool
  2419  Thunk_statement::do_traverse_assignments(Traverse_assignments* tassign)
  2420  {
  2421    Expression* fn = this->call_->call_expression()->fn();
  2422    Expression* fn2 = fn;
  2423    tassign->value(&fn2, true, false);
  2424    return true;
  2425  }
  2426  
  2427  // Determine types in a thunk statement.
  2428  
  2429  void
  2430  Thunk_statement::do_determine_types()
  2431  {
  2432    this->call_->determine_type_no_context();
  2433  
  2434    // Now that we know the types of the call, build the struct used to
  2435    // pass parameters.
  2436    Call_expression* ce = this->call_->call_expression();
  2437    if (ce == NULL)
  2438      return;
  2439    Function_type* fntype = ce->get_function_type();
  2440    if (fntype != NULL && !this->is_simple(fntype))
  2441      this->struct_type_ = this->build_struct(fntype);
  2442  }
  2443  
  2444  // Check types in a thunk statement.
  2445  
  2446  void
  2447  Thunk_statement::do_check_types(Gogo*)
  2448  {
  2449    if (!this->call_->discarding_value())
  2450      return;
  2451    Call_expression* ce = this->call_->call_expression();
  2452    if (ce == NULL)
  2453      {
  2454        if (!this->call_->is_error_expression())
  2455  	this->report_error("expected call expression");
  2456        return;
  2457      }
  2458  }
  2459  
  2460  // The Traverse class used to find and simplify thunk statements.
  2461  
  2462  class Simplify_thunk_traverse : public Traverse
  2463  {
  2464   public:
  2465    Simplify_thunk_traverse(Gogo* gogo)
  2466      : Traverse(traverse_functions | traverse_blocks),
  2467        gogo_(gogo), function_(NULL)
  2468    { }
  2469  
  2470    int
  2471    function(Named_object*);
  2472  
  2473    int
  2474    block(Block*);
  2475  
  2476   private:
  2477    // General IR.
  2478    Gogo* gogo_;
  2479    // The function we are traversing.
  2480    Named_object* function_;
  2481  };
  2482  
  2483  // Keep track of the current function while looking for thunks.
  2484  
  2485  int
  2486  Simplify_thunk_traverse::function(Named_object* no)
  2487  {
  2488    go_assert(this->function_ == NULL);
  2489    this->function_ = no;
  2490    int t = no->func_value()->traverse(this);
  2491    this->function_ = NULL;
  2492    if (t == TRAVERSE_EXIT)
  2493      return t;
  2494    return TRAVERSE_SKIP_COMPONENTS;
  2495  }
  2496  
  2497  // Look for thunks in a block.
  2498  
  2499  int
  2500  Simplify_thunk_traverse::block(Block* b)
  2501  {
  2502    // The parser ensures that thunk statements always appear at the end
  2503    // of a block.
  2504    if (b->statements()->size() < 1)
  2505      return TRAVERSE_CONTINUE;
  2506    Thunk_statement* stat = b->statements()->back()->thunk_statement();
  2507    if (stat == NULL)
  2508      return TRAVERSE_CONTINUE;
  2509    if (stat->simplify_statement(this->gogo_, this->function_, b))
  2510      return TRAVERSE_SKIP_COMPONENTS;
  2511    return TRAVERSE_CONTINUE;
  2512  }
  2513  
  2514  // Simplify all thunk statements.
  2515  
  2516  void
  2517  Gogo::simplify_thunk_statements()
  2518  {
  2519    Simplify_thunk_traverse thunk_traverse(this);
  2520    this->traverse(&thunk_traverse);
  2521  }
  2522  
  2523  // Return true if the thunk function is a constant, which means that
  2524  // it does not need to be passed to the thunk routine.
  2525  
  2526  bool
  2527  Thunk_statement::is_constant_function() const
  2528  {
  2529    Call_expression* ce = this->call_->call_expression();
  2530    Function_type* fntype = ce->get_function_type();
  2531    if (fntype == NULL)
  2532      {
  2533        go_assert(saw_errors());
  2534        return false;
  2535      }
  2536    if (fntype->is_builtin())
  2537      return true;
  2538    Expression* fn = ce->fn();
  2539    if (fn->func_expression() != NULL)
  2540      return fn->func_expression()->closure() == NULL;
  2541    if (fn->interface_field_reference_expression() != NULL)
  2542      return true;
  2543    if (fn->bound_method_expression() != NULL)
  2544      return true;
  2545    return false;
  2546  }
  2547  
  2548  // Simplify complex thunk statements into simple ones.  A complicated
  2549  // thunk statement is one which takes anything other than zero
  2550  // parameters or a single pointer parameter.  We rewrite it into code
  2551  // which allocates a struct, stores the parameter values into the
  2552  // struct, and does a simple go or defer statement which passes the
  2553  // struct to a thunk.  The thunk does the real call.
  2554  
  2555  bool
  2556  Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
  2557  				    Block* block)
  2558  {
  2559    if (this->classification() == STATEMENT_ERROR)
  2560      return false;
  2561    if (this->call_->is_error_expression())
  2562      return false;
  2563  
  2564    if (this->classification() == STATEMENT_DEFER)
  2565      {
  2566        // Make sure that the defer stack exists for the function.  We
  2567        // will use when converting this statement to the backend
  2568        // representation, but we want it to exist when we start
  2569        // converting the function.
  2570        function->func_value()->defer_stack(this->location());
  2571      }
  2572  
  2573    Call_expression* ce = this->call_->call_expression();
  2574    Function_type* fntype = ce->get_function_type();
  2575    if (fntype == NULL)
  2576      {
  2577        go_assert(saw_errors());
  2578        this->set_is_error();
  2579        return false;
  2580      }
  2581    if (this->is_simple(fntype))
  2582      return false;
  2583  
  2584    Expression* fn = ce->fn();
  2585    Interface_field_reference_expression* interface_method =
  2586      fn->interface_field_reference_expression();
  2587    Bound_method_expression* bme = fn->bound_method_expression();
  2588  
  2589    Location location = this->location();
  2590  
  2591    bool is_constant_function = this->is_constant_function();
  2592    Temporary_statement* fn_temp = NULL;
  2593    if (!is_constant_function)
  2594      {
  2595        fn_temp = Statement::make_temporary(NULL, fn, location);
  2596        block->insert_statement_before(block->statements()->size() - 1, fn_temp);
  2597        fn = Expression::make_temporary_reference(fn_temp, location);
  2598      }
  2599  
  2600    std::string thunk_name = gogo->thunk_name();
  2601  
  2602    // Build the thunk.
  2603    this->build_thunk(gogo, thunk_name);
  2604  
  2605    // Generate code to call the thunk.
  2606  
  2607    // Get the values to store into the struct which is the single
  2608    // argument to the thunk.
  2609  
  2610    Expression_list* vals = new Expression_list();
  2611    if (!is_constant_function)
  2612      vals->push_back(fn);
  2613  
  2614    if (interface_method != NULL)
  2615      vals->push_back(interface_method->expr());
  2616    if (bme != NULL)
  2617      vals->push_back(bme->first_argument());
  2618  
  2619    if (ce->args() != NULL)
  2620      {
  2621        for (Expression_list::const_iterator p = ce->args()->begin();
  2622  	   p != ce->args()->end();
  2623  	   ++p)
  2624  	{
  2625  	  if ((*p)->is_constant())
  2626  	    continue;
  2627  	  vals->push_back(*p);
  2628  	}
  2629      }
  2630  
  2631    // Build the struct.
  2632    Expression* constructor =
  2633      Expression::make_struct_composite_literal(this->struct_type_, vals,
  2634  					      location);
  2635  
  2636    // Allocate the initialized struct on the heap.
  2637    constructor = Expression::make_heap_expression(constructor, location);
  2638    if ((Node::make_node(this)->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
  2639      constructor->heap_expression()->set_allocate_on_stack();
  2640  
  2641    // Throw an error if the function is nil.  This is so that for `go
  2642    // nil` we get a backtrace from the go statement, rather than a
  2643    // useless backtrace from the brand new goroutine.
  2644    Expression* param = constructor;
  2645    if (!is_constant_function && this->classification() == STATEMENT_GO)
  2646      {
  2647        fn = Expression::make_temporary_reference(fn_temp, location);
  2648        Expression* nil = Expression::make_nil(location);
  2649        Expression* isnil = Expression::make_binary(OPERATOR_EQEQ, fn, nil,
  2650  						  location);
  2651        Expression* crash = Runtime::make_call(Runtime::PANIC_GO_NIL,
  2652  					     location, 0);
  2653        crash = Expression::make_conditional(isnil, crash,
  2654  					   Expression::make_nil(location),
  2655  					   location);
  2656        param = Expression::make_compound(crash, constructor, location);
  2657      }
  2658  
  2659    // Look up the thunk.
  2660    Named_object* named_thunk = gogo->lookup(thunk_name, NULL);
  2661    go_assert(named_thunk != NULL && named_thunk->is_function());
  2662  
  2663    // Build the call.
  2664    Expression* func = Expression::make_func_reference(named_thunk, NULL,
  2665  						     location);
  2666    Expression_list* params = new Expression_list();
  2667    params->push_back(param);
  2668    Call_expression* call = Expression::make_call(func, params, false, location);
  2669  
  2670    // Build the simple go or defer statement.
  2671    Statement* s;
  2672    if (this->classification() == STATEMENT_GO)
  2673      s = Statement::make_go_statement(call, location);
  2674    else if (this->classification() == STATEMENT_DEFER)
  2675      {
  2676        s = Statement::make_defer_statement(call, location);
  2677        if ((Node::make_node(this)->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
  2678          s->defer_statement()->set_on_stack();
  2679      }
  2680    else
  2681      go_unreachable();
  2682  
  2683    // The current block should end with the go statement.
  2684    go_assert(block->statements()->size() >= 1);
  2685    go_assert(block->statements()->back() == this);
  2686    block->replace_statement(block->statements()->size() - 1, s);
  2687  
  2688    // We already ran the determine_types pass, so we need to run it now
  2689    // for the new statement.
  2690    s->determine_types();
  2691  
  2692    // Sanity check.
  2693    gogo->check_types_in_block(block);
  2694  
  2695    // Return true to tell the block not to keep looking at statements.
  2696    return true;
  2697  }
  2698  
  2699  // Set the name to use for thunk parameter N.
  2700  
  2701  void
  2702  Thunk_statement::thunk_field_param(int n, char* buf, size_t buflen)
  2703  {
  2704    snprintf(buf, buflen, "a%d", n);
  2705  }
  2706  
  2707  // Build a new struct type to hold the parameters for a complicated
  2708  // thunk statement.  FNTYPE is the type of the function call.
  2709  
  2710  Struct_type*
  2711  Thunk_statement::build_struct(Function_type* fntype)
  2712  {
  2713    Location location = this->location();
  2714  
  2715    Struct_field_list* fields = new Struct_field_list();
  2716  
  2717    Call_expression* ce = this->call_->call_expression();
  2718    Expression* fn = ce->fn();
  2719  
  2720    if (!this->is_constant_function())
  2721      {
  2722        // The function to call.
  2723        fields->push_back(Struct_field(Typed_identifier("fn", fntype,
  2724  						      location)));
  2725      }
  2726  
  2727    // If this thunk statement calls a method on an interface, we pass
  2728    // the interface object to the thunk.
  2729    Interface_field_reference_expression* interface_method =
  2730      fn->interface_field_reference_expression();
  2731    if (interface_method != NULL)
  2732      {
  2733        Typed_identifier tid("object", interface_method->expr()->type(),
  2734  			   location);
  2735        fields->push_back(Struct_field(tid));
  2736      }
  2737  
  2738    // If this thunk statement calls a bound method expression, as in
  2739    // "go s.m()", we pass the bound method argument to the thunk,
  2740    // to ensure that we make a copy of it if needed.
  2741    Bound_method_expression* bme = fn->bound_method_expression();
  2742    if (bme != NULL)
  2743      {
  2744        Typed_identifier tid("object", bme->first_argument()->type(), location);
  2745        fields->push_back(Struct_field(tid));
  2746      }
  2747  
  2748    // The predeclared recover function has no argument.  However, we
  2749    // add an argument when building recover thunks.  Handle that here.
  2750    if (ce->is_recover_call())
  2751      {
  2752        fields->push_back(Struct_field(Typed_identifier("can_recover",
  2753  						      Type::lookup_bool_type(),
  2754  						      location)));
  2755      }
  2756  
  2757    const Expression_list* args = ce->args();
  2758    if (args != NULL)
  2759      {
  2760        int i = 0;
  2761        for (Expression_list::const_iterator p = args->begin();
  2762  	   p != args->end();
  2763  	   ++p, ++i)
  2764  	{
  2765  	  if ((*p)->is_constant())
  2766  	    continue;
  2767  
  2768  	  char buf[50];
  2769  	  this->thunk_field_param(i, buf, sizeof buf);
  2770  	  fields->push_back(Struct_field(Typed_identifier(buf, (*p)->type(),
  2771  							  location)));
  2772  	}
  2773      }
  2774  
  2775    Struct_type *st = Type::make_struct_type(fields, location);
  2776    st->set_is_struct_incomparable();
  2777    return st;
  2778  }
  2779  
  2780  // Build the thunk we are going to call.  This is a brand new, albeit
  2781  // artificial, function.
  2782  
  2783  void
  2784  Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
  2785  {
  2786    Location location = this->location();
  2787  
  2788    Call_expression* ce = this->call_->call_expression();
  2789  
  2790    bool may_call_recover = false;
  2791    if (this->classification() == STATEMENT_DEFER)
  2792      {
  2793        Func_expression* fn = ce->fn()->func_expression();
  2794        if (fn == NULL)
  2795  	may_call_recover = true;
  2796        else
  2797  	{
  2798  	  const Named_object* no = fn->named_object();
  2799  	  if (!no->is_function())
  2800  	    may_call_recover = true;
  2801  	  else
  2802  	    may_call_recover = no->func_value()->calls_recover();
  2803  	}
  2804      }
  2805  
  2806    // Build the type of the thunk.  The thunk takes a single parameter,
  2807    // which is a pointer to the special structure we build.
  2808    const char* const parameter_name = "__go_thunk_parameter";
  2809    Typed_identifier_list* thunk_parameters = new Typed_identifier_list();
  2810    Type* pointer_to_struct_type = Type::make_pointer_type(this->struct_type_);
  2811    thunk_parameters->push_back(Typed_identifier(parameter_name,
  2812  					       pointer_to_struct_type,
  2813  					       location));
  2814  
  2815    Typed_identifier_list* thunk_results = NULL;
  2816    if (may_call_recover)
  2817      {
  2818        // When deferring a function which may call recover, add a
  2819        // return value, to disable tail call optimizations which will
  2820        // break the way we check whether recover is permitted.
  2821        thunk_results = new Typed_identifier_list();
  2822        thunk_results->push_back(Typed_identifier("", Type::lookup_bool_type(),
  2823  						location));
  2824      }
  2825  
  2826    Function_type* thunk_type = Type::make_function_type(NULL, thunk_parameters,
  2827  						       thunk_results,
  2828  						       location);
  2829  
  2830    // Start building the thunk.
  2831    Named_object* function = gogo->start_function(thunk_name, thunk_type, true,
  2832  						location);
  2833  
  2834    gogo->start_block(location);
  2835  
  2836    // For a defer statement, start with a call to
  2837    // __go_set_defer_retaddr.  */
  2838    Label* retaddr_label = NULL;
  2839    if (may_call_recover)
  2840      {
  2841        retaddr_label = gogo->add_label_reference("retaddr", location, false);
  2842        Expression* arg = Expression::make_label_addr(retaddr_label, location);
  2843        Expression* call = Runtime::make_call(Runtime::SETDEFERRETADDR,
  2844  					    location, 1, arg);
  2845  
  2846        // This is a hack to prevent the middle-end from deleting the
  2847        // label.
  2848        gogo->start_block(location);
  2849        gogo->add_statement(Statement::make_goto_statement(retaddr_label,
  2850  							 location));
  2851        Block* then_block = gogo->finish_block(location);
  2852        then_block->determine_types();
  2853  
  2854        Statement* s = Statement::make_if_statement(call, then_block, NULL,
  2855  						  location);
  2856        s->determine_types();
  2857        gogo->add_statement(s);
  2858  
  2859        function->func_value()->set_calls_defer_retaddr();
  2860      }
  2861  
  2862    // Get a reference to the parameter.
  2863    Named_object* named_parameter = gogo->lookup(parameter_name, NULL);
  2864    go_assert(named_parameter != NULL && named_parameter->is_variable());
  2865  
  2866    // Build the call.  Note that the field names are the same as the
  2867    // ones used in build_struct.
  2868    Expression* thunk_parameter = Expression::make_var_reference(named_parameter,
  2869  							       location);
  2870    thunk_parameter =
  2871        Expression::make_dereference(thunk_parameter,
  2872                                     Expression::NIL_CHECK_NOT_NEEDED,
  2873                                     location);
  2874  
  2875    Interface_field_reference_expression* interface_method =
  2876      ce->fn()->interface_field_reference_expression();
  2877    Bound_method_expression* bme = ce->fn()->bound_method_expression();
  2878  
  2879    Expression* func_to_call;
  2880    unsigned int next_index;
  2881    if (this->is_constant_function())
  2882      {
  2883        func_to_call = ce->fn();
  2884        next_index = 0;
  2885      }
  2886    else
  2887      {
  2888        func_to_call = Expression::make_field_reference(thunk_parameter,
  2889  						      0, location);
  2890        next_index = 1;
  2891      }
  2892  
  2893    if (interface_method != NULL)
  2894      {
  2895        // The main program passes the interface object.
  2896        go_assert(next_index == 0);
  2897        Expression* r = Expression::make_field_reference(thunk_parameter, 0,
  2898  						       location);
  2899        const std::string& name(interface_method->name());
  2900        func_to_call = Expression::make_interface_field_reference(r, name,
  2901  								location);
  2902        next_index = 1;
  2903      }
  2904  
  2905    if (bme != NULL)
  2906      {
  2907        // This is a call to a method.
  2908        go_assert(next_index == 0);
  2909        Expression* r = Expression::make_field_reference(thunk_parameter, 0,
  2910  						       location);
  2911        func_to_call = Expression::make_bound_method(r, bme->method(),
  2912  						   bme->function(), location);
  2913        next_index = 1;
  2914      }
  2915  
  2916    Expression_list* call_params = new Expression_list();
  2917    const Struct_field_list* fields = this->struct_type_->fields();
  2918    Struct_field_list::const_iterator p = fields->begin();
  2919    for (unsigned int i = 0; i < next_index; ++i)
  2920      ++p;
  2921    bool is_recover_call = ce->is_recover_call();
  2922    Expression* recover_arg = NULL;
  2923  
  2924    const Expression_list* args = ce->args();
  2925    if (args != NULL)
  2926      {
  2927        for (Expression_list::const_iterator arg = args->begin();
  2928  	   arg != args->end();
  2929  	   ++arg)
  2930  	{
  2931  	  Expression* param;
  2932  	  if ((*arg)->is_constant())
  2933  	    param = *arg;
  2934  	  else
  2935  	    {
  2936  	      Expression* thunk_param =
  2937  		Expression::make_var_reference(named_parameter, location);
  2938               thunk_param =
  2939                   Expression::make_dereference(thunk_param,
  2940                                                Expression::NIL_CHECK_NOT_NEEDED,
  2941                                                location);
  2942  	      param = Expression::make_field_reference(thunk_param,
  2943  						       next_index,
  2944  						       location);
  2945  	      ++next_index;
  2946  	    }
  2947  
  2948  	  if (!is_recover_call)
  2949  	    call_params->push_back(param);
  2950  	  else
  2951  	    {
  2952  	      go_assert(call_params->empty());
  2953  	      recover_arg = param;
  2954  	    }
  2955  	}
  2956      }
  2957  
  2958    if (call_params->empty())
  2959      {
  2960        delete call_params;
  2961        call_params = NULL;
  2962      }
  2963  
  2964    Call_expression* call = Expression::make_call(func_to_call, call_params,
  2965  						false, location);
  2966  
  2967    // This call expression was already lowered before entering the
  2968    // thunk statement.  Don't try to lower varargs again, as that will
  2969    // cause confusion for, e.g., method calls which already have a
  2970    // receiver parameter.
  2971    call->set_varargs_are_lowered();
  2972  
  2973    Statement* call_statement = Statement::make_statement(call, true);
  2974  
  2975    gogo->add_statement(call_statement);
  2976  
  2977    // If this is a defer statement, the label comes immediately after
  2978    // the call.
  2979    if (may_call_recover)
  2980      {
  2981        gogo->add_label_definition("retaddr", location);
  2982  
  2983        Expression_list* vals = new Expression_list();
  2984        vals->push_back(Expression::make_boolean(false, location));
  2985        gogo->add_statement(Statement::make_return_statement(vals, location));
  2986      }
  2987  
  2988    Block* b = gogo->finish_block(location);
  2989  
  2990    gogo->add_block(b, location);
  2991  
  2992    gogo->lower_block(function, b);
  2993  
  2994    // We already ran the determine_types pass, so we need to run it
  2995    // just for the call statement now.  The other types are known.
  2996    call_statement->determine_types();
  2997  
  2998    gogo->add_conversions_in_block(b);
  2999  
  3000    if (may_call_recover
  3001        || recover_arg != NULL
  3002        || this->classification() == STATEMENT_GO)
  3003      {
  3004        // Dig up the call expression, which may have been changed
  3005        // during lowering.
  3006        go_assert(call_statement->classification() == STATEMENT_EXPRESSION);
  3007        Expression_statement* es =
  3008  	static_cast<Expression_statement*>(call_statement);
  3009        ce = es->expr()->call_expression();
  3010        if (ce == NULL)
  3011  	go_assert(saw_errors());
  3012        else
  3013  	{
  3014  	  if (may_call_recover)
  3015  	    ce->set_is_deferred();
  3016  	  if (this->classification() == STATEMENT_GO)
  3017  	    ce->set_is_concurrent();
  3018  	  if (recover_arg != NULL)
  3019  	    ce->set_recover_arg(recover_arg);
  3020  	}
  3021      }
  3022  
  3023    gogo->flatten_block(function, b);
  3024  
  3025    // That is all the thunk has to do.
  3026    gogo->finish_function(location);
  3027  }
  3028  
  3029  // Get the function and argument expressions.
  3030  
  3031  bool
  3032  Thunk_statement::get_fn_and_arg(Expression** pfn, Expression** parg)
  3033  {
  3034    if (this->call_->is_error_expression())
  3035      return false;
  3036  
  3037    Call_expression* ce = this->call_->call_expression();
  3038  
  3039    Expression* fn = ce->fn();
  3040    Func_expression* fe = fn->func_expression();
  3041    go_assert(fe != NULL);
  3042    *pfn = Expression::make_func_code_reference(fe->named_object(),
  3043  					      fe->location());
  3044  
  3045    const Expression_list* args = ce->args();
  3046    if (args == NULL || args->empty())
  3047      *parg = Expression::make_nil(this->location());
  3048    else
  3049      {
  3050        go_assert(args->size() == 1);
  3051        *parg = args->front();
  3052      }
  3053  
  3054    return true;
  3055  }
  3056  
  3057  // Class Go_statement.
  3058  
  3059  Bstatement*
  3060  Go_statement::do_get_backend(Translate_context* context)
  3061  {
  3062    Expression* fn;
  3063    Expression* arg;
  3064    if (!this->get_fn_and_arg(&fn, &arg))
  3065      return context->backend()->error_statement();
  3066  
  3067    Expression* call = Runtime::make_call(Runtime::GO, this->location(), 2,
  3068  					fn, arg);
  3069    Bexpression* bcall = call->get_backend(context);
  3070    Bfunction* bfunction = context->function()->func_value()->get_decl();
  3071    return context->backend()->expression_statement(bfunction, bcall);
  3072  }
  3073  
  3074  // Dump the AST representation for go statement.
  3075  
  3076  void
  3077  Go_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
  3078  {
  3079    ast_dump_context->print_indent();
  3080    ast_dump_context->ostream() << "go ";
  3081    ast_dump_context->dump_expression(this->call());
  3082    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  3083  }
  3084  
  3085  // Make a go statement.
  3086  
  3087  Statement*
  3088  Statement::make_go_statement(Call_expression* call, Location location)
  3089  {
  3090    return new Go_statement(call, location);
  3091  }
  3092  
  3093  // Class Defer_statement.
  3094  
  3095  Bstatement*
  3096  Defer_statement::do_get_backend(Translate_context* context)
  3097  {
  3098    Expression* fn;
  3099    Expression* arg;
  3100    if (!this->get_fn_and_arg(&fn, &arg))
  3101      return context->backend()->error_statement();
  3102  
  3103    Location loc = this->location();
  3104    Expression* ds = context->function()->func_value()->defer_stack(loc);
  3105  
  3106    Expression* call;
  3107    if (this->on_stack_)
  3108      {
  3109        if (context->gogo()->debug_optimization())
  3110          go_debug(loc, "stack allocated defer");
  3111  
  3112        Type* defer_type = Defer_statement::defer_struct_type();
  3113        Expression* defer = Expression::make_allocation(defer_type, loc);
  3114        defer->allocation_expression()->set_allocate_on_stack();
  3115        defer->allocation_expression()->set_no_zero();
  3116        call = Runtime::make_call(Runtime::DEFERPROCSTACK, loc, 4,
  3117                                  defer, ds, fn, arg);
  3118      }
  3119    else
  3120      call = Runtime::make_call(Runtime::DEFERPROC, loc, 3,
  3121                                ds, fn, arg);
  3122    Bexpression* bcall = call->get_backend(context);
  3123    Bfunction* bfunction = context->function()->func_value()->get_decl();
  3124    return context->backend()->expression_statement(bfunction, bcall);
  3125  }
  3126  
  3127  Type*
  3128  Defer_statement::defer_struct_type()
  3129  {
  3130    Type* ptr_type = Type::make_pointer_type(Type::make_void_type());
  3131    Type* uintptr_type = Type::lookup_integer_type("uintptr");
  3132    Type* bool_type = Type::make_boolean_type();
  3133    return Type::make_builtin_struct_type(9,
  3134                                          "link", ptr_type,
  3135                                          "frame", ptr_type,
  3136                                          "panicStack", ptr_type,
  3137                                          "_panic", ptr_type,
  3138                                          "pfn", uintptr_type,
  3139                                          "arg", ptr_type,
  3140                                          "retaddr", uintptr_type,
  3141                                          "makefunccanrecover", bool_type,
  3142                                          "heap", bool_type);
  3143  }
  3144  
  3145  // Dump the AST representation for defer statement.
  3146  
  3147  void
  3148  Defer_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
  3149  {
  3150    ast_dump_context->print_indent();
  3151    ast_dump_context->ostream() << "defer ";
  3152    ast_dump_context->dump_expression(this->call());
  3153    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  3154  }
  3155  
  3156  // Make a defer statement.
  3157  
  3158  Statement*
  3159  Statement::make_defer_statement(Call_expression* call,
  3160  				Location location)
  3161  {
  3162    return new Defer_statement(call, location);
  3163  }
  3164  
  3165  // Class Return_statement.
  3166  
  3167  // Traverse assignments.  We treat each return value as a top level
  3168  // RHS in an expression.
  3169  
  3170  bool
  3171  Return_statement::do_traverse_assignments(Traverse_assignments* tassign)
  3172  {
  3173    Expression_list* vals = this->vals_;
  3174    if (vals != NULL)
  3175      {
  3176        for (Expression_list::iterator p = vals->begin();
  3177  	   p != vals->end();
  3178  	   ++p)
  3179  	tassign->value(&*p, true, true);
  3180      }
  3181    return true;
  3182  }
  3183  
  3184  // Lower a return statement.  If we are returning a function call
  3185  // which returns multiple values which match the current function,
  3186  // split up the call's results.  If the return statement lists
  3187  // explicit values, implement this statement by assigning the values
  3188  // to the result variables and change this statement to a naked
  3189  // return.  This lets panic/recover work correctly.
  3190  
  3191  Statement*
  3192  Return_statement::do_lower(Gogo*, Named_object* function, Block* enclosing,
  3193  			   Statement_inserter*)
  3194  {
  3195    if (this->is_lowered_)
  3196      return this;
  3197  
  3198    Expression_list* vals = this->vals_;
  3199    this->vals_ = NULL;
  3200    this->is_lowered_ = true;
  3201  
  3202    Location loc = this->location();
  3203  
  3204    size_t vals_count = vals == NULL ? 0 : vals->size();
  3205    Function::Results* results = function->func_value()->result_variables();
  3206    size_t results_count = results == NULL ? 0 : results->size();
  3207  
  3208    if (vals_count == 0)
  3209      {
  3210        if (results_count > 0 && !function->func_value()->results_are_named())
  3211  	{
  3212  	  this->report_error(_("not enough arguments to return"));
  3213  	  return this;
  3214  	}
  3215        return this;
  3216      }
  3217  
  3218    if (results_count == 0)
  3219      {
  3220        this->report_error(_("return with value in function "
  3221  			   "with no return type"));
  3222        return this;
  3223      }
  3224  
  3225    // If the current function has multiple return values, and we are
  3226    // returning a single call expression, split up the call expression.
  3227    if (results_count > 1
  3228        && vals->size() == 1
  3229        && vals->front()->call_expression() != NULL)
  3230      {
  3231        Call_expression* call = vals->front()->call_expression();
  3232        call->set_expected_result_count(results_count);
  3233        delete vals;
  3234        vals = new Expression_list;
  3235        for (size_t i = 0; i < results_count; ++i)
  3236  	vals->push_back(Expression::make_call_result(call, i));
  3237        vals_count = results_count;
  3238      }
  3239  
  3240    if (vals_count < results_count)
  3241      {
  3242        this->report_error(_("not enough arguments to return"));
  3243        return this;
  3244      }
  3245  
  3246    if (vals_count > results_count)
  3247      {
  3248        this->report_error(_("too many values in return statement"));
  3249        return this;
  3250      }
  3251  
  3252    Block* b = new Block(enclosing, loc);
  3253  
  3254    Expression_list* lhs = new Expression_list();
  3255    Expression_list* rhs = new Expression_list();
  3256  
  3257    Expression_list::const_iterator pe = vals->begin();
  3258    int i = 1;
  3259    for (Function::Results::const_iterator pr = results->begin();
  3260         pr != results->end();
  3261         ++pr, ++pe, ++i)
  3262      {
  3263        Named_object* rv = *pr;
  3264        Expression* e = *pe;
  3265  
  3266        // Check types now so that we give a good error message.  The
  3267        // result type is known.  We determine the expression type
  3268        // early.
  3269  
  3270        Type *rvtype = rv->result_var_value()->type();
  3271        Type_context type_context(rvtype, false);
  3272        e->determine_type(&type_context);
  3273  
  3274        std::string reason;
  3275        if (Type::are_assignable(rvtype, e->type(), &reason))
  3276  	{
  3277  	  Expression* ve = Expression::make_var_reference(rv, e->location());
  3278  	  lhs->push_back(ve);
  3279  	  rhs->push_back(e);
  3280  	}
  3281        else
  3282  	{
  3283  	  if (reason.empty())
  3284  	    go_error_at(e->location(),
  3285  			"incompatible type for return value %d", i);
  3286  	  else
  3287  	    go_error_at(e->location(),
  3288  			"incompatible type for return value %d (%s)",
  3289  			i, reason.c_str());
  3290  	}
  3291      }
  3292    go_assert(lhs->size() == rhs->size());
  3293  
  3294    if (lhs->empty())
  3295      ;
  3296    else if (lhs->size() == 1)
  3297      {
  3298        b->add_statement(Statement::make_assignment(lhs->front(), rhs->front(),
  3299  						  loc));
  3300        delete lhs;
  3301        delete rhs;
  3302      }
  3303    else
  3304      b->add_statement(Statement::make_tuple_assignment(lhs, rhs, loc));
  3305  
  3306    b->add_statement(this);
  3307  
  3308    delete vals;
  3309  
  3310    return Statement::make_block_statement(b, loc);
  3311  }
  3312  
  3313  // Convert a return statement to the backend representation.
  3314  
  3315  Bstatement*
  3316  Return_statement::do_get_backend(Translate_context* context)
  3317  {
  3318    Location loc = this->location();
  3319  
  3320    Function* function = context->function()->func_value();
  3321    Function::Results* results = function->result_variables();
  3322    std::vector<Bexpression*> retvals;
  3323    if (results != NULL && !results->empty())
  3324      {
  3325        retvals.reserve(results->size());
  3326        for (Function::Results::const_iterator p = results->begin();
  3327  	   p != results->end();
  3328  	   p++)
  3329  	{
  3330  	  Expression* vr = Expression::make_var_reference(*p, loc);
  3331  	  retvals.push_back(vr->get_backend(context));
  3332  	}
  3333      }
  3334  
  3335    return context->backend()->return_statement(function->get_decl(),
  3336  					      retvals, loc);
  3337  }
  3338  
  3339  // Export a return statement.  At this point all the expressions have
  3340  // been converted to assignments to the result variables, so this is
  3341  // simple.
  3342  
  3343  void
  3344  Return_statement::do_export_statement(Export_function_body* efb)
  3345  {
  3346    efb->write_c_string("return");
  3347  }
  3348  
  3349  // Dump the AST representation for a return statement.
  3350  
  3351  void
  3352  Return_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
  3353  {
  3354    ast_dump_context->print_indent();
  3355    ast_dump_context->ostream() << "return " ;
  3356    ast_dump_context->dump_expression_list(this->vals_);
  3357    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  3358  }
  3359  
  3360  // Make a return statement.
  3361  
  3362  Return_statement*
  3363  Statement::make_return_statement(Expression_list* vals,
  3364  				 Location location)
  3365  {
  3366    return new Return_statement(vals, location);
  3367  }
  3368  
  3369  // Make a statement that returns the result of a call expression.
  3370  
  3371  Statement*
  3372  Statement::make_return_from_call(Call_expression* call, Location location)
  3373  {
  3374    size_t rc = call->result_count();
  3375    if (rc == 0)
  3376      return Statement::make_statement(call, true);
  3377    else
  3378      {
  3379        Expression_list* vals = new Expression_list();
  3380        if (rc == 1)
  3381  	vals->push_back(call);
  3382        else
  3383  	{
  3384  	  for (size_t i = 0; i < rc; ++i)
  3385  	    vals->push_back(Expression::make_call_result(call, i));
  3386  	}
  3387        return Statement::make_return_statement(vals, location);
  3388      }
  3389  }
  3390  
  3391  // A break or continue statement.
  3392  
  3393  class Bc_statement : public Statement
  3394  {
  3395   public:
  3396    Bc_statement(bool is_break, Unnamed_label* label, Location location)
  3397      : Statement(STATEMENT_BREAK_OR_CONTINUE, location),
  3398        label_(label), is_break_(is_break)
  3399    { }
  3400  
  3401    bool
  3402    is_break() const
  3403    { return this->is_break_; }
  3404  
  3405   protected:
  3406    int
  3407    do_traverse(Traverse*)
  3408    { return TRAVERSE_CONTINUE; }
  3409  
  3410    bool
  3411    do_may_fall_through() const
  3412    { return false; }
  3413  
  3414    Bstatement*
  3415    do_get_backend(Translate_context* context)
  3416    { return this->label_->get_goto(context, this->location()); }
  3417  
  3418    void
  3419    do_dump_statement(Ast_dump_context*) const;
  3420  
  3421   private:
  3422    // The label that this branches to.
  3423    Unnamed_label* label_;
  3424    // True if this is "break", false if it is "continue".
  3425    bool is_break_;
  3426  };
  3427  
  3428  // Dump the AST representation for a break/continue statement
  3429  
  3430  void
  3431  Bc_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
  3432  {
  3433    ast_dump_context->print_indent();
  3434    ast_dump_context->ostream() << (this->is_break_ ? "break" : "continue");
  3435    if (this->label_ != NULL)
  3436      {
  3437        ast_dump_context->ostream() << " ";
  3438        ast_dump_context->dump_label_name(this->label_);
  3439      }
  3440    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  3441  }
  3442  
  3443  // Make a break statement.
  3444  
  3445  Statement*
  3446  Statement::make_break_statement(Unnamed_label* label, Location location)
  3447  {
  3448    return new Bc_statement(true, label, location);
  3449  }
  3450  
  3451  // Make a continue statement.
  3452  
  3453  Statement*
  3454  Statement::make_continue_statement(Unnamed_label* label,
  3455  				   Location location)
  3456  {
  3457    return new Bc_statement(false, label, location);
  3458  }
  3459  
  3460  // Class Goto_statement.
  3461  
  3462  int
  3463  Goto_statement::do_traverse(Traverse*)
  3464  {
  3465    return TRAVERSE_CONTINUE;
  3466  }
  3467  
  3468  // Check types for a label.  There aren't any types per se, but we use
  3469  // this to give an error if the label was never defined.
  3470  
  3471  void
  3472  Goto_statement::do_check_types(Gogo*)
  3473  {
  3474    if (!this->label_->is_defined())
  3475      {
  3476        go_error_at(this->location(), "reference to undefined label %qs",
  3477  		  Gogo::message_name(this->label_->name()).c_str());
  3478        this->set_is_error();
  3479      }
  3480  }
  3481  
  3482  // Convert the goto statement to the backend representation.
  3483  
  3484  Bstatement*
  3485  Goto_statement::do_get_backend(Translate_context* context)
  3486  {
  3487    Blabel* blabel = this->label_->get_backend_label(context);
  3488    return context->backend()->goto_statement(blabel, this->location());
  3489  }
  3490  
  3491  // Export a goto statement.
  3492  
  3493  void
  3494  Goto_statement::do_export_statement(Export_function_body *efb)
  3495  {
  3496    efb->write_c_string("goto ");
  3497    efb->write_string(this->label_->name());
  3498  }
  3499  
  3500  // Import a goto or goto unnamed statement.
  3501  
  3502  Statement*
  3503  Goto_statement::do_import(Import_function_body* ifb, Location loc)
  3504  {
  3505    ifb->require_c_string("goto ");
  3506    std::string id = ifb->read_identifier();
  3507    if (id[0] != '$')
  3508      {
  3509        Function* fn = ifb->function()->func_value();
  3510        Label* label = fn->add_label_reference(ifb->gogo(), id, loc, false);
  3511        return Statement::make_goto_statement(label, loc);
  3512      }
  3513    else
  3514      {
  3515        if (id[1] != 'l')
  3516  	{
  3517  	  if (!ifb->saw_error())
  3518  	    go_error_at(loc,
  3519  			("invalid export data for %qs: "
  3520  			 "bad unnamed label at %lu"),
  3521  			ifb->name().c_str(),
  3522  			static_cast<unsigned long>(ifb->off()));
  3523  	  ifb->set_saw_error();
  3524  	  return Statement::make_error_statement(loc);
  3525  	}
  3526        const char* p = id.c_str();
  3527        char* end;
  3528        long idx = strtol(p + 2, &end, 10);
  3529        if (*end != '\0' || idx > 0x7fffffff)
  3530  	{
  3531  	  if (!ifb->saw_error())
  3532  	    go_error_at(loc,
  3533  			("invalid export data for %qs: "
  3534  			 "bad unnamed label index at %lu"),
  3535  			ifb->name().c_str(),
  3536  			static_cast<unsigned long>(ifb->off()));
  3537  	  ifb->set_saw_error();
  3538  	  return Statement::make_error_statement(loc);
  3539  	}
  3540  
  3541        Unnamed_label* label = ifb->unnamed_label(idx, loc);
  3542        return Statement::make_goto_unnamed_statement(label, loc);
  3543      }
  3544  }
  3545  
  3546  // Dump the AST representation for a goto statement.
  3547  
  3548  void
  3549  Goto_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
  3550  {
  3551    ast_dump_context->print_indent();
  3552    ast_dump_context->ostream() << "goto " << this->label_->name() << dsuffix(location()) << std::endl;
  3553  }
  3554  
  3555  // Make a goto statement.
  3556  
  3557  Statement*
  3558  Statement::make_goto_statement(Label* label, Location location)
  3559  {
  3560    return new Goto_statement(label, location);
  3561  }
  3562  
  3563  // Class Goto_unnamed_statement.
  3564  
  3565  int
  3566  Goto_unnamed_statement::do_traverse(Traverse*)
  3567  {
  3568    return TRAVERSE_CONTINUE;
  3569  }
  3570  
  3571  // Convert the goto unnamed statement to the backend representation.
  3572  
  3573  Bstatement*
  3574  Goto_unnamed_statement::do_get_backend(Translate_context* context)
  3575  {
  3576    return this->label_->get_goto(context, this->location());
  3577  }
  3578  
  3579  // Export a goto unnamed statement.
  3580  
  3581  void
  3582  Goto_unnamed_statement::do_export_statement(Export_function_body *efb)
  3583  {
  3584    unsigned int index = efb->unnamed_label_index(this->label_);
  3585    char buf[100];
  3586    snprintf(buf, sizeof buf, "goto $l%u", index);
  3587    efb->write_c_string(buf);
  3588  }
  3589  
  3590  // Dump the AST representation for an unnamed goto statement
  3591  
  3592  void
  3593  Goto_unnamed_statement::do_dump_statement(
  3594      Ast_dump_context* ast_dump_context) const
  3595  {
  3596    ast_dump_context->print_indent();
  3597    ast_dump_context->ostream() << "goto ";
  3598    ast_dump_context->dump_label_name(this->label_);
  3599    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  3600  }
  3601  
  3602  // Make a goto statement to an unnamed label.
  3603  
  3604  Statement*
  3605  Statement::make_goto_unnamed_statement(Unnamed_label* label,
  3606  				       Location location)
  3607  {
  3608    return new Goto_unnamed_statement(label, location);
  3609  }
  3610  
  3611  // Class Label_statement.
  3612  
  3613  // Traversal.
  3614  
  3615  int
  3616  Label_statement::do_traverse(Traverse*)
  3617  {
  3618    return TRAVERSE_CONTINUE;
  3619  }
  3620  
  3621  // Return the backend representation of the statement defining this
  3622  // label.
  3623  
  3624  Bstatement*
  3625  Label_statement::do_get_backend(Translate_context* context)
  3626  {
  3627    if (this->label_->is_dummy_label())
  3628      {
  3629        Bexpression* bce = context->backend()->boolean_constant_expression(false);
  3630        Bfunction* bfunction = context->function()->func_value()->get_decl();
  3631        return context->backend()->expression_statement(bfunction, bce);
  3632      }
  3633    Blabel* blabel = this->label_->get_backend_label(context);
  3634    return context->backend()->label_definition_statement(blabel);
  3635  }
  3636  
  3637  // Export a label.
  3638  
  3639  void
  3640  Label_statement::do_export_statement(Export_function_body* efb)
  3641  {
  3642    if (this->label_->is_dummy_label())
  3643      return;
  3644    // We use a leading colon, not a trailing one, to simplify import.
  3645    efb->write_c_string(":");
  3646    efb->write_string(this->label_->name());
  3647  }
  3648  
  3649  // Import a label or an unnamed label.
  3650  
  3651  Statement*
  3652  Label_statement::do_import(Import_function_body* ifb, Location loc)
  3653  {
  3654    ifb->require_c_string(":");
  3655    std::string id = ifb->read_identifier();
  3656    if (id[0] != '$')
  3657      {
  3658        Function* fn = ifb->function()->func_value();
  3659        Label* label = fn->add_label_definition(ifb->gogo(), id, loc);
  3660        return Statement::make_label_statement(label, loc);
  3661      }
  3662    else
  3663      {
  3664        if (id[1] != 'l')
  3665  	{
  3666  	  if (!ifb->saw_error())
  3667  	    go_error_at(loc,
  3668  			("invalid export data for %qs: "
  3669  			 "bad unnamed label at %lu"),
  3670  			ifb->name().c_str(),
  3671  			static_cast<unsigned long>(ifb->off()));
  3672  	  ifb->set_saw_error();
  3673  	  return Statement::make_error_statement(loc);
  3674  	}
  3675        const char* p = id.c_str();
  3676        char* end;
  3677        long idx = strtol(p + 2, &end, 10);
  3678        if (*end != '\0' || idx > 0x7fffffff)
  3679  	{
  3680  	  if (!ifb->saw_error())
  3681  	    go_error_at(loc,
  3682  			("invalid export data for %qs: "
  3683  			 "bad unnamed label index at %lu"),
  3684  			ifb->name().c_str(),
  3685  			static_cast<unsigned long>(ifb->off()));
  3686  	  ifb->set_saw_error();
  3687  	  return Statement::make_error_statement(loc);
  3688  	}
  3689  
  3690        Unnamed_label* label = ifb->unnamed_label(idx, loc);
  3691        return Statement::make_unnamed_label_statement(label);
  3692      }
  3693  }
  3694  
  3695  // Dump the AST for a label definition statement.
  3696  
  3697  void
  3698  Label_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
  3699  {
  3700    ast_dump_context->print_indent();
  3701    ast_dump_context->ostream() << this->label_->name() << ":" << dsuffix(location()) << std::endl;
  3702  }
  3703  
  3704  // Make a label statement.
  3705  
  3706  Statement*
  3707  Statement::make_label_statement(Label* label, Location location)
  3708  {
  3709    return new Label_statement(label, location);
  3710  }
  3711  
  3712  // Class Unnamed_label_statement.
  3713  
  3714  Unnamed_label_statement::Unnamed_label_statement(Unnamed_label* label)
  3715    : Statement(STATEMENT_UNNAMED_LABEL, label->location()),
  3716      label_(label)
  3717  { }
  3718  
  3719  int
  3720  Unnamed_label_statement::do_traverse(Traverse*)
  3721  {
  3722    return TRAVERSE_CONTINUE;
  3723  }
  3724  
  3725  // Get the backend definition for this unnamed label statement.
  3726  
  3727  Bstatement*
  3728  Unnamed_label_statement::do_get_backend(Translate_context* context)
  3729  {
  3730    return this->label_->get_definition(context);
  3731  }
  3732  
  3733  // Export an unnamed label.
  3734  
  3735  void
  3736  Unnamed_label_statement::do_export_statement(Export_function_body* efb)
  3737  {
  3738    unsigned int index = efb->unnamed_label_index(this->label_);
  3739    char buf[50];
  3740    // We use a leading colon, not a trailing one, to simplify import.
  3741    snprintf(buf, sizeof buf, ":$l%u", index);
  3742    efb->write_c_string(buf);
  3743  }
  3744  
  3745  // Dump the AST representation for an unnamed label definition statement.
  3746  
  3747  void
  3748  Unnamed_label_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
  3749      const
  3750  {
  3751    ast_dump_context->print_indent();
  3752    ast_dump_context->dump_label_name(this->label_);
  3753    ast_dump_context->ostream() << ":" << dsuffix(location()) << std::endl;
  3754  }
  3755  
  3756  // Make an unnamed label statement.
  3757  
  3758  Statement*
  3759  Statement::make_unnamed_label_statement(Unnamed_label* label)
  3760  {
  3761    return new Unnamed_label_statement(label);
  3762  }
  3763  
  3764  // Class If_statement.
  3765  
  3766  // Traversal.
  3767  
  3768  int
  3769  If_statement::do_traverse(Traverse* traverse)
  3770  {
  3771    if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT
  3772        || this->then_block_->traverse(traverse) == TRAVERSE_EXIT)
  3773      return TRAVERSE_EXIT;
  3774    if (this->else_block_ != NULL)
  3775      {
  3776        if (this->else_block_->traverse(traverse) == TRAVERSE_EXIT)
  3777  	return TRAVERSE_EXIT;
  3778      }
  3779    return TRAVERSE_CONTINUE;
  3780  }
  3781  
  3782  void
  3783  If_statement::do_determine_types()
  3784  {
  3785    Type_context context(Type::lookup_bool_type(), false);
  3786    this->cond_->determine_type(&context);
  3787    this->then_block_->determine_types();
  3788    if (this->else_block_ != NULL)
  3789      this->else_block_->determine_types();
  3790  }
  3791  
  3792  // Check types.
  3793  
  3794  void
  3795  If_statement::do_check_types(Gogo*)
  3796  {
  3797    Type* type = this->cond_->type();
  3798    if (type->is_error())
  3799      this->set_is_error();
  3800    else if (!type->is_boolean_type())
  3801      this->report_error(_("expected boolean expression"));
  3802  }
  3803  
  3804  // Whether the overall statement may fall through.
  3805  
  3806  bool
  3807  If_statement::do_may_fall_through() const
  3808  {
  3809    return (this->else_block_ == NULL
  3810  	  || this->then_block_->may_fall_through()
  3811  	  || this->else_block_->may_fall_through());
  3812  }
  3813  
  3814  // Get the backend representation.
  3815  
  3816  Bstatement*
  3817  If_statement::do_get_backend(Translate_context* context)
  3818  {
  3819    go_assert(this->cond_->type()->is_boolean_type()
  3820  	     || this->cond_->type()->is_error());
  3821    Bexpression* cond = this->cond_->get_backend(context);
  3822    Bblock* then_block = this->then_block_->get_backend(context);
  3823    Bblock* else_block = (this->else_block_ == NULL
  3824  			? NULL
  3825  			: this->else_block_->get_backend(context));
  3826    Bfunction* bfunction = context->function()->func_value()->get_decl();
  3827    return context->backend()->if_statement(bfunction,
  3828                                            cond, then_block, else_block,
  3829  					  this->location());
  3830  }
  3831  
  3832  // Export an if statement.
  3833  
  3834  void
  3835  If_statement::do_export_statement(Export_function_body* efb)
  3836  {
  3837    efb->write_c_string("if ");
  3838    this->cond_->export_expression(efb);
  3839    efb->write_c_string(" ");
  3840    Block_statement::export_block(efb, this->then_block_, false);
  3841    if (this->else_block_ != NULL)
  3842      {
  3843        efb->write_c_string(" else ");
  3844        Block_statement::export_block(efb, this->else_block_, false);
  3845      }
  3846  }
  3847  
  3848  // Import an if statement.
  3849  
  3850  Statement*
  3851  If_statement::do_import(Import_function_body* ifb, Location loc)
  3852  {
  3853    ifb->require_c_string("if ");
  3854  
  3855    Expression* cond = Expression::import_expression(ifb, loc);
  3856    ifb->require_c_string(" ");
  3857  
  3858    if (!ifb->match_c_string("{"))
  3859      {
  3860        if (!ifb->saw_error())
  3861  	go_error_at(ifb->location(),
  3862  		    "import error for %qs: no block for if statement at %lu",
  3863  		    ifb->name().c_str(),
  3864  		    static_cast<unsigned long>(ifb->off()));
  3865        ifb->set_saw_error();
  3866        return Statement::make_error_statement(loc);
  3867      }
  3868  
  3869    bool is_lowered_for_statement;
  3870    Block* then_block = Block_statement::do_import(ifb, loc,
  3871  						 &is_lowered_for_statement);
  3872    if (then_block == NULL)
  3873      return Statement::make_error_statement(loc);
  3874    if (is_lowered_for_statement)
  3875      {
  3876        if (!ifb->saw_error())
  3877  	go_error_at(ifb->location(),
  3878  		    ("import error for %qs: "
  3879  		     "unexpected lowered for in if statement at %lu"),
  3880  		    ifb->name().c_str(),
  3881  		    static_cast<unsigned long>(ifb->off()));
  3882        ifb->set_saw_error();
  3883        return Statement::make_error_statement(loc);
  3884      }
  3885  
  3886    Block* else_block = NULL;
  3887    if (ifb->match_c_string(" else "))
  3888      {
  3889        ifb->advance(6);
  3890        if (!ifb->match_c_string("{"))
  3891  	{
  3892  	  if (!ifb->saw_error())
  3893  	    go_error_at(ifb->location(),
  3894  			("import error for %qs: no else block "
  3895  			 "for if statement at %lu"),
  3896  			ifb->name().c_str(),
  3897  			static_cast<unsigned long>(ifb->off()));
  3898  	  ifb->set_saw_error();
  3899  	  return Statement::make_error_statement(loc);
  3900  	}
  3901  
  3902        else_block = Block_statement::do_import(ifb, loc,
  3903  					      &is_lowered_for_statement);
  3904        if (else_block == NULL)
  3905  	return Statement::make_error_statement(loc);
  3906        if (is_lowered_for_statement)
  3907  	{
  3908  	  if (!ifb->saw_error())
  3909  	    go_error_at(ifb->location(),
  3910  			("import error for %qs: "
  3911  			 "unexpected lowered for in if statement at %lu"),
  3912  			ifb->name().c_str(),
  3913  			static_cast<unsigned long>(ifb->off()));
  3914  	  ifb->set_saw_error();
  3915  	  return Statement::make_error_statement(loc);
  3916  	}
  3917      }
  3918  
  3919    return Statement::make_if_statement(cond, then_block, else_block, loc);
  3920  }
  3921  
  3922  // Dump the AST representation for an if statement
  3923  
  3924  void
  3925  If_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
  3926  {
  3927    ast_dump_context->print_indent();
  3928    ast_dump_context->ostream() << "if ";
  3929    ast_dump_context->dump_expression(this->cond_);
  3930    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  3931    if (ast_dump_context->dump_subblocks())
  3932      {
  3933        ast_dump_context->dump_block(this->then_block_);
  3934        if (this->else_block_ != NULL)
  3935  	{
  3936  	  ast_dump_context->print_indent();
  3937  	  ast_dump_context->ostream() << "else" << std::endl;
  3938  	  ast_dump_context->dump_block(this->else_block_);
  3939  	}
  3940      }
  3941  }
  3942  
  3943  // Make an if statement.
  3944  
  3945  Statement*
  3946  Statement::make_if_statement(Expression* cond, Block* then_block,
  3947  			     Block* else_block, Location location)
  3948  {
  3949    return new If_statement(cond, then_block, else_block, location);
  3950  }
  3951  
  3952  // Class Case_clauses::Hash_integer_value.
  3953  
  3954  class Case_clauses::Hash_integer_value
  3955  {
  3956   public:
  3957    size_t
  3958    operator()(Expression*) const;
  3959  };
  3960  
  3961  size_t
  3962  Case_clauses::Hash_integer_value::operator()(Expression* pe) const
  3963  {
  3964    Numeric_constant nc;
  3965    mpz_t ival;
  3966    if (!pe->numeric_constant_value(&nc) || !nc.to_int(&ival))
  3967      go_unreachable();
  3968    size_t ret = mpz_get_ui(ival);
  3969    mpz_clear(ival);
  3970    return ret;
  3971  }
  3972  
  3973  // Class Case_clauses::Eq_integer_value.
  3974  
  3975  class Case_clauses::Eq_integer_value
  3976  {
  3977   public:
  3978    bool
  3979    operator()(Expression*, Expression*) const;
  3980  };
  3981  
  3982  bool
  3983  Case_clauses::Eq_integer_value::operator()(Expression* a, Expression* b) const
  3984  {
  3985    Numeric_constant anc;
  3986    mpz_t aval;
  3987    Numeric_constant bnc;
  3988    mpz_t bval;
  3989    if (!a->numeric_constant_value(&anc)
  3990        || !anc.to_int(&aval)
  3991        || !b->numeric_constant_value(&bnc)
  3992        || !bnc.to_int(&bval))
  3993      go_unreachable();
  3994    bool ret = mpz_cmp(aval, bval) == 0;
  3995    mpz_clear(aval);
  3996    mpz_clear(bval);
  3997    return ret;
  3998  }
  3999  
  4000  // Class Case_clauses::Case_clause.
  4001  
  4002  // Traversal.
  4003  
  4004  int
  4005  Case_clauses::Case_clause::traverse(Traverse* traverse)
  4006  {
  4007    if (this->cases_ != NULL
  4008        && (traverse->traverse_mask()
  4009  	  & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
  4010      {
  4011        if (this->cases_->traverse(traverse) == TRAVERSE_EXIT)
  4012  	return TRAVERSE_EXIT;
  4013      }
  4014    if (this->statements_ != NULL)
  4015      {
  4016        if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
  4017  	return TRAVERSE_EXIT;
  4018      }
  4019    return TRAVERSE_CONTINUE;
  4020  }
  4021  
  4022  // Check whether all the case expressions are integer constants.
  4023  
  4024  bool
  4025  Case_clauses::Case_clause::is_constant() const
  4026  {
  4027    if (this->cases_ != NULL)
  4028      {
  4029        for (Expression_list::const_iterator p = this->cases_->begin();
  4030  	   p != this->cases_->end();
  4031  	   ++p)
  4032  	if (!(*p)->is_constant() || (*p)->type()->integer_type() == NULL)
  4033  	  return false;
  4034      }
  4035    return true;
  4036  }
  4037  
  4038  // Lower a case clause for a nonconstant switch.  VAL_TEMP is the
  4039  // value we are switching on; it may be NULL.  If START_LABEL is not
  4040  // NULL, it goes at the start of the statements, after the condition
  4041  // test.  We branch to FINISH_LABEL at the end of the statements.
  4042  
  4043  void
  4044  Case_clauses::Case_clause::lower(Block* b, Temporary_statement* val_temp,
  4045  				 Unnamed_label* start_label,
  4046  				 Unnamed_label* finish_label) const
  4047  {
  4048    Location loc = this->location_;
  4049    Unnamed_label* next_case_label;
  4050    if (this->cases_ == NULL || this->cases_->empty())
  4051      {
  4052        go_assert(this->is_default_);
  4053        next_case_label = NULL;
  4054      }
  4055    else
  4056      {
  4057        Expression* cond = NULL;
  4058  
  4059        for (Expression_list::const_iterator p = this->cases_->begin();
  4060  	   p != this->cases_->end();
  4061  	   ++p)
  4062  	{
  4063  	  Expression* ref = Expression::make_temporary_reference(val_temp,
  4064  								 loc);
  4065  	  Expression* this_cond = Expression::make_binary(OPERATOR_EQEQ, ref,
  4066  							  *p, loc);
  4067  	  if (cond == NULL)
  4068  	    cond = this_cond;
  4069  	  else
  4070  	    cond = Expression::make_binary(OPERATOR_OROR, cond, this_cond, loc);
  4071  	}
  4072  
  4073        Block* then_block = new Block(b, loc);
  4074        next_case_label = new Unnamed_label(Linemap::unknown_location());
  4075        Statement* s = Statement::make_goto_unnamed_statement(next_case_label,
  4076  							    loc);
  4077        then_block->add_statement(s);
  4078  
  4079        // if !COND { goto NEXT_CASE_LABEL }
  4080        cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
  4081        s = Statement::make_if_statement(cond, then_block, NULL, loc);
  4082        b->add_statement(s);
  4083      }
  4084  
  4085    if (start_label != NULL)
  4086      b->add_statement(Statement::make_unnamed_label_statement(start_label));
  4087  
  4088    if (this->statements_ != NULL)
  4089      b->add_statement(Statement::make_block_statement(this->statements_, loc));
  4090  
  4091    Statement* s = Statement::make_goto_unnamed_statement(finish_label, loc);
  4092    b->add_statement(s);
  4093  
  4094    if (next_case_label != NULL)
  4095      b->add_statement(Statement::make_unnamed_label_statement(next_case_label));
  4096  }
  4097  
  4098  // Determine types.
  4099  
  4100  void
  4101  Case_clauses::Case_clause::determine_types(Type* type)
  4102  {
  4103    if (this->cases_ != NULL)
  4104      {
  4105        Type_context case_context(type, false);
  4106        for (Expression_list::iterator p = this->cases_->begin();
  4107  	   p != this->cases_->end();
  4108  	   ++p)
  4109  	(*p)->determine_type(&case_context);
  4110      }
  4111    if (this->statements_ != NULL)
  4112      this->statements_->determine_types();
  4113  }
  4114  
  4115  // Check types.  Returns false if there was an error.
  4116  
  4117  bool
  4118  Case_clauses::Case_clause::check_types(Type* type)
  4119  {
  4120    if (this->cases_ != NULL)
  4121      {
  4122        for (Expression_list::iterator p = this->cases_->begin();
  4123  	   p != this->cases_->end();
  4124  	   ++p)
  4125  	{
  4126  	  if (!Type::are_assignable(type, (*p)->type(), NULL)
  4127  	      && !Type::are_assignable((*p)->type(), type, NULL))
  4128  	    {
  4129  	      go_error_at((*p)->location(),
  4130  			  "type mismatch between switch value and case clause");
  4131  	      return false;
  4132  	    }
  4133  	}
  4134      }
  4135    return true;
  4136  }
  4137  
  4138  // Return true if this clause may fall through to the following
  4139  // statements.  Note that this is not the same as whether the case
  4140  // uses the "fallthrough" keyword.
  4141  
  4142  bool
  4143  Case_clauses::Case_clause::may_fall_through() const
  4144  {
  4145    if (this->statements_ == NULL)
  4146      return true;
  4147    return this->statements_->may_fall_through();
  4148  }
  4149  
  4150  // Convert the case values and statements to the backend
  4151  // representation.  BREAK_LABEL is the label which break statements
  4152  // should branch to.  CASE_CONSTANTS is used to detect duplicate
  4153  // constants.  *CASES should be passed as an empty vector; the values
  4154  // for this case will be added to it.  If this is the default case,
  4155  // *CASES will remain empty.  This returns the statement to execute if
  4156  // one of these cases is selected.
  4157  
  4158  Bstatement*
  4159  Case_clauses::Case_clause::get_backend(Translate_context* context,
  4160  				       Unnamed_label* break_label,
  4161  				       Case_constants* case_constants,
  4162  				       std::vector<Bexpression*>* cases) const
  4163  {
  4164    if (this->cases_ != NULL)
  4165      {
  4166        go_assert(!this->is_default_);
  4167        for (Expression_list::const_iterator p = this->cases_->begin();
  4168  	   p != this->cases_->end();
  4169  	   ++p)
  4170  	{
  4171  	  Expression* e = *p;
  4172  	  if (e->classification() != Expression::EXPRESSION_INTEGER)
  4173  	    {
  4174  	      Numeric_constant nc;
  4175  	      mpz_t ival;
  4176  	      if (!(*p)->numeric_constant_value(&nc) || !nc.to_int(&ival))
  4177  		{
  4178  		  // Something went wrong.  This can happen with a
  4179  		  // negative constant and an unsigned switch value.
  4180  		  go_assert(saw_errors());
  4181  		  continue;
  4182  		}
  4183  	      go_assert(nc.type() != NULL);
  4184  	      e = Expression::make_integer_z(&ival, nc.type(), e->location());
  4185  	      mpz_clear(ival);
  4186  	    }
  4187  
  4188  	  std::pair<Case_constants::iterator, bool> ins =
  4189  	    case_constants->insert(e);
  4190  	  if (!ins.second)
  4191  	    {
  4192  	      // Value was already present.
  4193  	      go_error_at(this->location_, "duplicate case in switch");
  4194  	      e = Expression::make_error(this->location_);
  4195  	    }
  4196  	  cases->push_back(e->get_backend(context));
  4197  	}
  4198      }
  4199  
  4200    Bstatement* statements;
  4201    if (this->statements_ == NULL)
  4202      statements = NULL;
  4203    else
  4204      {
  4205        Bblock* bblock = this->statements_->get_backend(context);
  4206        statements = context->backend()->block_statement(bblock);
  4207      }
  4208  
  4209    Bstatement* break_stat;
  4210    if (this->is_fallthrough_)
  4211      break_stat = NULL;
  4212    else
  4213      break_stat = break_label->get_goto(context, this->location_);
  4214  
  4215    if (statements == NULL)
  4216      return break_stat;
  4217    else if (break_stat == NULL)
  4218      return statements;
  4219    else
  4220      return context->backend()->compound_statement(statements, break_stat);
  4221  }
  4222  
  4223  // Dump the AST representation for a case clause
  4224  
  4225  void
  4226  Case_clauses::Case_clause::dump_clause(Ast_dump_context* ast_dump_context)
  4227      const
  4228  {
  4229    ast_dump_context->print_indent();
  4230    if (this->is_default_)
  4231      {
  4232        ast_dump_context->ostream() << "default:";
  4233      }
  4234    else
  4235      {
  4236        ast_dump_context->ostream() << "case ";
  4237        ast_dump_context->dump_expression_list(this->cases_);
  4238        ast_dump_context->ostream() << ":" ;
  4239      }
  4240    ast_dump_context->dump_block(this->statements_);
  4241    if (this->is_fallthrough_)
  4242      {
  4243        ast_dump_context->print_indent();
  4244        ast_dump_context->ostream() <<  " (fallthrough)" << dsuffix(location()) << std::endl;
  4245      }
  4246  }
  4247  
  4248  // Class Case_clauses.
  4249  
  4250  // Traversal.
  4251  
  4252  int
  4253  Case_clauses::traverse(Traverse* traverse)
  4254  {
  4255    for (Clauses::iterator p = this->clauses_.begin();
  4256         p != this->clauses_.end();
  4257         ++p)
  4258      {
  4259        if (p->traverse(traverse) == TRAVERSE_EXIT)
  4260  	return TRAVERSE_EXIT;
  4261      }
  4262    return TRAVERSE_CONTINUE;
  4263  }
  4264  
  4265  // Check whether all the case expressions are constant.
  4266  
  4267  bool
  4268  Case_clauses::is_constant() const
  4269  {
  4270    for (Clauses::const_iterator p = this->clauses_.begin();
  4271         p != this->clauses_.end();
  4272         ++p)
  4273      if (!p->is_constant())
  4274        return false;
  4275    return true;
  4276  }
  4277  
  4278  // Lower case clauses for a nonconstant switch.
  4279  
  4280  void
  4281  Case_clauses::lower(Block* b, Temporary_statement* val_temp,
  4282  		    Unnamed_label* break_label) const
  4283  {
  4284    // The default case.
  4285    const Case_clause* default_case = NULL;
  4286  
  4287    // The label for the fallthrough of the previous case.
  4288    Unnamed_label* last_fallthrough_label = NULL;
  4289  
  4290    // The label for the start of the default case.  This is used if the
  4291    // case before the default case falls through.
  4292    Unnamed_label* default_start_label = NULL;
  4293  
  4294    // The label for the end of the default case.  This normally winds
  4295    // up as BREAK_LABEL, but it will be different if the default case
  4296    // falls through.
  4297    Unnamed_label* default_finish_label = NULL;
  4298  
  4299    for (Clauses::const_iterator p = this->clauses_.begin();
  4300         p != this->clauses_.end();
  4301         ++p)
  4302      {
  4303        // The label to use for the start of the statements for this
  4304        // case.  This is NULL unless the previous case falls through.
  4305        Unnamed_label* start_label = last_fallthrough_label;
  4306  
  4307        // The label to jump to after the end of the statements for this
  4308        // case.
  4309        Unnamed_label* finish_label = break_label;
  4310  
  4311        last_fallthrough_label = NULL;
  4312        if (p->is_fallthrough() && p + 1 != this->clauses_.end())
  4313  	{
  4314  	  finish_label = new Unnamed_label(p->location());
  4315  	  last_fallthrough_label = finish_label;
  4316  	}
  4317  
  4318        if (!p->is_default())
  4319  	p->lower(b, val_temp, start_label, finish_label);
  4320        else
  4321  	{
  4322  	  // We have to move the default case to the end, so that we
  4323  	  // only use it if all the other tests fail.
  4324  	  default_case = &*p;
  4325  	  default_start_label = start_label;
  4326  	  default_finish_label = finish_label;
  4327  	}
  4328      }
  4329  
  4330    if (default_case != NULL)
  4331      default_case->lower(b, val_temp, default_start_label,
  4332  			default_finish_label);
  4333  }
  4334  
  4335  // Determine types.
  4336  
  4337  void
  4338  Case_clauses::determine_types(Type* type)
  4339  {
  4340    for (Clauses::iterator p = this->clauses_.begin();
  4341         p != this->clauses_.end();
  4342         ++p)
  4343      p->determine_types(type);
  4344  }
  4345  
  4346  // Check types.  Returns false if there was an error.
  4347  
  4348  bool
  4349  Case_clauses::check_types(Type* type)
  4350  {
  4351    bool ret = true;
  4352    for (Clauses::iterator p = this->clauses_.begin();
  4353         p != this->clauses_.end();
  4354         ++p)
  4355      {
  4356        if (!p->check_types(type))
  4357  	ret = false;
  4358      }
  4359    return ret;
  4360  }
  4361  
  4362  // Return true if these clauses may fall through to the statements
  4363  // following the switch statement.
  4364  
  4365  bool
  4366  Case_clauses::may_fall_through() const
  4367  {
  4368    bool found_default = false;
  4369    for (Clauses::const_iterator p = this->clauses_.begin();
  4370         p != this->clauses_.end();
  4371         ++p)
  4372      {
  4373        if (p->may_fall_through() && !p->is_fallthrough())
  4374  	return true;
  4375        if (p->is_default())
  4376  	found_default = true;
  4377      }
  4378    return !found_default;
  4379  }
  4380  
  4381  // Convert the cases to the backend representation.  This sets
  4382  // *ALL_CASES and *ALL_STATEMENTS.
  4383  
  4384  void
  4385  Case_clauses::get_backend(Translate_context* context,
  4386  			  Unnamed_label* break_label,
  4387  			  std::vector<std::vector<Bexpression*> >* all_cases,
  4388  			  std::vector<Bstatement*>* all_statements) const
  4389  {
  4390    Case_constants case_constants;
  4391  
  4392    size_t c = this->clauses_.size();
  4393    all_cases->resize(c);
  4394    all_statements->resize(c);
  4395  
  4396    size_t i = 0;
  4397    for (Clauses::const_iterator p = this->clauses_.begin();
  4398         p != this->clauses_.end();
  4399         ++p, ++i)
  4400      {
  4401        std::vector<Bexpression*> cases;
  4402        Bstatement* stat = p->get_backend(context, break_label, &case_constants,
  4403  					&cases);
  4404        // The final clause can't fall through.
  4405        if (i == c - 1 && p->is_fallthrough())
  4406          {
  4407            go_assert(saw_errors());
  4408            stat = context->backend()->error_statement();
  4409          }
  4410        (*all_cases)[i].swap(cases);
  4411        (*all_statements)[i] = stat;
  4412      }
  4413  }
  4414  
  4415  // Dump the AST representation for case clauses (from a switch statement)
  4416  
  4417  void
  4418  Case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
  4419  {
  4420    for (Clauses::const_iterator p = this->clauses_.begin();
  4421         p != this->clauses_.end();
  4422         ++p)
  4423      p->dump_clause(ast_dump_context);
  4424  }
  4425  
  4426  // A constant switch statement.  A Switch_statement is lowered to this
  4427  // when all the cases are constants.
  4428  
  4429  class Constant_switch_statement : public Statement
  4430  {
  4431   public:
  4432    Constant_switch_statement(Expression* val, Case_clauses* clauses,
  4433  			    Unnamed_label* break_label,
  4434  			    Location location)
  4435      : Statement(STATEMENT_CONSTANT_SWITCH, location),
  4436        val_(val), clauses_(clauses), break_label_(break_label)
  4437    { }
  4438  
  4439   protected:
  4440    int
  4441    do_traverse(Traverse*);
  4442  
  4443    void
  4444    do_determine_types();
  4445  
  4446    void
  4447    do_check_types(Gogo*);
  4448  
  4449    Bstatement*
  4450    do_get_backend(Translate_context*);
  4451  
  4452    void
  4453    do_dump_statement(Ast_dump_context*) const;
  4454  
  4455   private:
  4456    // The value to switch on.
  4457    Expression* val_;
  4458    // The case clauses.
  4459    Case_clauses* clauses_;
  4460    // The break label, if needed.
  4461    Unnamed_label* break_label_;
  4462  };
  4463  
  4464  // Traversal.
  4465  
  4466  int
  4467  Constant_switch_statement::do_traverse(Traverse* traverse)
  4468  {
  4469    if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
  4470      return TRAVERSE_EXIT;
  4471    return this->clauses_->traverse(traverse);
  4472  }
  4473  
  4474  // Determine types.
  4475  
  4476  void
  4477  Constant_switch_statement::do_determine_types()
  4478  {
  4479    this->val_->determine_type_no_context();
  4480    this->clauses_->determine_types(this->val_->type());
  4481  }
  4482  
  4483  // Check types.
  4484  
  4485  void
  4486  Constant_switch_statement::do_check_types(Gogo*)
  4487  {
  4488    if (!this->clauses_->check_types(this->val_->type()))
  4489      this->set_is_error();
  4490  }
  4491  
  4492  // Convert to GENERIC.
  4493  
  4494  Bstatement*
  4495  Constant_switch_statement::do_get_backend(Translate_context* context)
  4496  {
  4497    Bexpression* switch_val_expr = this->val_->get_backend(context);
  4498  
  4499    Unnamed_label* break_label = this->break_label_;
  4500    if (break_label == NULL)
  4501      break_label = new Unnamed_label(this->location());
  4502  
  4503    std::vector<std::vector<Bexpression*> > all_cases;
  4504    std::vector<Bstatement*> all_statements;
  4505    this->clauses_->get_backend(context, break_label, &all_cases,
  4506  			      &all_statements);
  4507  
  4508    Bfunction* bfunction = context->function()->func_value()->get_decl();
  4509    Bstatement* switch_statement;
  4510    switch_statement = context->backend()->switch_statement(bfunction,
  4511  							  switch_val_expr,
  4512  							  all_cases,
  4513  							  all_statements,
  4514  							  this->location());
  4515    Bstatement* ldef = break_label->get_definition(context);
  4516    return context->backend()->compound_statement(switch_statement, ldef);
  4517  }
  4518  
  4519  // Dump the AST representation for a constant switch statement.
  4520  
  4521  void
  4522  Constant_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
  4523      const
  4524  {
  4525    ast_dump_context->print_indent();
  4526    ast_dump_context->ostream() << "switch ";
  4527    ast_dump_context->dump_expression(this->val_);
  4528  
  4529    if (ast_dump_context->dump_subblocks())
  4530      {
  4531        ast_dump_context->ostream() << " {" << std::endl;
  4532        this->clauses_->dump_clauses(ast_dump_context);
  4533        ast_dump_context->ostream() << "}";
  4534      }
  4535  
  4536     ast_dump_context->ostream() << std::endl;
  4537  }
  4538  
  4539  // Class Switch_statement.
  4540  
  4541  // Traversal.
  4542  
  4543  int
  4544  Switch_statement::do_traverse(Traverse* traverse)
  4545  {
  4546    if (this->val_ != NULL)
  4547      {
  4548        if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
  4549  	return TRAVERSE_EXIT;
  4550      }
  4551    return this->clauses_->traverse(traverse);
  4552  }
  4553  
  4554  // Lower a Switch_statement to a Constant_switch_statement or a series
  4555  // of if statements.
  4556  
  4557  Statement*
  4558  Switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
  4559  			   Statement_inserter*)
  4560  {
  4561    Location loc = this->location();
  4562  
  4563    if (this->val_ != NULL
  4564        && (this->val_->is_error_expression()
  4565  	  || this->val_->type()->is_error()))
  4566      {
  4567        go_assert(saw_errors());
  4568        return Statement::make_error_statement(loc);
  4569      }
  4570  
  4571    if (this->val_ != NULL
  4572        && this->val_->type()->integer_type() != NULL
  4573        && !this->clauses_->empty()
  4574        && this->clauses_->is_constant())
  4575      return new Constant_switch_statement(this->val_, this->clauses_,
  4576  					 this->break_label_, loc);
  4577  
  4578    if (this->val_ != NULL
  4579        && !this->val_->type()->is_comparable()
  4580        && !Type::are_compatible_for_comparison(true, this->val_->type(),
  4581  					      Type::make_nil_type(), NULL))
  4582      {
  4583        go_error_at(this->val_->location(),
  4584  		  "cannot switch on value whose type may not be compared");
  4585        return Statement::make_error_statement(loc);
  4586      }
  4587  
  4588    Block* b = new Block(enclosing, loc);
  4589  
  4590    if (this->clauses_->empty())
  4591      {
  4592        Expression* val = this->val_;
  4593        if (val == NULL)
  4594  	val = Expression::make_boolean(true, loc);
  4595        return Statement::make_statement(val, true);
  4596      }
  4597  
  4598    // var val_temp VAL_TYPE = VAL
  4599    Expression* val = this->val_;
  4600    if (val == NULL)
  4601      val = Expression::make_boolean(true, loc);
  4602  
  4603    Type* type = val->type();
  4604    if (type->is_abstract())
  4605      type = type->make_non_abstract_type();
  4606    Temporary_statement* val_temp = Statement::make_temporary(type, val, loc);
  4607    b->add_statement(val_temp);
  4608  
  4609    this->clauses_->lower(b, val_temp, this->break_label());
  4610  
  4611    Statement* s = Statement::make_unnamed_label_statement(this->break_label_);
  4612    b->add_statement(s);
  4613  
  4614    return Statement::make_block_statement(b, loc);
  4615  }
  4616  
  4617  // Return the break label for this switch statement, creating it if
  4618  // necessary.
  4619  
  4620  Unnamed_label*
  4621  Switch_statement::break_label()
  4622  {
  4623    if (this->break_label_ == NULL)
  4624      this->break_label_ = new Unnamed_label(this->location());
  4625    return this->break_label_;
  4626  }
  4627  
  4628  // Dump the AST representation for a switch statement.
  4629  
  4630  void
  4631  Switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
  4632  {
  4633    ast_dump_context->print_indent();
  4634    ast_dump_context->ostream() << "switch ";
  4635    if (this->val_ != NULL)
  4636      {
  4637        ast_dump_context->dump_expression(this->val_);
  4638      }
  4639    if (ast_dump_context->dump_subblocks())
  4640      {
  4641        ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
  4642        this->clauses_->dump_clauses(ast_dump_context);
  4643        ast_dump_context->print_indent();
  4644        ast_dump_context->ostream() << "}";
  4645      }
  4646    ast_dump_context->ostream() << std::endl;
  4647  }
  4648  
  4649  // Return whether this switch may fall through.
  4650  
  4651  bool
  4652  Switch_statement::do_may_fall_through() const
  4653  {
  4654    if (this->clauses_ == NULL)
  4655      return true;
  4656  
  4657    // If we have a break label, then some case needed it.  That implies
  4658    // that the switch statement as a whole can fall through.
  4659    if (this->break_label_ != NULL)
  4660      return true;
  4661  
  4662    return this->clauses_->may_fall_through();
  4663  }
  4664  
  4665  // Make a switch statement.
  4666  
  4667  Switch_statement*
  4668  Statement::make_switch_statement(Expression* val, Location location)
  4669  {
  4670    return new Switch_statement(val, location);
  4671  }
  4672  
  4673  // Class Type_case_clauses::Type_case_clause.
  4674  
  4675  // Traversal.
  4676  
  4677  int
  4678  Type_case_clauses::Type_case_clause::traverse(Traverse* traverse)
  4679  {
  4680    if (!this->is_default_
  4681        && ((traverse->traverse_mask()
  4682  	   & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
  4683        && Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
  4684      return TRAVERSE_EXIT;
  4685    if (this->statements_ != NULL)
  4686      return this->statements_->traverse(traverse);
  4687    return TRAVERSE_CONTINUE;
  4688  }
  4689  
  4690  // Lower one clause in a type switch.  Add statements to the block B.
  4691  // The type descriptor we are switching on is in DESCRIPTOR_TEMP.
  4692  // BREAK_LABEL is the label at the end of the type switch.
  4693  // *STMTS_LABEL, if not NULL, is a label to put at the start of the
  4694  // statements.
  4695  
  4696  void
  4697  Type_case_clauses::Type_case_clause::lower(Gogo* gogo,
  4698  					   Type* switch_val_type,
  4699  					   Block* b,
  4700  					   Temporary_statement* descriptor_temp,
  4701  					   Unnamed_label* break_label,
  4702  					   Unnamed_label** stmts_label) const
  4703  {
  4704    Location loc = this->location_;
  4705  
  4706    Unnamed_label* next_case_label = NULL;
  4707    if (!this->is_default_)
  4708      {
  4709        Type* type = this->type_;
  4710  
  4711        std::string reason;
  4712        if (switch_val_type->interface_type() != NULL
  4713  	  && !type->is_nil_constant_as_type()
  4714  	  && type->interface_type() == NULL
  4715  	  && !switch_val_type->interface_type()->implements_interface(type,
  4716  								      &reason))
  4717  	{
  4718  	  if (reason.empty())
  4719  	    go_error_at(this->location_, "impossible type switch case");
  4720  	  else
  4721  	    go_error_at(this->location_, "impossible type switch case (%s)",
  4722  			reason.c_str());
  4723  	}
  4724  
  4725        Expression* ref = Expression::make_temporary_reference(descriptor_temp,
  4726  							     loc);
  4727  
  4728        Expression* cond;
  4729        // The language permits case nil, which is of course a constant
  4730        // rather than a type.  It will appear here as an invalid
  4731        // forwarding type.
  4732        if (type->is_nil_constant_as_type())
  4733  	cond = Expression::make_binary(OPERATOR_EQEQ, ref,
  4734  				       Expression::make_nil(loc),
  4735  				       loc);
  4736        else if (type->interface_type() == NULL)
  4737  	{
  4738  	  if (!gogo->need_eqtype())
  4739  	    cond = Expression::make_binary(OPERATOR_EQEQ, ref,
  4740  				           Expression::make_type_descriptor(type, loc),
  4741  				           loc);
  4742  	  else
  4743  	    cond = Runtime::make_call(Runtime::EQTYPE, loc, 2,
  4744  				      Expression::make_type_descriptor(type, loc),
  4745  				      ref);
  4746  	}
  4747        else
  4748  	cond = Runtime::make_call(Runtime::IFACET2IP, loc, 2,
  4749  				  Expression::make_type_descriptor(type, loc),
  4750  				  ref);
  4751  
  4752        Unnamed_label* dest;
  4753        if (!this->is_fallthrough_)
  4754  	{
  4755  	  // if !COND { goto NEXT_CASE_LABEL }
  4756  	  next_case_label = new Unnamed_label(Linemap::unknown_location());
  4757  	  dest = next_case_label;
  4758  	  cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
  4759  	}
  4760        else
  4761  	{
  4762  	  // if COND { goto STMTS_LABEL }
  4763  	  go_assert(stmts_label != NULL);
  4764  	  if (*stmts_label == NULL)
  4765  	    *stmts_label = new Unnamed_label(Linemap::unknown_location());
  4766  	  dest = *stmts_label;
  4767  	}
  4768        Block* then_block = new Block(b, loc);
  4769        Statement* s = Statement::make_goto_unnamed_statement(dest, loc);
  4770        then_block->add_statement(s);
  4771        s = Statement::make_if_statement(cond, then_block, NULL, loc);
  4772        b->add_statement(s);
  4773      }
  4774  
  4775    if (this->statements_ != NULL
  4776        || (!this->is_fallthrough_
  4777  	  && stmts_label != NULL
  4778  	  && *stmts_label != NULL))
  4779      {
  4780        go_assert(!this->is_fallthrough_);
  4781        if (stmts_label != NULL && *stmts_label != NULL)
  4782  	{
  4783  	  go_assert(!this->is_default_);
  4784  	  if (this->statements_ != NULL)
  4785  	    (*stmts_label)->set_location(this->statements_->start_location());
  4786  	  Statement* s = Statement::make_unnamed_label_statement(*stmts_label);
  4787  	  b->add_statement(s);
  4788  	  *stmts_label = NULL;
  4789  	}
  4790        if (this->statements_ != NULL)
  4791  	b->add_statement(Statement::make_block_statement(this->statements_,
  4792  							 loc));
  4793      }
  4794  
  4795    if (this->is_fallthrough_)
  4796      go_assert(next_case_label == NULL);
  4797    else
  4798      {
  4799        Location gloc = (this->statements_ == NULL
  4800  			      ? loc
  4801  			      : this->statements_->end_location());
  4802        b->add_statement(Statement::make_goto_unnamed_statement(break_label,
  4803  							      gloc));
  4804        if (next_case_label != NULL)
  4805  	{
  4806  	  Statement* s =
  4807  	    Statement::make_unnamed_label_statement(next_case_label);
  4808  	  b->add_statement(s);
  4809  	}
  4810      }
  4811  }
  4812  
  4813  // Return true if this type clause may fall through to the statements
  4814  // following the switch.
  4815  
  4816  bool
  4817  Type_case_clauses::Type_case_clause::may_fall_through() const
  4818  {
  4819    if (this->is_fallthrough_)
  4820      {
  4821        // This case means that we automatically fall through to the
  4822        // next case (it's used for T1 in case T1, T2:).  It does not
  4823        // mean that we fall through to the end of the type switch as a
  4824        // whole.  There is sure to be a next case and that next case
  4825        // will determine whether we fall through to the statements
  4826        // after the type switch.
  4827        return false;
  4828      }
  4829    if (this->statements_ == NULL)
  4830      return true;
  4831    return this->statements_->may_fall_through();
  4832  }
  4833  
  4834  // Dump the AST representation for a type case clause
  4835  
  4836  void
  4837  Type_case_clauses::Type_case_clause::dump_clause(
  4838      Ast_dump_context* ast_dump_context) const
  4839  {
  4840    ast_dump_context->print_indent();
  4841    if (this->is_default_)
  4842      {
  4843        ast_dump_context->ostream() << "default:";
  4844      }
  4845    else
  4846      {
  4847        ast_dump_context->ostream() << "case ";
  4848        ast_dump_context->dump_type(this->type_);
  4849        ast_dump_context->ostream() << ":" ;
  4850      }
  4851    ast_dump_context->dump_block(this->statements_);
  4852    if (this->is_fallthrough_)
  4853      {
  4854        ast_dump_context->print_indent();
  4855        ast_dump_context->ostream() <<  " (fallthrough)" << std::endl;
  4856      }
  4857  }
  4858  
  4859  // Class Type_case_clauses.
  4860  
  4861  // Traversal.
  4862  
  4863  int
  4864  Type_case_clauses::traverse(Traverse* traverse)
  4865  {
  4866    for (Type_clauses::iterator p = this->clauses_.begin();
  4867         p != this->clauses_.end();
  4868         ++p)
  4869      {
  4870        if (p->traverse(traverse) == TRAVERSE_EXIT)
  4871  	return TRAVERSE_EXIT;
  4872      }
  4873    return TRAVERSE_CONTINUE;
  4874  }
  4875  
  4876  // Check for duplicate types.
  4877  
  4878  void
  4879  Type_case_clauses::check_duplicates() const
  4880  {
  4881    typedef Unordered_set_hash(const Type*, Type_hash_identical,
  4882  			     Type_identical) Types_seen;
  4883    Types_seen types_seen;
  4884    for (Type_clauses::const_iterator p = this->clauses_.begin();
  4885         p != this->clauses_.end();
  4886         ++p)
  4887      {
  4888        Type* t = p->type();
  4889        if (t == NULL)
  4890  	continue;
  4891        if (t->is_nil_constant_as_type())
  4892  	t = Type::make_nil_type();
  4893        std::pair<Types_seen::iterator, bool> ins = types_seen.insert(t);
  4894        if (!ins.second)
  4895  	go_error_at(p->location(), "duplicate type in switch");
  4896      }
  4897  }
  4898  
  4899  // Lower the clauses in a type switch.  Add statements to the block B.
  4900  // The type descriptor we are switching on is in DESCRIPTOR_TEMP.
  4901  // BREAK_LABEL is the label at the end of the type switch.
  4902  
  4903  void
  4904  Type_case_clauses::lower(Gogo* gogo, Type* switch_val_type,
  4905  			 Block* b,
  4906  			 Temporary_statement* descriptor_temp,
  4907  			 Unnamed_label* break_label) const
  4908  {
  4909    const Type_case_clause* default_case = NULL;
  4910  
  4911    Unnamed_label* stmts_label = NULL;
  4912    for (Type_clauses::const_iterator p = this->clauses_.begin();
  4913         p != this->clauses_.end();
  4914         ++p)
  4915      {
  4916        if (!p->is_default())
  4917  	p->lower(gogo, switch_val_type, b, descriptor_temp, break_label,
  4918  		 &stmts_label);
  4919        else
  4920  	{
  4921  	  // We are generating a series of tests, which means that we
  4922  	  // need to move the default case to the end.
  4923  	  default_case = &*p;
  4924  	}
  4925      }
  4926    go_assert(stmts_label == NULL);
  4927  
  4928    if (default_case != NULL)
  4929      default_case->lower(gogo, switch_val_type, b, descriptor_temp, break_label,
  4930  			NULL);
  4931  }
  4932  
  4933  // Return true if these clauses may fall through to the statements
  4934  // following the switch statement.
  4935  
  4936  bool
  4937  Type_case_clauses::may_fall_through() const
  4938  {
  4939    bool found_default = false;
  4940    for (Type_clauses::const_iterator p = this->clauses_.begin();
  4941         p != this->clauses_.end();
  4942         ++p)
  4943      {
  4944        if (p->may_fall_through())
  4945  	return true;
  4946        if (p->is_default())
  4947  	found_default = true;
  4948      }
  4949    return !found_default;
  4950  }
  4951  
  4952  // Dump the AST representation for case clauses (from a switch statement)
  4953  
  4954  void
  4955  Type_case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
  4956  {
  4957    for (Type_clauses::const_iterator p = this->clauses_.begin();
  4958         p != this->clauses_.end();
  4959         ++p)
  4960      p->dump_clause(ast_dump_context);
  4961  }
  4962  
  4963  // Class Type_switch_statement.
  4964  
  4965  // Traversal.
  4966  
  4967  int
  4968  Type_switch_statement::do_traverse(Traverse* traverse)
  4969  {
  4970    if (this->traverse_expression(traverse, &this->expr_) == TRAVERSE_EXIT)
  4971      return TRAVERSE_EXIT;
  4972    if (this->clauses_ != NULL)
  4973      return this->clauses_->traverse(traverse);
  4974    return TRAVERSE_CONTINUE;
  4975  }
  4976  
  4977  // Lower a type switch statement to a series of if statements.  The gc
  4978  // compiler is able to generate a table in some cases.  However, that
  4979  // does not work for us because we may have type descriptors in
  4980  // different shared libraries, so we can't compare them with simple
  4981  // equality testing.
  4982  
  4983  Statement*
  4984  Type_switch_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
  4985  				Statement_inserter*)
  4986  {
  4987    const Location loc = this->location();
  4988  
  4989    if (this->clauses_ != NULL)
  4990      this->clauses_->check_duplicates();
  4991  
  4992    Block* b = new Block(enclosing, loc);
  4993  
  4994    Type* val_type = this->expr_->type();
  4995    if (val_type->interface_type() == NULL)
  4996      {
  4997        if (!val_type->is_error())
  4998  	this->report_error(_("cannot type switch on non-interface value"));
  4999        return Statement::make_error_statement(loc);
  5000      }
  5001  
  5002    Temporary_statement* val_temp =
  5003      Statement::make_temporary(NULL, this->expr_, loc);
  5004    b->add_statement(val_temp);
  5005  
  5006    // var descriptor_temp DESCRIPTOR_TYPE
  5007    Type* descriptor_type = Type::make_type_descriptor_ptr_type();
  5008    Temporary_statement* descriptor_temp =
  5009      Statement::make_temporary(descriptor_type, NULL, loc);
  5010    b->add_statement(descriptor_temp);
  5011  
  5012    // descriptor_temp = ifacetype(val_temp)
  5013    Expression* ref = Expression::make_temporary_reference(val_temp, loc);
  5014    Expression* td = Expression::get_interface_type_descriptor(ref);
  5015    Temporary_reference_expression* lhs =
  5016      Expression::make_temporary_reference(descriptor_temp, loc);
  5017    lhs->set_is_lvalue();
  5018    Statement* s = Statement::make_assignment(lhs, td, loc);
  5019    b->add_statement(s);
  5020  
  5021    if (this->clauses_ != NULL)
  5022      this->clauses_->lower(gogo, val_type, b, descriptor_temp, this->break_label());
  5023  
  5024    s = Statement::make_unnamed_label_statement(this->break_label_);
  5025    b->add_statement(s);
  5026  
  5027    return Statement::make_block_statement(b, loc);
  5028  }
  5029  
  5030  // Return whether this switch may fall through.
  5031  
  5032  bool
  5033  Type_switch_statement::do_may_fall_through() const
  5034  {
  5035    if (this->clauses_ == NULL)
  5036      return true;
  5037  
  5038    // If we have a break label, then some case needed it.  That implies
  5039    // that the switch statement as a whole can fall through.
  5040    if (this->break_label_ != NULL)
  5041      return true;
  5042  
  5043    return this->clauses_->may_fall_through();
  5044  }
  5045  
  5046  // Return the break label for this type switch statement, creating it
  5047  // if necessary.
  5048  
  5049  Unnamed_label*
  5050  Type_switch_statement::break_label()
  5051  {
  5052    if (this->break_label_ == NULL)
  5053      this->break_label_ = new Unnamed_label(this->location());
  5054    return this->break_label_;
  5055  }
  5056  
  5057  // Dump the AST representation for a type switch statement
  5058  
  5059  void
  5060  Type_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
  5061      const
  5062  {
  5063    ast_dump_context->print_indent();
  5064    ast_dump_context->ostream() << "switch ";
  5065    if (!this->name_.empty())
  5066      ast_dump_context->ostream() << this->name_ << " = ";
  5067    ast_dump_context->dump_expression(this->expr_);
  5068    ast_dump_context->ostream() << " .(type)";
  5069    if (ast_dump_context->dump_subblocks())
  5070      {
  5071        ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
  5072        this->clauses_->dump_clauses(ast_dump_context);
  5073        ast_dump_context->ostream() << "}";
  5074      }
  5075    ast_dump_context->ostream() << std::endl;
  5076  }
  5077  
  5078  // Make a type switch statement.
  5079  
  5080  Type_switch_statement*
  5081  Statement::make_type_switch_statement(const std::string& name, Expression* expr,
  5082  				      Location location)
  5083  {
  5084    return new Type_switch_statement(name, expr, location);
  5085  }
  5086  
  5087  // Class Send_statement.
  5088  
  5089  // Traversal.
  5090  
  5091  int
  5092  Send_statement::do_traverse(Traverse* traverse)
  5093  {
  5094    if (this->traverse_expression(traverse, &this->channel_) == TRAVERSE_EXIT)
  5095      return TRAVERSE_EXIT;
  5096    return this->traverse_expression(traverse, &this->val_);
  5097  }
  5098  
  5099  // Determine types.
  5100  
  5101  void
  5102  Send_statement::do_determine_types()
  5103  {
  5104    this->channel_->determine_type_no_context();
  5105    Type* type = this->channel_->type();
  5106    Type_context context;
  5107    if (type->channel_type() != NULL)
  5108      context.type = type->channel_type()->element_type();
  5109    this->val_->determine_type(&context);
  5110  }
  5111  
  5112  // Check types.
  5113  
  5114  void
  5115  Send_statement::do_check_types(Gogo*)
  5116  {
  5117    Type* type = this->channel_->type();
  5118    if (type->is_error())
  5119      {
  5120        this->set_is_error();
  5121        return;
  5122      }
  5123    Channel_type* channel_type = type->channel_type();
  5124    if (channel_type == NULL)
  5125      {
  5126        go_error_at(this->location(), "left operand of %<<-%> must be channel");
  5127        this->set_is_error();
  5128        return;
  5129      }
  5130    Type* element_type = channel_type->element_type();
  5131    if (!Type::are_assignable(element_type, this->val_->type(), NULL))
  5132      {
  5133        this->report_error(_("incompatible types in send"));
  5134        return;
  5135      }
  5136    if (!channel_type->may_send())
  5137      {
  5138        this->report_error(_("invalid send on receive-only channel"));
  5139        return;
  5140      }
  5141  }
  5142  
  5143  // Flatten a send statement.  We may need a temporary for interface
  5144  // conversion.
  5145  
  5146  Statement*
  5147  Send_statement::do_flatten(Gogo*, Named_object*, Block*,
  5148  			   Statement_inserter* inserter)
  5149  {
  5150    if (this->channel_->is_error_expression()
  5151        || this->channel_->type()->is_error_type())
  5152      {
  5153        go_assert(saw_errors());
  5154        return Statement::make_error_statement(this->location());
  5155      }
  5156  
  5157    Type* element_type = this->channel_->type()->channel_type()->element_type();
  5158    if (!Type::are_identical(element_type, this->val_->type(),
  5159  			   Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
  5160  			   NULL)
  5161        && this->val_->type()->interface_type() != NULL
  5162        && !this->val_->is_multi_eval_safe())
  5163      {
  5164        Temporary_statement* temp =
  5165  	Statement::make_temporary(NULL, this->val_, this->location());
  5166        inserter->insert(temp);
  5167        this->val_ = Expression::make_temporary_reference(temp,
  5168  							this->location());
  5169      }
  5170    return this;
  5171  }
  5172  
  5173  // Add explicit type conversions.
  5174  
  5175  void
  5176  Send_statement::do_add_conversions()
  5177  {
  5178    Type* lt = this->channel_->type()->channel_type()->element_type();
  5179    Type* rt = this->val_->type();
  5180    if (!Type::are_identical(lt, rt, 0, NULL)
  5181        && lt->interface_type() != NULL)
  5182      this->val_ = Expression::make_cast(lt, this->val_, this->location());
  5183  }
  5184  
  5185  // Convert a send statement to the backend representation.
  5186  
  5187  Bstatement*
  5188  Send_statement::do_get_backend(Translate_context* context)
  5189  {
  5190    Location loc = this->location();
  5191  
  5192    Channel_type* channel_type = this->channel_->type()->channel_type();
  5193    Type* element_type = channel_type->element_type();
  5194    Expression* val = Expression::convert_for_assignment(context->gogo(),
  5195  						       element_type,
  5196  						       this->val_, loc);
  5197  
  5198    bool can_take_address;
  5199    switch (element_type->base()->classification())
  5200      {
  5201      case Type::TYPE_BOOLEAN:
  5202      case Type::TYPE_INTEGER:
  5203      case Type::TYPE_FUNCTION:
  5204      case Type::TYPE_POINTER:
  5205      case Type::TYPE_MAP:
  5206      case Type::TYPE_CHANNEL:
  5207      case Type::TYPE_FLOAT:
  5208      case Type::TYPE_COMPLEX:
  5209      case Type::TYPE_STRING:
  5210      case Type::TYPE_INTERFACE:
  5211        can_take_address = false;
  5212        break;
  5213  
  5214      case Type::TYPE_STRUCT:
  5215        can_take_address = true;
  5216        break;
  5217  
  5218      case Type::TYPE_ARRAY:
  5219        can_take_address = !element_type->is_slice_type();
  5220        break;
  5221  
  5222      default:
  5223      case Type::TYPE_ERROR:
  5224      case Type::TYPE_VOID:
  5225      case Type::TYPE_SINK:
  5226      case Type::TYPE_NIL:
  5227      case Type::TYPE_NAMED:
  5228      case Type::TYPE_FORWARD:
  5229        go_assert(saw_errors());
  5230        return context->backend()->error_statement();
  5231      }
  5232  
  5233    // Only try to take the address of a variable.  We have already
  5234    // moved variables to the heap, so this should not cause that to
  5235    // happen unnecessarily.
  5236    if (can_take_address
  5237        && val->var_expression() == NULL
  5238        && val->temporary_reference_expression() == NULL)
  5239      can_take_address = false;
  5240  
  5241    Bstatement* btemp = NULL;
  5242    if (can_take_address)
  5243      {
  5244        // The function doesn't change the value, so just take its
  5245        // address directly.
  5246        val = Expression::make_unary(OPERATOR_AND, val, loc);
  5247      }
  5248    else
  5249      {
  5250        // The value is not in a variable, or is small enough that it
  5251        // might be in a register, and taking the address would push it
  5252        // on the stack.  Copy it into a temporary variable to take the
  5253        // address.
  5254        Temporary_statement* temp = Statement::make_temporary(element_type,
  5255  							    val, loc);
  5256        Expression* ref = Expression::make_temporary_reference(temp, loc);
  5257        val = Expression::make_unary(OPERATOR_AND, ref, loc);
  5258        btemp = temp->get_backend(context);
  5259      }
  5260  
  5261    Expression* call = Runtime::make_call(Runtime::CHANSEND, loc, 2,
  5262  					this->channel_, val);
  5263  
  5264    context->gogo()->lower_expression(context->function(), NULL, &call);
  5265    Bexpression* bcall = call->get_backend(context);
  5266    Bfunction* bfunction = context->function()->func_value()->get_decl();
  5267    Bstatement* s = context->backend()->expression_statement(bfunction, bcall);
  5268  
  5269    if (btemp == NULL)
  5270      return s;
  5271    else
  5272      return context->backend()->compound_statement(btemp, s);
  5273  }
  5274  
  5275  // Dump the AST representation for a send statement
  5276  
  5277  void
  5278  Send_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
  5279  {
  5280    ast_dump_context->print_indent();
  5281    ast_dump_context->dump_expression(this->channel_);
  5282    ast_dump_context->ostream() << " <- ";
  5283    ast_dump_context->dump_expression(this->val_);
  5284    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  5285  }
  5286  
  5287  // Make a send statement.
  5288  
  5289  Send_statement*
  5290  Statement::make_send_statement(Expression* channel, Expression* val,
  5291  			       Location location)
  5292  {
  5293    return new Send_statement(channel, val, location);
  5294  }
  5295  
  5296  // Class Select_clauses::Select_clause.
  5297  
  5298  // Traversal.
  5299  
  5300  int
  5301  Select_clauses::Select_clause::traverse(Traverse* traverse)
  5302  {
  5303    if (!this->is_lowered_
  5304        && (traverse->traverse_mask()
  5305  	  & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
  5306      {
  5307        if (this->channel_ != NULL)
  5308  	{
  5309  	  if (Expression::traverse(&this->channel_, traverse) == TRAVERSE_EXIT)
  5310  	    return TRAVERSE_EXIT;
  5311  	}
  5312        if (this->val_ != NULL)
  5313  	{
  5314  	  if (Expression::traverse(&this->val_, traverse) == TRAVERSE_EXIT)
  5315  	    return TRAVERSE_EXIT;
  5316  	}
  5317        if (this->closed_ != NULL)
  5318  	{
  5319  	  if (Expression::traverse(&this->closed_, traverse) == TRAVERSE_EXIT)
  5320  	    return TRAVERSE_EXIT;
  5321  	}
  5322      }
  5323    if (this->statements_ != NULL)
  5324      {
  5325        if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
  5326  	return TRAVERSE_EXIT;
  5327      }
  5328    return TRAVERSE_CONTINUE;
  5329  }
  5330  
  5331  // Lowering.  We call a function to register this clause, and arrange
  5332  // to set any variables in any receive clause.
  5333  
  5334  void
  5335  Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
  5336  				     Block* b, Temporary_statement* scases,
  5337  				     int index, Temporary_statement* recvok)
  5338  {
  5339    Location loc = this->location_;
  5340  
  5341    this->set_case_index(index);
  5342  
  5343    if (this->is_default_)
  5344      {
  5345        go_assert(this->channel_ == NULL && this->val_ == NULL);
  5346        this->is_lowered_ = true;
  5347        return;
  5348      }
  5349  
  5350    Expression* scase = Expression::make_temporary_reference(scases, loc);
  5351    Expression* index_expr = Expression::make_integer_sl(index, NULL, loc);
  5352    scase = Expression::make_array_index(scase, index_expr, NULL, NULL, loc);
  5353  
  5354    // Evaluate the channel before the select statement.
  5355    Temporary_statement* channel_temp = Statement::make_temporary(NULL,
  5356  								this->channel_,
  5357  								loc);
  5358    b->add_statement(channel_temp);
  5359    Expression* chanref = Expression::make_temporary_reference(channel_temp,
  5360  							     loc);
  5361  
  5362    if (this->is_send_)
  5363      this->lower_send(b, scase, chanref);
  5364    else
  5365      this->lower_recv(gogo, function, b, scase, chanref, recvok);
  5366  
  5367    // Now all references should be handled through the statements, not
  5368    // through here.
  5369    this->is_lowered_ = true;
  5370    this->val_ = NULL;
  5371  }
  5372  
  5373  // Lower a send clause in a select statement.
  5374  
  5375  void
  5376  Select_clauses::Select_clause::lower_send(Block* b, Expression* scase,
  5377  					  Expression* chanref)
  5378  {
  5379    Location loc = this->location_;
  5380  
  5381    Channel_type* ct = this->channel_->type()->channel_type();
  5382    if (ct == NULL)
  5383      return;
  5384  
  5385    Type* valtype = ct->element_type();
  5386  
  5387    // Note that copying the value to a temporary here means that we
  5388    // evaluate the send values in the required order.
  5389    Temporary_statement* val = Statement::make_temporary(valtype, this->val_,
  5390  						       loc);
  5391    // The value here escapes, because it might be sent on a channel.
  5392    // We record that via the Temporary_statement, so that the escape
  5393    // analysis pass can pick it up.  The gc compiler lowers select
  5394    // statements after escape analysis, so it doesn't have to worry
  5395    // about this.
  5396    val->set_value_escapes();
  5397    b->add_statement(val);
  5398  
  5399    Expression* valref = Expression::make_temporary_reference(val, loc);
  5400    Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
  5401    Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
  5402    valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);
  5403  
  5404    this->set_case(b, scase, chanref, valaddr);
  5405  }
  5406  
  5407  // Lower a receive clause in a select statement.
  5408  
  5409  void
  5410  Select_clauses::Select_clause::lower_recv(Gogo* gogo, Named_object* function,
  5411  					  Block* b, Expression* scase,
  5412  					  Expression* chanref,
  5413  					  Temporary_statement* recvok)
  5414  {
  5415    Location loc = this->location_;
  5416  
  5417    Channel_type* ct = this->channel_->type()->channel_type();
  5418    if (ct == NULL)
  5419      return;
  5420  
  5421    Type* valtype = ct->element_type();
  5422    Temporary_statement* val = Statement::make_temporary(valtype, NULL, loc);
  5423    b->add_statement(val);
  5424  
  5425    Expression* valref = Expression::make_temporary_reference(val, loc);
  5426    Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
  5427    Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
  5428    valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);
  5429  
  5430    this->set_case(b, scase, chanref, valaddr);
  5431  
  5432    // If the block of statements is executed, arrange for the received
  5433    // value to move from VAL to the place where the statements expect
  5434    // it.
  5435  
  5436    Block* init = NULL;
  5437  
  5438    if (this->var_ != NULL)
  5439      {
  5440        go_assert(this->val_ == NULL);
  5441        valref = Expression::make_temporary_reference(val, loc);
  5442        this->var_->var_value()->set_init(valref);
  5443        this->var_->var_value()->clear_type_from_chan_element();
  5444      }
  5445    else if (this->val_ != NULL && !this->val_->is_sink_expression())
  5446      {
  5447        init = new Block(b, loc);
  5448        valref = Expression::make_temporary_reference(val, loc);
  5449        init->add_statement(Statement::make_assignment(this->val_, valref, loc));
  5450      }
  5451  
  5452    if (this->closedvar_ != NULL)
  5453      {
  5454        go_assert(this->closed_ == NULL);
  5455        Expression* cref = Expression::make_temporary_reference(recvok, loc);
  5456        this->closedvar_->var_value()->set_init(cref);
  5457      }
  5458    else if (this->closed_ != NULL && !this->closed_->is_sink_expression())
  5459      {
  5460        if (init == NULL)
  5461  	init = new Block(b, loc);
  5462        Expression* cref = Expression::make_temporary_reference(recvok, loc);
  5463        init->add_statement(Statement::make_assignment(this->closed_, cref,
  5464  						     loc));
  5465      }
  5466  
  5467    if (init != NULL)
  5468      {
  5469        gogo->lower_block(function, init);
  5470  
  5471        if (this->statements_ != NULL)
  5472  	init->add_statement(Statement::make_block_statement(this->statements_,
  5473  							    loc));
  5474        this->statements_ = init;
  5475      }
  5476  }
  5477  
  5478  // Set the fields of an scase struct, an element in the array that we
  5479  // pass to the runtime function selectgo.
  5480  
  5481  void
  5482  Select_clauses::Select_clause::set_case(Block* b,
  5483  					Expression* scase,
  5484  					Expression* chanref,
  5485  					Expression* elem)
  5486  {
  5487    Location loc = this->location_;
  5488    Struct_type* scase_type = scase->type()->struct_type();
  5489  
  5490    int field_index = 0;
  5491    go_assert(scase_type->field(field_index)->is_field_name("c"));
  5492    Expression* ref = Expression::make_field_reference(scase, field_index, loc);
  5493    Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
  5494    chanref = Expression::make_unsafe_cast(unsafe_pointer_type, chanref, loc);
  5495    Statement* s = Statement::make_assignment(ref, chanref, loc);
  5496    b->add_statement(s);
  5497  
  5498    if (elem != NULL)
  5499      {
  5500        field_index = 1;
  5501        go_assert(scase_type->field(field_index)->is_field_name("elem"));
  5502        ref = Expression::make_field_reference(scase->copy(), field_index, loc);
  5503        s = Statement::make_assignment(ref, elem, loc);
  5504        b->add_statement(s);
  5505      }
  5506  }
  5507  
  5508  // Determine types.
  5509  
  5510  void
  5511  Select_clauses::Select_clause::determine_types()
  5512  {
  5513    go_assert(this->is_lowered_);
  5514    if (this->statements_ != NULL)
  5515      this->statements_->determine_types();
  5516  }
  5517  
  5518  // Check types.
  5519  
  5520  void
  5521  Select_clauses::Select_clause::check_types()
  5522  {
  5523    if (this->is_default_)
  5524      return;
  5525  
  5526    Channel_type* ct = this->channel_->type()->channel_type();
  5527    if (ct == NULL)
  5528      {
  5529        go_error_at(this->channel_->location(), "expected channel");
  5530        return;
  5531      }
  5532  
  5533    if (this->is_send_ && !ct->may_send())
  5534      go_error_at(this->location(), "invalid send on receive-only channel");
  5535    else if (!this->is_send_ && !ct->may_receive())
  5536      go_error_at(this->location(), "invalid receive on send-only channel");
  5537  }
  5538  
  5539  // Whether this clause may fall through to the statement which follows
  5540  // the overall select statement.
  5541  
  5542  bool
  5543  Select_clauses::Select_clause::may_fall_through() const
  5544  {
  5545    if (this->statements_ == NULL)
  5546      return true;
  5547    return this->statements_->may_fall_through();
  5548  }
  5549  
  5550  // Return the backend representation for the statements to execute.
  5551  
  5552  Bstatement*
  5553  Select_clauses::Select_clause::get_statements_backend(
  5554      Translate_context* context)
  5555  {
  5556    if (this->statements_ == NULL)
  5557      return NULL;
  5558    Bblock* bblock = this->statements_->get_backend(context);
  5559    return context->backend()->block_statement(bblock);
  5560  }
  5561  
  5562  // Dump the AST representation for a select case clause
  5563  
  5564  void
  5565  Select_clauses::Select_clause::dump_clause(
  5566      Ast_dump_context* ast_dump_context) const
  5567  {
  5568    ast_dump_context->print_indent();
  5569    if (this->is_default_)
  5570      {
  5571        ast_dump_context->ostream() << "default:";
  5572      }
  5573    else
  5574      {
  5575        ast_dump_context->ostream() << "case "  ;
  5576        if (this->is_send_)
  5577          {
  5578            ast_dump_context->dump_expression(this->channel_);
  5579            ast_dump_context->ostream() << " <- " ;
  5580  	  if (this->val_ != NULL)
  5581  	    ast_dump_context->dump_expression(this->val_);
  5582          }
  5583        else
  5584          {
  5585  	  if (this->val_ != NULL)
  5586  	    ast_dump_context->dump_expression(this->val_);
  5587            if (this->closed_ != NULL)
  5588              {
  5589  	      // FIXME: can val_ == NULL and closed_ ! = NULL?
  5590                ast_dump_context->ostream() << " , " ;
  5591                ast_dump_context->dump_expression(this->closed_);
  5592              }
  5593            if (this->closedvar_ != NULL || this->var_ != NULL)
  5594              ast_dump_context->ostream() << " := " ;
  5595  
  5596            ast_dump_context->ostream() << " <- " ;
  5597            ast_dump_context->dump_expression(this->channel_);
  5598          }
  5599        ast_dump_context->ostream() << ":" ;
  5600      }
  5601    ast_dump_context->dump_block(this->statements_);
  5602  }
  5603  
  5604  // Class Select_clauses.
  5605  
  5606  // Whether there is a default case.
  5607  
  5608  bool
  5609  Select_clauses::has_default() const
  5610  {
  5611    for (Clauses::const_iterator p = this->clauses_.begin();
  5612         p != this->clauses_.end();
  5613         ++p)
  5614      if (p->is_default())
  5615        return true;
  5616    return false;
  5617  }
  5618  
  5619  // Traversal.
  5620  
  5621  int
  5622  Select_clauses::traverse(Traverse* traverse)
  5623  {
  5624    for (Clauses::iterator p = this->clauses_.begin();
  5625         p != this->clauses_.end();
  5626         ++p)
  5627      {
  5628        if (p->traverse(traverse) == TRAVERSE_EXIT)
  5629  	return TRAVERSE_EXIT;
  5630      }
  5631    return TRAVERSE_CONTINUE;
  5632  }
  5633  
  5634  // Lowering.  Here we pull out the channel and the send values, to
  5635  // enforce the order of evaluation.  We also add explicit send and
  5636  // receive statements to the clauses.  This builds the entries in the
  5637  // local array of scase values.  It sets *P_SEND_COUNT and
  5638  // *P_RECV_COUNT.
  5639  
  5640  void
  5641  Select_clauses::lower(Gogo* gogo, Named_object* function, Block* b,
  5642  		      Temporary_statement* scases, Temporary_statement* recvok,
  5643  		      int *p_send_count, int *p_recv_count)
  5644  {
  5645    int send_count = 0;
  5646    int recv_count = 0;
  5647    bool has_default = false;
  5648    for (Clauses::iterator p = this->clauses_.begin();
  5649         p != this->clauses_.end();
  5650         ++p)
  5651      {
  5652        if (p->is_default())
  5653  	has_default = true;
  5654        else if (p->is_send())
  5655  	++send_count;
  5656        else
  5657  	++recv_count;
  5658      }
  5659  
  5660    *p_send_count = send_count;
  5661    *p_recv_count = recv_count;
  5662  
  5663    int send_index = 0;
  5664    int recv_index = send_count;
  5665    for (Clauses::iterator p = this->clauses_.begin();
  5666         p != this->clauses_.end();
  5667         ++p)
  5668      {
  5669        int index;
  5670        if (p->is_default())
  5671  	index = -1;
  5672        else if (p->is_send())
  5673  	{
  5674  	  index = send_index;
  5675  	  ++send_index;
  5676  	}
  5677        else
  5678  	{
  5679  	  index = recv_index;
  5680  	  ++recv_index;
  5681  	}
  5682  
  5683        p->lower(gogo, function, b, scases, index, recvok);
  5684      }
  5685  
  5686    go_assert(send_index == send_count);
  5687    go_assert(recv_index == send_count + recv_count);
  5688    go_assert(static_cast<size_t>(recv_index + (has_default ? 1 : 0))
  5689  	    == this->size());
  5690  }
  5691  
  5692  // Determine types.
  5693  
  5694  void
  5695  Select_clauses::determine_types()
  5696  {
  5697    for (Clauses::iterator p = this->clauses_.begin();
  5698         p != this->clauses_.end();
  5699         ++p)
  5700      p->determine_types();
  5701  }
  5702  
  5703  // Check types.
  5704  
  5705  void
  5706  Select_clauses::check_types()
  5707  {
  5708    for (Clauses::iterator p = this->clauses_.begin();
  5709         p != this->clauses_.end();
  5710         ++p)
  5711      p->check_types();
  5712  }
  5713  
  5714  // Return whether these select clauses fall through to the statement
  5715  // following the overall select statement.
  5716  
  5717  bool
  5718  Select_clauses::may_fall_through() const
  5719  {
  5720    for (Clauses::const_iterator p = this->clauses_.begin();
  5721         p != this->clauses_.end();
  5722         ++p)
  5723      if (p->may_fall_through())
  5724        return true;
  5725    return false;
  5726  }
  5727  
  5728  // Convert to the backend representation.  Assemble the clauses and
  5729  // build a switch statement on the index value returned by the call to
  5730  // selectgo.
  5731  
  5732  Bstatement*
  5733  Select_clauses::get_backend(Translate_context* context,
  5734  			    Temporary_statement* index,
  5735  			    Unnamed_label *break_label,
  5736  			    Location location)
  5737  {
  5738    size_t count = this->clauses_.size();
  5739    std::vector<std::vector<Bexpression*> > cases(count + 1);
  5740    std::vector<Bstatement*> clauses(count + 1);
  5741  
  5742    Type* int_type = Type::lookup_integer_type("int");
  5743  
  5744    int i = 0;
  5745    for (Clauses::iterator p = this->clauses_.begin();
  5746         p != this->clauses_.end();
  5747         ++p, ++i)
  5748      {
  5749        Expression* index_expr = Expression::make_integer_sl(p->case_index(),
  5750  							   int_type,
  5751  							   location);
  5752        cases[i].push_back(index_expr->get_backend(context));
  5753  
  5754        Bstatement* s = p->get_statements_backend(context);
  5755        Location gloc = (p->statements() == NULL
  5756  		       ? p->location()
  5757  		       : p->statements()->end_location());
  5758        Bstatement* g = break_label->get_goto(context, gloc);
  5759  
  5760        if (s == NULL)
  5761  	clauses[i] = g;
  5762        else
  5763          clauses[i] = context->backend()->compound_statement(s, g);
  5764      }
  5765  
  5766    Expression* ref = Expression::make_temporary_reference(index, location);
  5767    Bexpression* bindex = ref->get_backend(context);
  5768  
  5769    Bfunction* bfunction = context->function()->func_value()->get_decl();
  5770  
  5771    if (count == 0)
  5772      return context->backend()->expression_statement(bfunction, bindex);
  5773  
  5774    Expression* crash = Runtime::make_call(Runtime::UNREACHABLE, location, 0);
  5775    Bexpression* bcrash = crash->get_backend(context);
  5776    clauses[count] = context->backend()->expression_statement(bfunction, bcrash);
  5777  
  5778    std::vector<Bstatement*> statements;
  5779    statements.reserve(2);
  5780  
  5781    Bstatement* switch_stmt = context->backend()->switch_statement(bfunction,
  5782  								 bindex,
  5783  								 cases,
  5784  								 clauses,
  5785  								 location);
  5786    statements.push_back(switch_stmt);
  5787  
  5788    Bstatement* ldef = break_label->get_definition(context);
  5789    statements.push_back(ldef);
  5790  
  5791    return context->backend()->statement_list(statements);
  5792  }
  5793  
  5794  // Dump the AST representation for select clauses.
  5795  
  5796  void
  5797  Select_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
  5798  {
  5799    for (Clauses::const_iterator p = this->clauses_.begin();
  5800         p != this->clauses_.end();
  5801         ++p)
  5802      p->dump_clause(ast_dump_context);
  5803  }
  5804  
  5805  // Class Select_statement.
  5806  
  5807  // Return the break label for this switch statement, creating it if
  5808  // necessary.
  5809  
  5810  Unnamed_label*
  5811  Select_statement::break_label()
  5812  {
  5813    if (this->break_label_ == NULL)
  5814      this->break_label_ = new Unnamed_label(this->location());
  5815    return this->break_label_;
  5816  }
  5817  
  5818  // Lower a select statement.  This will return a block containing this
  5819  // select statement.  The block will implement the order of evaluation
  5820  // rules, include the send and receive statements as explicit
  5821  // statements in the clauses, and call the runtime selectgo function.
  5822  
  5823  Statement*
  5824  Select_statement::do_lower(Gogo* gogo, Named_object* function,
  5825  			   Block* enclosing, Statement_inserter*)
  5826  {
  5827    if (this->is_lowered_)
  5828      return this;
  5829  
  5830    Location loc = this->location();
  5831  
  5832    Block* b = new Block(enclosing, loc);
  5833  
  5834    int ncases = this->clauses_->size();
  5835    bool has_default = this->clauses_->has_default();
  5836  
  5837    // Zero-case select.  Just block the execution.
  5838    if (ncases == 0)
  5839      {
  5840        Expression* call = Runtime::make_call(Runtime::BLOCK, loc, 0);
  5841        Statement *s = Statement::make_statement(call, false);
  5842        b->add_statement(s);
  5843        this->is_lowered_ = true;
  5844        return Statement::make_block_statement(b, loc);
  5845      }
  5846  
  5847    // One-case select.  It is mostly just to run the case.
  5848    if (ncases == 1)
  5849      return this->lower_one_case(b);
  5850  
  5851    // Two-case select with one default case.  It is a non-blocking
  5852    // send/receive.
  5853    if (ncases == 2 && has_default)
  5854      return this->lower_two_case(b);
  5855  
  5856    // We don't allocate an entry in scases for the default case.
  5857    if (has_default)
  5858      --ncases;
  5859  
  5860    Type* scase_type = Channel_type::select_case_type();
  5861    Expression* ncases_expr =
  5862      Expression::make_integer_ul(ncases, NULL,
  5863  				Linemap::predeclared_location());
  5864    Array_type* scases_type = Type::make_array_type(scase_type, ncases_expr);
  5865    scases_type->set_is_array_incomparable();
  5866  
  5867    Temporary_statement* scases = Statement::make_temporary(scases_type, NULL,
  5868  							  loc);
  5869    b->add_statement(scases);
  5870  
  5871    Expression* ncases2_expr =
  5872      Expression::make_integer_ul(ncases * 2, NULL,
  5873  				Linemap::predeclared_location());
  5874    Type* uint16_type = Type::lookup_integer_type("uint16");
  5875    Array_type* order_type = Type::make_array_type(uint16_type, ncases2_expr);
  5876    order_type->set_is_array_incomparable();
  5877  
  5878    Temporary_statement* order = Statement::make_temporary(order_type, NULL,
  5879  							 loc);
  5880    b->add_statement(order);
  5881  
  5882    Type* int_type = Type::lookup_integer_type("int");
  5883    this->index_ = Statement::make_temporary(int_type, NULL, loc);
  5884    b->add_statement(this->index_);
  5885  
  5886    Type* bool_type = Type::lookup_bool_type();
  5887    Temporary_statement* recvok = Statement::make_temporary(bool_type, NULL,
  5888  							  loc);
  5889    b->add_statement(recvok);
  5890  
  5891    // Initialize the scases array.
  5892    int send_count;
  5893    int recv_count;
  5894    this->clauses_->lower(gogo, function, b, scases, recvok, &send_count,
  5895  			&recv_count);
  5896  
  5897    // Build the call to selectgo.  Later, in do_get_backend, we will
  5898    // build a switch on the result that branches to the various cases.
  5899  
  5900    Expression* scases_ref = Expression::make_temporary_reference(scases, loc);
  5901    scases_ref = Expression::make_unary(OPERATOR_AND, scases_ref, loc);
  5902    Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
  5903    scases_ref = Expression::make_cast(unsafe_pointer_type, scases_ref, loc);
  5904  
  5905    Expression* order_ref = Expression::make_temporary_reference(order, loc);
  5906    order_ref = Expression::make_unary(OPERATOR_AND, order_ref, loc);
  5907    order_ref = Expression::make_cast(unsafe_pointer_type, order_ref, loc);
  5908  
  5909    Expression* send_count_expr = Expression::make_integer_sl(send_count,
  5910  							    int_type,
  5911  							    loc);
  5912    Expression* recv_count_expr = Expression::make_integer_sl(recv_count,
  5913  							    int_type,
  5914  							    loc);
  5915    Expression* block_expr = Expression::make_boolean(!has_default, loc);
  5916  
  5917    Call_expression* call = Runtime::make_call(Runtime::SELECTGO, loc, 5,
  5918  					     scases_ref, order_ref,
  5919  					     send_count_expr, recv_count_expr,
  5920  					     block_expr);
  5921  
  5922    Expression* result = Expression::make_call_result(call, 0);
  5923    Expression* ref = Expression::make_temporary_reference(this->index_, loc);
  5924    Statement* s = Statement::make_assignment(ref, result, loc);
  5925    b->add_statement(s);
  5926  
  5927    result = Expression::make_call_result(call, 1);
  5928    ref = Expression::make_temporary_reference(recvok, loc);
  5929    s = Statement::make_assignment(ref, result, loc);
  5930    b->add_statement(s);
  5931  
  5932    this->is_lowered_ = true;
  5933    b->add_statement(this);
  5934  
  5935    return Statement::make_block_statement(b, loc);
  5936  }
  5937  
  5938  // Lower a one-case select statement.
  5939  
  5940  Statement*
  5941  Select_statement::lower_one_case(Block* b)
  5942  {
  5943    Select_clauses::Select_clause& scase = this->clauses_->at(0);
  5944    Location loc = this->location();
  5945    Expression* chan = scase.channel();
  5946    if (chan != NULL)
  5947      {
  5948        // Lower this to
  5949        //   if chan == nil { block() }; send/recv; body
  5950        Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc);
  5951        b->add_statement(chantmp);
  5952        Expression* chanref = Expression::make_temporary_reference(chantmp, loc);
  5953  
  5954        Expression* nil = Expression::make_nil(loc);
  5955        Expression* cond = Expression::make_binary(OPERATOR_EQEQ, chanref, nil, loc);
  5956        Block* bnil = new Block(b, loc);
  5957        Expression* call = Runtime::make_call(Runtime::BLOCK, loc, 0);
  5958        Statement* s = Statement::make_statement(call, false);
  5959        bnil->add_statement(s);
  5960        Statement* ifs = Statement::make_if_statement(cond, bnil, NULL, loc);
  5961        b->add_statement(ifs);
  5962  
  5963        chanref = chanref->copy();
  5964        Location cloc = scase.location();
  5965        if (scase.is_send())
  5966          {
  5967            s = Statement::make_send_statement(chanref, scase.val(), cloc);
  5968            b->add_statement(s);
  5969          }
  5970        else
  5971          {
  5972            if (scase.closed() == NULL && scase.closedvar() == NULL)
  5973              {
  5974                // Simple receive.
  5975                Expression* recv = Expression::make_receive(chanref, cloc);
  5976                if (scase.val() != NULL)
  5977                  s = Statement::make_assignment(scase.val(), recv, cloc);
  5978                else if (scase.var() != NULL)
  5979                  {
  5980                    Temporary_statement *ts =
  5981                      Statement::make_temporary(NULL, recv, cloc);
  5982                    Expression* ref =
  5983                      Expression::make_temporary_reference(ts, cloc);
  5984                    s = ts;
  5985                    scase.var()->var_value()->set_init(ref);
  5986                    scase.var()->var_value()->clear_type_from_chan_element();
  5987                  }
  5988                else
  5989                  s = Statement::make_statement(recv, false);
  5990                b->add_statement(s);
  5991              }
  5992            else
  5993              {
  5994                // Tuple receive.
  5995                Expression* lhs;
  5996                if (scase.val() != NULL)
  5997                  lhs = scase.val();
  5998                else
  5999                  {
  6000                    Type* valtype = chan->type()->channel_type()->element_type();
  6001                    Temporary_statement *ts =
  6002                      Statement::make_temporary(valtype, NULL, cloc);
  6003                    lhs = Expression::make_temporary_reference(ts, cloc);
  6004                    b->add_statement(ts);
  6005                  }
  6006  
  6007                Expression* lhs2;
  6008                if (scase.closed() != NULL)
  6009                  lhs2 = scase.closed();
  6010                else
  6011                  {
  6012                    Type* booltype = Type::make_boolean_type();
  6013                    Temporary_statement *ts =
  6014                      Statement::make_temporary(booltype, NULL, cloc);
  6015                    lhs2 = Expression::make_temporary_reference(ts, cloc);
  6016                    b->add_statement(ts);
  6017                  }
  6018  
  6019                s = Statement::make_tuple_receive_assignment(lhs, lhs2, chanref, cloc);
  6020                b->add_statement(s);
  6021  
  6022                if (scase.var() != NULL)
  6023                  {
  6024                    scase.var()->var_value()->set_init(lhs->copy());
  6025                    scase.var()->var_value()->clear_type_from_chan_element();
  6026                  }
  6027  
  6028                if (scase.closedvar() != NULL)
  6029                  scase.closedvar()->var_value()->set_init(lhs2->copy());
  6030              }
  6031          }
  6032      }
  6033  
  6034    Statement* bs =
  6035      Statement::make_block_statement(scase.statements(), scase.location());
  6036    b->add_statement(bs);
  6037  
  6038    Statement* label =
  6039      Statement::make_unnamed_label_statement(this->break_label());
  6040    b->add_statement(label);
  6041  
  6042    this->is_lowered_ = true;
  6043    return Statement::make_block_statement(b, loc);
  6044  }
  6045  
  6046  // Lower a two-case select statement with one default case.
  6047  
  6048  Statement*
  6049  Select_statement::lower_two_case(Block* b)
  6050  {
  6051    Select_clauses::Select_clause& chancase =
  6052      (this->clauses_->at(0).is_default()
  6053       ? this->clauses_->at(1)
  6054       : this->clauses_->at(0));
  6055    Select_clauses::Select_clause& defcase =
  6056      (this->clauses_->at(0).is_default()
  6057       ? this->clauses_->at(0)
  6058       : this->clauses_->at(1));
  6059    Location loc = this->location();
  6060    Expression* chan = chancase.channel();
  6061    Type* valtype = chan->type()->channel_type()->element_type();
  6062  
  6063    Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc);
  6064    b->add_statement(chantmp);
  6065    Expression* chanref = Expression::make_temporary_reference(chantmp, loc);
  6066  
  6067    Block* bchan;
  6068    Expression* cond;
  6069    if (chancase.is_send())
  6070      {
  6071        // if selectnbsend(chan, &val) { body } else { default body }
  6072  
  6073        Temporary_statement* ts =
  6074          Statement::make_temporary(valtype, chancase.val(), loc);
  6075        // Tell the escape analysis that the value escapes, as it may be sent
  6076        // to a channel.
  6077        ts->set_value_escapes();
  6078        b->add_statement(ts);
  6079  
  6080        Expression* ref = Expression::make_temporary_reference(ts, loc);
  6081        Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
  6082        cond = Runtime::make_call(Runtime::SELECTNBSEND, loc, 2, chanref, addr);
  6083        bchan = chancase.statements();
  6084      }
  6085    else
  6086      {
  6087        Temporary_statement* ts = Statement::make_temporary(valtype, NULL, loc);
  6088        b->add_statement(ts);
  6089  
  6090        Expression* ref = Expression::make_temporary_reference(ts, loc);
  6091        Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
  6092  
  6093        // selected, ok = selectnbrecv(&lhs, chan)
  6094        Call_expression* call = Runtime::make_call(Runtime::SELECTNBRECV, loc, 2,
  6095  						 addr, chanref);
  6096  
  6097        Temporary_statement* selected_temp =
  6098  	Statement::make_temporary(Type::make_boolean_type(),
  6099  				  Expression::make_call_result(call, 0),
  6100  				  loc);
  6101        b->add_statement(selected_temp);
  6102  
  6103        Temporary_statement* ok_temp =
  6104  	Statement::make_temporary(Type::make_boolean_type(),
  6105  				  Expression::make_call_result(call, 1),
  6106  				  loc);
  6107        b->add_statement(ok_temp);
  6108  
  6109        cond = Expression::make_temporary_reference(selected_temp, loc);
  6110  
  6111        Location cloc = chancase.location();
  6112        bchan = new Block(b, loc);
  6113        if (chancase.val() != NULL && !chancase.val()->is_sink_expression())
  6114          {
  6115            Statement* as = Statement::make_assignment(chancase.val(),
  6116  						     ref->copy(),
  6117                                                       cloc);
  6118            bchan->add_statement(as);
  6119          }
  6120        else if (chancase.var() != NULL)
  6121          {
  6122            chancase.var()->var_value()->set_init(ref->copy());
  6123            chancase.var()->var_value()->clear_type_from_chan_element();
  6124          }
  6125  
  6126        if (chancase.closed() != NULL && !chancase.closed()->is_sink_expression())
  6127          {
  6128  	  Expression* okref = Expression::make_temporary_reference(ok_temp,
  6129  								   cloc);
  6130            Statement* as = Statement::make_assignment(chancase.closed(),
  6131                                                       okref, cloc);
  6132            bchan->add_statement(as);
  6133          }
  6134        else if (chancase.closedvar() != NULL)
  6135  	{
  6136  	  Expression* okref = Expression::make_temporary_reference(ok_temp,
  6137  								   cloc);
  6138  	  chancase.closedvar()->var_value()->set_init(okref);
  6139  	}
  6140  
  6141        Statement* bs = Statement::make_block_statement(chancase.statements(),
  6142                                                        cloc);
  6143        bchan->add_statement(bs);
  6144      }
  6145  
  6146    Statement* ifs =
  6147      Statement::make_if_statement(cond, bchan, defcase.statements(), loc);
  6148    b->add_statement(ifs);
  6149  
  6150    Statement* label =
  6151      Statement::make_unnamed_label_statement(this->break_label());
  6152    b->add_statement(label);
  6153  
  6154    this->is_lowered_ = true;
  6155    return Statement::make_block_statement(b, loc);
  6156  }
  6157  
  6158  // Whether the select statement itself may fall through to the following
  6159  // statement.
  6160  
  6161  bool
  6162  Select_statement::do_may_fall_through() const
  6163  {
  6164    // A select statement is terminating if no break statement
  6165    // refers to it and all of its clauses are terminating.
  6166    if (this->break_label_ != NULL)
  6167      return true;
  6168    return this->clauses_->may_fall_through();
  6169  }
  6170  
  6171  // Return the backend representation for a select statement.
  6172  
  6173  Bstatement*
  6174  Select_statement::do_get_backend(Translate_context* context)
  6175  {
  6176    return this->clauses_->get_backend(context, this->index_,
  6177  				     this->break_label(), this->location());
  6178  }
  6179  
  6180  // Dump the AST representation for a select statement.
  6181  
  6182  void
  6183  Select_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
  6184  {
  6185    ast_dump_context->print_indent();
  6186    ast_dump_context->ostream() << "select";
  6187    if (ast_dump_context->dump_subblocks())
  6188      {
  6189        ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
  6190        this->clauses_->dump_clauses(ast_dump_context);
  6191        ast_dump_context->print_indent();
  6192        ast_dump_context->ostream() << "}";
  6193      }
  6194    ast_dump_context->ostream() << std::endl;
  6195  }
  6196  
  6197  // Make a select statement.
  6198  
  6199  Select_statement*
  6200  Statement::make_select_statement(Location location)
  6201  {
  6202    return new Select_statement(location);
  6203  }
  6204  
  6205  // Class For_statement.
  6206  
  6207  // Traversal.
  6208  
  6209  int
  6210  For_statement::do_traverse(Traverse* traverse)
  6211  {
  6212    if (this->init_ != NULL)
  6213      {
  6214        if (this->init_->traverse(traverse) == TRAVERSE_EXIT)
  6215  	return TRAVERSE_EXIT;
  6216      }
  6217    if (this->cond_ != NULL)
  6218      {
  6219        if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT)
  6220  	return TRAVERSE_EXIT;
  6221      }
  6222    if (this->post_ != NULL)
  6223      {
  6224        if (this->post_->traverse(traverse) == TRAVERSE_EXIT)
  6225  	return TRAVERSE_EXIT;
  6226      }
  6227    return this->statements_->traverse(traverse);
  6228  }
  6229  
  6230  // Lower a For_statement into if statements and gotos.  Getting rid of
  6231  // complex statements make it easier to handle garbage collection.
  6232  
  6233  Statement*
  6234  For_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
  6235  			Statement_inserter*)
  6236  {
  6237    Statement* s;
  6238    Location loc = this->location();
  6239  
  6240    Block* b = new Block(enclosing, this->location());
  6241    if (this->init_ != NULL)
  6242      {
  6243        s = Statement::make_block_statement(this->init_,
  6244  					  this->init_->start_location());
  6245        b->add_statement(s);
  6246      }
  6247  
  6248    Unnamed_label* entry = NULL;
  6249    if (this->cond_ != NULL)
  6250      {
  6251        entry = new Unnamed_label(this->location());
  6252        b->add_statement(Statement::make_goto_unnamed_statement(entry, loc));
  6253      }
  6254  
  6255    Unnamed_label* top = new Unnamed_label(this->location());
  6256    top->set_derived_from(this);
  6257    b->add_statement(Statement::make_unnamed_label_statement(top));
  6258  
  6259    s = Statement::make_block_statement(this->statements_,
  6260  				      this->statements_->start_location());
  6261    b->add_statement(s);
  6262  
  6263    Location end_loc = this->statements_->end_location();
  6264  
  6265    Unnamed_label* cont = this->continue_label_;
  6266    if (cont != NULL)
  6267      b->add_statement(Statement::make_unnamed_label_statement(cont));
  6268  
  6269    if (this->post_ != NULL)
  6270      {
  6271        s = Statement::make_block_statement(this->post_,
  6272  					  this->post_->start_location());
  6273        b->add_statement(s);
  6274        end_loc = this->post_->end_location();
  6275      }
  6276  
  6277    if (this->cond_ == NULL)
  6278      b->add_statement(Statement::make_goto_unnamed_statement(top, end_loc));
  6279    else
  6280      {
  6281        b->add_statement(Statement::make_unnamed_label_statement(entry));
  6282  
  6283        Location cond_loc = this->cond_->location();
  6284        Block* then_block = new Block(b, cond_loc);
  6285        s = Statement::make_goto_unnamed_statement(top, cond_loc);
  6286        then_block->add_statement(s);
  6287  
  6288        s = Statement::make_if_statement(this->cond_, then_block, NULL, cond_loc);
  6289        b->add_statement(s);
  6290      }
  6291  
  6292    Unnamed_label* brk = this->break_label_;
  6293    if (brk != NULL)
  6294      b->add_statement(Statement::make_unnamed_label_statement(brk));
  6295  
  6296    b->set_end_location(end_loc);
  6297  
  6298    Statement* bs = Statement::make_block_statement(b, loc);
  6299    bs->block_statement()->set_is_lowered_for_statement();
  6300    return bs;
  6301  }
  6302  
  6303  // Return the break label, creating it if necessary.
  6304  
  6305  Unnamed_label*
  6306  For_statement::break_label()
  6307  {
  6308    if (this->break_label_ == NULL)
  6309      this->break_label_ = new Unnamed_label(this->location());
  6310    return this->break_label_;
  6311  }
  6312  
  6313  // Return the continue LABEL_EXPR.
  6314  
  6315  Unnamed_label*
  6316  For_statement::continue_label()
  6317  {
  6318    if (this->continue_label_ == NULL)
  6319      this->continue_label_ = new Unnamed_label(this->location());
  6320    return this->continue_label_;
  6321  }
  6322  
  6323  // Set the break and continue labels a for statement.  This is used
  6324  // when lowering a for range statement.
  6325  
  6326  void
  6327  For_statement::set_break_continue_labels(Unnamed_label* break_label,
  6328  					 Unnamed_label* continue_label)
  6329  {
  6330    go_assert(this->break_label_ == NULL && this->continue_label_ == NULL);
  6331    this->break_label_ = break_label;
  6332    this->continue_label_ = continue_label;
  6333  }
  6334  
  6335  // Whether the overall statement may fall through.
  6336  
  6337  bool
  6338  For_statement::do_may_fall_through() const
  6339  {
  6340    // A for loop is terminating if it has no condition and
  6341    // no break statement.
  6342    if(this->cond_ != NULL)
  6343      return true;
  6344    if(this->break_label_ != NULL)
  6345      return true;
  6346    return false;
  6347  }
  6348  
  6349  // Dump the AST representation for a for statement.
  6350  
  6351  void
  6352  For_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
  6353  {
  6354    if (this->init_ != NULL && ast_dump_context->dump_subblocks())
  6355      {
  6356        ast_dump_context->print_indent();
  6357        ast_dump_context->indent();
  6358        ast_dump_context->ostream() << "// INIT  " << std::endl;
  6359        ast_dump_context->dump_block(this->init_);
  6360        ast_dump_context->unindent();
  6361      }
  6362    ast_dump_context->print_indent();
  6363    ast_dump_context->ostream() << "for ";
  6364    if (this->cond_ != NULL)
  6365      ast_dump_context->dump_expression(this->cond_);
  6366  
  6367    if (ast_dump_context->dump_subblocks())
  6368      {
  6369        ast_dump_context->ostream() << " {" << std::endl;
  6370        ast_dump_context->dump_block(this->statements_);
  6371        if (this->init_ != NULL)
  6372  	{
  6373  	  ast_dump_context->print_indent();
  6374  	  ast_dump_context->ostream() << "// POST " << std::endl;
  6375  	  ast_dump_context->dump_block(this->post_);
  6376  	}
  6377        ast_dump_context->unindent();
  6378  
  6379        ast_dump_context->print_indent();
  6380        ast_dump_context->ostream() << "}";
  6381      }
  6382  
  6383    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  6384  }
  6385  
  6386  // Make a for statement.
  6387  
  6388  For_statement*
  6389  Statement::make_for_statement(Block* init, Expression* cond, Block* post,
  6390  			      Location location)
  6391  {
  6392    return new For_statement(init, cond, post, location);
  6393  }
  6394  
  6395  // Class For_range_statement.
  6396  
  6397  // Traversal.
  6398  
  6399  int
  6400  For_range_statement::do_traverse(Traverse* traverse)
  6401  {
  6402    if (this->index_var_ != NULL)
  6403      {
  6404        if (this->traverse_expression(traverse, &this->index_var_)
  6405  	  == TRAVERSE_EXIT)
  6406  	return TRAVERSE_EXIT;
  6407      }
  6408    if (this->value_var_ != NULL)
  6409      {
  6410        if (this->traverse_expression(traverse, &this->value_var_)
  6411  	  == TRAVERSE_EXIT)
  6412  	return TRAVERSE_EXIT;
  6413      }
  6414    if (this->traverse_expression(traverse, &this->range_) == TRAVERSE_EXIT)
  6415      return TRAVERSE_EXIT;
  6416    return this->statements_->traverse(traverse);
  6417  }
  6418  
  6419  // Lower a for range statement.  For simplicity we lower this into a
  6420  // for statement, which will then be lowered in turn to goto
  6421  // statements.
  6422  
  6423  Statement*
  6424  For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
  6425  			      Statement_inserter*)
  6426  {
  6427    Type* range_type = this->range_->type();
  6428    if (range_type->points_to() != NULL
  6429        && range_type->points_to()->array_type() != NULL
  6430        && !range_type->points_to()->is_slice_type())
  6431      range_type = range_type->points_to();
  6432  
  6433    Type* index_type;
  6434    Type* value_type = NULL;
  6435    if (range_type->array_type() != NULL)
  6436      {
  6437        index_type = Type::lookup_integer_type("int");
  6438        value_type = range_type->array_type()->element_type();
  6439      }
  6440    else if (range_type->is_string_type())
  6441      {
  6442        index_type = Type::lookup_integer_type("int");
  6443        value_type = Type::lookup_integer_type("rune");
  6444      }
  6445    else if (range_type->map_type() != NULL)
  6446      {
  6447        index_type = range_type->map_type()->key_type();
  6448        value_type = range_type->map_type()->val_type();
  6449      }
  6450    else if (range_type->channel_type() != NULL)
  6451      {
  6452        index_type = range_type->channel_type()->element_type();
  6453        if (this->value_var_ != NULL)
  6454  	{
  6455  	  if (!this->value_var_->type()->is_error())
  6456  	    this->report_error(_("too many variables for range clause "
  6457  				 "with channel"));
  6458  	  return Statement::make_error_statement(this->location());
  6459  	}
  6460      }
  6461    else
  6462      {
  6463        this->report_error(_("range clause must have "
  6464  			   "array, slice, string, map, or channel type"));
  6465        return Statement::make_error_statement(this->location());
  6466      }
  6467  
  6468    // If there is only one iteration variable, and len(this->range_) is
  6469    // constant, then we do not evaluate the range variable.  len(x) is
  6470    // a contant if x is a string constant or if x is an array.  If x is
  6471    // a constant then evaluating it won't make any difference, so the
  6472    // only case to consider is when x is an array whose length is constant.
  6473    bool eval = true;
  6474    if ((this->value_var_ == NULL || this->value_var_->is_sink_expression())
  6475        && range_type->array_type() != NULL
  6476        && !range_type->is_slice_type()
  6477        && Builtin_call_expression::array_len_is_constant(this->range_))
  6478      eval = false;
  6479  
  6480    Location loc = this->location();
  6481    Block* temp_block = new Block(enclosing, loc);
  6482  
  6483    Expression* orig_range_expr = this->range_;
  6484    Named_object* range_object = NULL;
  6485    Temporary_statement* range_temp = NULL;
  6486    if (eval)
  6487      {
  6488        Var_expression* ve = this->range_->var_expression();
  6489        if (ve != NULL)
  6490  	range_object = ve->named_object();
  6491        else
  6492  	{
  6493  	  range_temp = Statement::make_temporary(NULL, this->range_, loc);
  6494  	  temp_block->add_statement(range_temp);
  6495  	  this->range_ = NULL;
  6496  	}
  6497      }
  6498  
  6499    // Try to match "range clear" patterns and rewrite to simple runtime
  6500    // calls.
  6501    if (range_type->map_type() != NULL)
  6502      {
  6503        Statement* clear = this->lower_map_range_clear(range_type,
  6504                                                       enclosing,
  6505                                                       orig_range_expr,
  6506                                                       range_object,
  6507                                                       range_temp, loc);
  6508        if (clear != NULL)
  6509          {
  6510            if (gogo->debug_optimization())
  6511              go_debug(loc, "map range clear");
  6512            temp_block->add_statement(clear);
  6513            return Statement::make_block_statement(temp_block, loc);
  6514          }
  6515      }
  6516    else if (range_type->array_type() != NULL)
  6517      {
  6518        // Slice or array.
  6519        Statement* clear = this->lower_array_range_clear(gogo,
  6520                                                         range_type,
  6521                                                         orig_range_expr,
  6522                                                         temp_block,
  6523                                                         range_object,
  6524                                                         range_temp, loc);
  6525        if (clear != NULL)
  6526          {
  6527            if (gogo->debug_optimization())
  6528              go_debug(loc, "array range clear");
  6529            temp_block->add_statement(clear);
  6530            return Statement::make_block_statement(temp_block, loc);
  6531          }
  6532      }
  6533  
  6534    Temporary_statement* index_temp = Statement::make_temporary(index_type,
  6535  							      NULL, loc);
  6536    temp_block->add_statement(index_temp);
  6537  
  6538    Temporary_statement* value_temp = NULL;
  6539    if (this->value_var_ != NULL && !this->value_var_->is_sink_expression())
  6540      {
  6541        value_temp = Statement::make_temporary(value_type, NULL, loc);
  6542        temp_block->add_statement(value_temp);
  6543      }
  6544  
  6545    Block* body = new Block(temp_block, loc);
  6546  
  6547    Block* init;
  6548    Expression* cond;
  6549    Block* iter_init;
  6550    Block* post;
  6551  
  6552    // Arrange to do a loop appropriate for the type.  We will produce
  6553    //   for INIT ; COND ; POST {
  6554    //           ITER_INIT
  6555    //           INDEX = INDEX_TEMP
  6556    //           VALUE = VALUE_TEMP // If there is a value
  6557    //           original statements
  6558    //   }
  6559  
  6560    if (range_type->is_slice_type())
  6561      this->lower_range_slice(gogo, temp_block, body, range_object, range_temp,
  6562  			    index_temp, value_temp, &init, &cond, &iter_init,
  6563  			    &post);
  6564    else if (range_type->array_type() != NULL)
  6565      this->lower_range_array(gogo, temp_block, body, range_object, range_temp,
  6566  			    index_temp, value_temp, &init, &cond, &iter_init,
  6567  			    &post);
  6568    else if (range_type->is_string_type())
  6569      this->lower_range_string(gogo, temp_block, body, range_object, range_temp,
  6570  			     index_temp, value_temp, &init, &cond, &iter_init,
  6571  			     &post);
  6572    else if (range_type->map_type() != NULL)
  6573      this->lower_range_map(gogo, range_type->map_type(), temp_block, body,
  6574  			  range_object, range_temp, index_temp, value_temp,
  6575  			  &init, &cond, &iter_init, &post);
  6576    else if (range_type->channel_type() != NULL)
  6577      this->lower_range_channel(gogo, temp_block, body, range_object, range_temp,
  6578  			      index_temp, value_temp, &init, &cond, &iter_init,
  6579  			      &post);
  6580    else
  6581      go_unreachable();
  6582  
  6583    if (iter_init != NULL)
  6584      body->add_statement(Statement::make_block_statement(iter_init, loc));
  6585  
  6586    if (this->index_var_ != NULL)
  6587      {
  6588        Statement* assign;
  6589        Expression* index_ref =
  6590  	Expression::make_temporary_reference(index_temp, loc);
  6591        if (this->value_var_ == NULL || this->value_var_->is_sink_expression())
  6592  	assign = Statement::make_assignment(this->index_var_, index_ref, loc);
  6593        else
  6594  	{
  6595  	  Expression_list* lhs = new Expression_list();
  6596  	  lhs->push_back(this->index_var_);
  6597  	  lhs->push_back(this->value_var_);
  6598  
  6599  	  Expression_list* rhs = new Expression_list();
  6600  	  rhs->push_back(index_ref);
  6601  	  rhs->push_back(Expression::make_temporary_reference(value_temp, loc));
  6602  
  6603  	  assign = Statement::make_tuple_assignment(lhs, rhs, loc);
  6604  	}
  6605        body->add_statement(assign);
  6606      }
  6607  
  6608    body->add_statement(Statement::make_block_statement(this->statements_, loc));
  6609  
  6610    body->set_end_location(this->statements_->end_location());
  6611  
  6612    For_statement* loop = Statement::make_for_statement(init, cond, post,
  6613  						      this->location());
  6614    loop->add_statements(body);
  6615    loop->set_break_continue_labels(this->break_label_, this->continue_label_);
  6616  
  6617    temp_block->add_statement(loop);
  6618  
  6619    return Statement::make_block_statement(temp_block, loc);
  6620  }
  6621  
  6622  // Return a reference to the range, which may be in RANGE_OBJECT or in
  6623  // RANGE_TEMP.
  6624  
  6625  Expression*
  6626  For_range_statement::make_range_ref(Named_object* range_object,
  6627  				    Temporary_statement* range_temp,
  6628  				    Location loc)
  6629  {
  6630    if (range_object != NULL)
  6631      return Expression::make_var_reference(range_object, loc);
  6632    else
  6633      return Expression::make_temporary_reference(range_temp, loc);
  6634  }
  6635  
  6636  // Return a call to the predeclared function FUNCNAME passing a
  6637  // reference to the temporary variable ARG.
  6638  
  6639  Call_expression*
  6640  For_range_statement::call_builtin(Gogo* gogo, const char* funcname,
  6641  				  Expression* arg,
  6642  				  Location loc)
  6643  {
  6644    Named_object* no = gogo->lookup_global(funcname);
  6645    go_assert(no != NULL && no->is_function_declaration());
  6646    Expression* func = Expression::make_func_reference(no, NULL, loc);
  6647    Expression_list* params = new Expression_list();
  6648    params->push_back(arg);
  6649    return Expression::make_call(func, params, false, loc);
  6650  }
  6651  
  6652  // Lower a for range over an array.
  6653  
  6654  void
  6655  For_range_statement::lower_range_array(Gogo* gogo,
  6656  				       Block* enclosing,
  6657  				       Block* body_block,
  6658  				       Named_object* range_object,
  6659  				       Temporary_statement* range_temp,
  6660  				       Temporary_statement* index_temp,
  6661  				       Temporary_statement* value_temp,
  6662  				       Block** pinit,
  6663  				       Expression** pcond,
  6664  				       Block** piter_init,
  6665  				       Block** ppost)
  6666  {
  6667    Location loc = this->location();
  6668  
  6669    // The loop we generate:
  6670    //   len_temp := len(range)
  6671    //   range_temp := range
  6672    //   for index_temp = 0; index_temp < len_temp; index_temp++ {
  6673    //           value_temp = range_temp[index_temp]
  6674    //           index = index_temp
  6675    //           value = value_temp
  6676    //           original body
  6677    //   }
  6678  
  6679    // Set *PINIT to
  6680    //   var len_temp int
  6681    //   len_temp = len(range)
  6682    //   index_temp = 0
  6683  
  6684    Block* init = new Block(enclosing, loc);
  6685  
  6686    Expression* len_arg;
  6687    if (range_object == NULL && range_temp == NULL)
  6688      {
  6689        // Don't evaluate this->range_, just get its length.
  6690        len_arg = this->range_;
  6691      }
  6692    else
  6693      {
  6694        Expression* ref = this->make_range_ref(range_object, range_temp, loc);
  6695        range_temp = Statement::make_temporary(NULL, ref, loc);
  6696        init->add_statement(range_temp);
  6697        len_arg = ref;
  6698      }
  6699    Expression* len_call = this->call_builtin(gogo, "len", len_arg, loc);
  6700    Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
  6701  							    len_call, loc);
  6702    init->add_statement(len_temp);
  6703  
  6704    Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);
  6705  
  6706    Temporary_reference_expression* tref =
  6707      Expression::make_temporary_reference(index_temp, loc);
  6708    tref->set_is_lvalue();
  6709    Statement* s = Statement::make_assignment(tref, zexpr, loc);
  6710    init->add_statement(s);
  6711  
  6712    *pinit = init;
  6713  
  6714    // Set *PCOND to
  6715    //   index_temp < len_temp
  6716  
  6717    Expression* ref = Expression::make_temporary_reference(index_temp, loc);
  6718    Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
  6719    Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);
  6720  
  6721    *pcond = lt;
  6722  
  6723    // Set *PITER_INIT to
  6724    //   value_temp = range[index_temp]
  6725  
  6726    Block* iter_init = NULL;
  6727    if (value_temp != NULL)
  6728      {
  6729        iter_init = new Block(body_block, loc);
  6730  
  6731        ref = Expression::make_temporary_reference(range_temp, loc);
  6732        ref2 = Expression::make_temporary_reference(index_temp, loc);
  6733        Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
  6734  
  6735        tref = Expression::make_temporary_reference(value_temp, loc);
  6736        tref->set_is_lvalue();
  6737        s = Statement::make_assignment(tref, index, loc);
  6738  
  6739        iter_init->add_statement(s);
  6740      }
  6741    *piter_init = iter_init;
  6742  
  6743    // Set *PPOST to
  6744    //   index_temp++
  6745  
  6746    Block* post = new Block(enclosing, loc);
  6747    tref = Expression::make_temporary_reference(index_temp, loc);
  6748    tref->set_is_lvalue();
  6749    s = Statement::make_inc_statement(tref);
  6750    post->add_statement(s);
  6751    *ppost = post;
  6752  }
  6753  
  6754  // Lower a for range over a slice.
  6755  
  6756  void
  6757  For_range_statement::lower_range_slice(Gogo* gogo,
  6758  				       Block* enclosing,
  6759  				       Block* body_block,
  6760  				       Named_object* range_object,
  6761  				       Temporary_statement* range_temp,
  6762  				       Temporary_statement* index_temp,
  6763  				       Temporary_statement* value_temp,
  6764  				       Block** pinit,
  6765  				       Expression** pcond,
  6766  				       Block** piter_init,
  6767  				       Block** ppost)
  6768  {
  6769    Location loc = this->location();
  6770  
  6771    // The loop we generate:
  6772    //   for_temp := range
  6773    //   len_temp := len(for_temp)
  6774    //   for index_temp = 0; index_temp < len_temp; index_temp++ {
  6775    //           value_temp = for_temp[index_temp]
  6776    //           index = index_temp
  6777    //           value = value_temp
  6778    //           original body
  6779    //   }
  6780    //
  6781    // Using for_temp means that we don't need to check bounds when
  6782    // fetching range_temp[index_temp].
  6783  
  6784    // Set *PINIT to
  6785    //   range_temp := range
  6786    //   var len_temp int
  6787    //   len_temp = len(range_temp)
  6788    //   index_temp = 0
  6789  
  6790    Block* init = new Block(enclosing, loc);
  6791  
  6792    Expression* ref = this->make_range_ref(range_object, range_temp, loc);
  6793    Temporary_statement* for_temp = Statement::make_temporary(NULL, ref, loc);
  6794    init->add_statement(for_temp);
  6795  
  6796    ref = Expression::make_temporary_reference(for_temp, loc);
  6797    Expression* len_call = this->call_builtin(gogo, "len", ref, loc);
  6798    Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
  6799  							    len_call, loc);
  6800    init->add_statement(len_temp);
  6801  
  6802    Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);
  6803  
  6804    Temporary_reference_expression* tref =
  6805      Expression::make_temporary_reference(index_temp, loc);
  6806    tref->set_is_lvalue();
  6807    Statement* s = Statement::make_assignment(tref, zexpr, loc);
  6808    init->add_statement(s);
  6809  
  6810    *pinit = init;
  6811  
  6812    // Set *PCOND to
  6813    //   index_temp < len_temp
  6814  
  6815    ref = Expression::make_temporary_reference(index_temp, loc);
  6816    Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
  6817    Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);
  6818  
  6819    *pcond = lt;
  6820  
  6821    // Set *PITER_INIT to
  6822    //   value_temp = range[index_temp]
  6823  
  6824    Block* iter_init = NULL;
  6825    if (value_temp != NULL)
  6826      {
  6827        iter_init = new Block(body_block, loc);
  6828  
  6829        ref = Expression::make_temporary_reference(for_temp, loc);
  6830        ref2 = Expression::make_temporary_reference(index_temp, loc);
  6831        Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
  6832  
  6833        tref = Expression::make_temporary_reference(value_temp, loc);
  6834        tref->set_is_lvalue();
  6835        s = Statement::make_assignment(tref, index, loc);
  6836  
  6837        iter_init->add_statement(s);
  6838      }
  6839    *piter_init = iter_init;
  6840  
  6841    // Set *PPOST to
  6842    //   index_temp++
  6843  
  6844    Block* post = new Block(enclosing, loc);
  6845    tref = Expression::make_temporary_reference(index_temp, loc);
  6846    tref->set_is_lvalue();
  6847    s = Statement::make_inc_statement(tref);
  6848    post->add_statement(s);
  6849    *ppost = post;
  6850  }
  6851  
  6852  // Lower a for range over a string.
  6853  
  6854  void
  6855  For_range_statement::lower_range_string(Gogo* gogo,
  6856  					Block* enclosing,
  6857  					Block* body_block,
  6858  					Named_object* range_object,
  6859  					Temporary_statement* range_temp,
  6860  					Temporary_statement* index_temp,
  6861  					Temporary_statement* value_temp,
  6862  					Block** pinit,
  6863  					Expression** pcond,
  6864  					Block** piter_init,
  6865  					Block** ppost)
  6866  {
  6867    Location loc = this->location();
  6868  
  6869    // The loop we generate:
  6870    //   len_temp := len(range)
  6871    //   var next_index_temp int
  6872    //   for index_temp = 0; index_temp < len_temp; index_temp = next_index_temp {
  6873    //           value_temp = rune(range[index_temp])
  6874    //           if value_temp < utf8.RuneSelf {
  6875    //                   next_index_temp = index_temp + 1
  6876    //           } else {
  6877    //                   value_temp, next_index_temp = decoderune(range, index_temp)
  6878    //           }
  6879    //           index = index_temp
  6880    //           value = value_temp
  6881    //           // original body
  6882    //   }
  6883  
  6884    // Set *PINIT to
  6885    //   len_temp := len(range)
  6886    //   var next_index_temp int
  6887    //   index_temp = 0
  6888    //   var value_temp rune // if value_temp not passed in
  6889  
  6890    Block* init = new Block(enclosing, loc);
  6891  
  6892    Expression* ref = this->make_range_ref(range_object, range_temp, loc);
  6893    Call_expression* call = this->call_builtin(gogo, "len", ref, loc);
  6894    Temporary_statement* len_temp =
  6895      Statement::make_temporary(index_temp->type(), call, loc);
  6896    init->add_statement(len_temp);
  6897  
  6898    Temporary_statement* next_index_temp =
  6899      Statement::make_temporary(index_temp->type(), NULL, loc);
  6900    init->add_statement(next_index_temp);
  6901  
  6902    Temporary_reference_expression* index_ref =
  6903      Expression::make_temporary_reference(index_temp, loc);
  6904    index_ref->set_is_lvalue();
  6905    Expression* zexpr = Expression::make_integer_ul(0, index_temp->type(), loc);
  6906    Statement* s = Statement::make_assignment(index_ref, zexpr, loc);
  6907    init->add_statement(s);
  6908  
  6909    Type* rune_type;
  6910    if (value_temp != NULL)
  6911      rune_type = value_temp->type();
  6912    else
  6913      {
  6914        rune_type = Type::lookup_integer_type("rune");
  6915        value_temp = Statement::make_temporary(rune_type, NULL, loc);
  6916        init->add_statement(value_temp);
  6917      }
  6918  
  6919    *pinit = init;
  6920  
  6921    // Set *PCOND to
  6922    //   index_temp < len_temp
  6923  
  6924    index_ref = Expression::make_temporary_reference(index_temp, loc);
  6925    Expression* len_ref =
  6926      Expression::make_temporary_reference(len_temp, loc);
  6927    *pcond = Expression::make_binary(OPERATOR_LT, index_ref, len_ref, loc);
  6928  
  6929    // Set *PITER_INIT to
  6930    //   value_temp = rune(range[index_temp])
  6931    //   if value_temp < utf8.RuneSelf {
  6932    //           next_index_temp = index_temp + 1
  6933    //   } else {
  6934    //           value_temp, next_index_temp = decoderune(range, index_temp)
  6935    //   }
  6936  
  6937    Block* iter_init = new Block(body_block, loc);
  6938  
  6939    ref = this->make_range_ref(range_object, range_temp, loc);
  6940    index_ref = Expression::make_temporary_reference(index_temp, loc);
  6941    ref = Expression::make_string_index(ref, index_ref, NULL, loc);
  6942    ref = Expression::make_cast(rune_type, ref, loc);
  6943    Temporary_reference_expression* value_ref =
  6944      Expression::make_temporary_reference(value_temp, loc);
  6945    value_ref->set_is_lvalue();
  6946    s = Statement::make_assignment(value_ref, ref, loc);
  6947    iter_init->add_statement(s);
  6948  
  6949    value_ref = Expression::make_temporary_reference(value_temp, loc);
  6950    Expression* rune_self = Expression::make_integer_ul(0x80, rune_type, loc);
  6951    Expression* cond = Expression::make_binary(OPERATOR_LT, value_ref, rune_self,
  6952  					     loc);
  6953  
  6954    Block* then_block = new Block(iter_init, loc);
  6955  
  6956    Temporary_reference_expression* lhs =
  6957      Expression::make_temporary_reference(next_index_temp, loc);
  6958    lhs->set_is_lvalue();
  6959    index_ref = Expression::make_temporary_reference(index_temp, loc);
  6960    Expression* one = Expression::make_integer_ul(1, index_temp->type(), loc);
  6961    Expression* sum = Expression::make_binary(OPERATOR_PLUS, index_ref, one,
  6962  					    loc);
  6963    s = Statement::make_assignment(lhs, sum, loc);
  6964    then_block->add_statement(s);
  6965  
  6966    Block* else_block = new Block(iter_init, loc);
  6967  
  6968    ref = this->make_range_ref(range_object, range_temp, loc);
  6969    index_ref = Expression::make_temporary_reference(index_temp, loc);
  6970    call = Runtime::make_call(Runtime::DECODERUNE, loc, 2, ref, index_ref);
  6971  
  6972    value_ref = Expression::make_temporary_reference(value_temp, loc);
  6973    value_ref->set_is_lvalue();
  6974    Expression* res = Expression::make_call_result(call, 0);
  6975    s = Statement::make_assignment(value_ref, res, loc);
  6976    else_block->add_statement(s);
  6977  
  6978    lhs = Expression::make_temporary_reference(next_index_temp, loc);
  6979    lhs->set_is_lvalue();
  6980    res = Expression::make_call_result(call, 1);
  6981    s = Statement::make_assignment(lhs, res, loc);
  6982    else_block->add_statement(s);
  6983  
  6984    s = Statement::make_if_statement(cond, then_block, else_block, loc);
  6985    iter_init->add_statement(s);
  6986  
  6987    *piter_init = iter_init;
  6988  
  6989    // Set *PPOST to
  6990    //   index_temp = next_index_temp
  6991  
  6992    Block* post = new Block(enclosing, loc);
  6993  
  6994    index_ref = Expression::make_temporary_reference(index_temp, loc);
  6995    index_ref->set_is_lvalue();
  6996    ref = Expression::make_temporary_reference(next_index_temp, loc);
  6997    s = Statement::make_assignment(index_ref, ref, loc);
  6998  
  6999    post->add_statement(s);
  7000    *ppost = post;
  7001  }
  7002  
  7003  // Lower a for range over a map.
  7004  
  7005  void
  7006  For_range_statement::lower_range_map(Gogo* gogo,
  7007  				     Map_type* map_type,
  7008  				     Block* enclosing,
  7009  				     Block* body_block,
  7010  				     Named_object* range_object,
  7011  				     Temporary_statement* range_temp,
  7012  				     Temporary_statement* index_temp,
  7013  				     Temporary_statement* value_temp,
  7014  				     Block** pinit,
  7015  				     Expression** pcond,
  7016  				     Block** piter_init,
  7017  				     Block** ppost)
  7018  {
  7019    Location loc = this->location();
  7020  
  7021    // The runtime uses a struct to handle ranges over a map.  The
  7022    // struct is built by Map_type::hiter_type for a specific map type.
  7023  
  7024    // The loop we generate:
  7025    //   var hiter map_iteration_struct
  7026    //   for mapiterinit(type, range, &hiter); hiter.key != nil; mapiternext(&hiter) {
  7027    //           index_temp = *hiter.key
  7028    //           value_temp = *hiter.val
  7029    //           index = index_temp
  7030    //           value = value_temp
  7031    //           original body
  7032    //   }
  7033  
  7034    // Set *PINIT to
  7035    //   var hiter map_iteration_struct
  7036    //   runtime.mapiterinit(type, range, &hiter)
  7037  
  7038    Block* init = new Block(enclosing, loc);
  7039  
  7040    Type* map_iteration_type = map_type->hiter_type(gogo);
  7041    Temporary_statement* hiter = Statement::make_temporary(map_iteration_type,
  7042  							 NULL, loc);
  7043    init->add_statement(hiter);
  7044  
  7045    Expression* p1 = Expression::make_type_descriptor(map_type, loc);
  7046    Expression* p2 = this->make_range_ref(range_object, range_temp, loc);
  7047    Expression* ref = Expression::make_temporary_reference(hiter, loc);
  7048    Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
  7049    Expression* call = Runtime::make_call(Runtime::MAPITERINIT, loc, 3,
  7050  					p1, p2, p3);
  7051    init->add_statement(Statement::make_statement(call, true));
  7052  
  7053    *pinit = init;
  7054  
  7055    // Set *PCOND to
  7056    //   hiter.key != nil
  7057  
  7058    ref = Expression::make_temporary_reference(hiter, loc);
  7059    ref = Expression::make_field_reference(ref, 0, loc);
  7060    Expression* ne = Expression::make_binary(OPERATOR_NOTEQ, ref,
  7061  					   Expression::make_nil(loc),
  7062  					   loc);
  7063    *pcond = ne;
  7064  
  7065    // Set *PITER_INIT to
  7066    //   index_temp = *hiter.key
  7067    //   value_temp = *hiter.val
  7068  
  7069    Block* iter_init = new Block(body_block, loc);
  7070  
  7071    Expression* lhs = Expression::make_temporary_reference(index_temp, loc);
  7072    Expression* rhs = Expression::make_temporary_reference(hiter, loc);
  7073    rhs = Expression::make_field_reference(ref, 0, loc);
  7074    rhs = Expression::make_dereference(ref, Expression::NIL_CHECK_NOT_NEEDED,
  7075                                       loc);
  7076    Statement* set = Statement::make_assignment(lhs, rhs, loc);
  7077    iter_init->add_statement(set);
  7078  
  7079    if (value_temp != NULL)
  7080      {
  7081        lhs = Expression::make_temporary_reference(value_temp, loc);
  7082        rhs = Expression::make_temporary_reference(hiter, loc);
  7083        rhs = Expression::make_field_reference(rhs, 1, loc);
  7084        rhs = Expression::make_dereference(rhs, Expression::NIL_CHECK_NOT_NEEDED,
  7085                                           loc);
  7086        set = Statement::make_assignment(lhs, rhs, loc);
  7087        iter_init->add_statement(set);
  7088      }
  7089  
  7090    *piter_init = iter_init;
  7091  
  7092    // Set *PPOST to
  7093    //   mapiternext(&hiter)
  7094  
  7095    Block* post = new Block(enclosing, loc);
  7096  
  7097    ref = Expression::make_temporary_reference(hiter, loc);
  7098    p1 = Expression::make_unary(OPERATOR_AND, ref, loc);
  7099    call = Runtime::make_call(Runtime::MAPITERNEXT, loc, 1, p1);
  7100    post->add_statement(Statement::make_statement(call, true));
  7101  
  7102    *ppost = post;
  7103  }
  7104  
  7105  // Lower a for range over a channel.
  7106  
  7107  void
  7108  For_range_statement::lower_range_channel(Gogo*,
  7109  					 Block*,
  7110  					 Block* body_block,
  7111  					 Named_object* range_object,
  7112  					 Temporary_statement* range_temp,
  7113  					 Temporary_statement* index_temp,
  7114  					 Temporary_statement* value_temp,
  7115  					 Block** pinit,
  7116  					 Expression** pcond,
  7117  					 Block** piter_init,
  7118  					 Block** ppost)
  7119  {
  7120    go_assert(value_temp == NULL);
  7121  
  7122    Location loc = this->location();
  7123  
  7124    // The loop we generate:
  7125    //   for {
  7126    //           index_temp, ok_temp = <-range
  7127    //           if !ok_temp {
  7128    //                   break
  7129    //           }
  7130    //           index = index_temp
  7131    //           original body
  7132    //   }
  7133  
  7134    // We have no initialization code, no condition, and no post code.
  7135  
  7136    *pinit = NULL;
  7137    *pcond = NULL;
  7138    *ppost = NULL;
  7139  
  7140    // Set *PITER_INIT to
  7141    //   index_temp, ok_temp = <-range
  7142    //   if !ok_temp {
  7143    //           break
  7144    //   }
  7145  
  7146    Block* iter_init = new Block(body_block, loc);
  7147  
  7148    Temporary_statement* ok_temp =
  7149      Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
  7150    iter_init->add_statement(ok_temp);
  7151  
  7152    Expression* cref = this->make_range_ref(range_object, range_temp, loc);
  7153    Temporary_reference_expression* iref =
  7154      Expression::make_temporary_reference(index_temp, loc);
  7155    iref->set_is_lvalue();
  7156    Temporary_reference_expression* oref =
  7157      Expression::make_temporary_reference(ok_temp, loc);
  7158    oref->set_is_lvalue();
  7159    Statement* s = Statement::make_tuple_receive_assignment(iref, oref, cref,
  7160  							  loc);
  7161    iter_init->add_statement(s);
  7162  
  7163    Block* then_block = new Block(iter_init, loc);
  7164    s = Statement::make_break_statement(this->break_label(), loc);
  7165    then_block->add_statement(s);
  7166  
  7167    oref = Expression::make_temporary_reference(ok_temp, loc);
  7168    Expression* cond = Expression::make_unary(OPERATOR_NOT, oref, loc);
  7169    s = Statement::make_if_statement(cond, then_block, NULL, loc);
  7170    iter_init->add_statement(s);
  7171  
  7172    *piter_init = iter_init;
  7173  }
  7174  
  7175  // Match
  7176  //
  7177  //   for k := range m { delete(m, k) }
  7178  //
  7179  // Lower it to runtime.mapclear(TYPE, m) on match, return the statement
  7180  // containing the call.  Return NULL otherwise.
  7181  
  7182  Statement*
  7183  For_range_statement::lower_map_range_clear(Type* map_type,
  7184                                             Block* enclosing,
  7185                                             Expression* orig_range_expr,
  7186                                             Named_object* range_object,
  7187                                             Temporary_statement* range_temp,
  7188                                             Location loc)
  7189  {
  7190    if (this->value_var_ != NULL)
  7191      return NULL;
  7192    if (this->index_var_ == NULL)
  7193      return NULL;
  7194  
  7195    // Require the loop index be a new variable.  We cannot rewrite
  7196    // if it is used outside of the loop.
  7197    Var_expression* index_ve = this->index_var_->var_expression();
  7198    if (index_ve == NULL)
  7199      return NULL;
  7200    Named_object* index_no = index_ve->named_object();
  7201    if (enclosing->bindings()->lookup_local(index_no->name()) != index_no)
  7202      return NULL;
  7203  
  7204    // Match the body, a single call statement delete(m, k).
  7205    const std::vector<Statement*>* statements = this->statements_->statements();
  7206    if (statements->size() != 1)
  7207      return NULL;
  7208    Expression_statement* es = statements->at(0)->expression_statement();
  7209    if (es == NULL)
  7210      return NULL;
  7211    Call_expression* call = es->expr()->call_expression();
  7212    if (call == NULL || !call->is_builtin()
  7213        || call->builtin_call_expression()->code()
  7214           != Builtin_call_expression::BUILTIN_DELETE)
  7215      return NULL;
  7216    if (!Expression::is_same_variable(call->args()->at(0), orig_range_expr)
  7217        || !Expression::is_same_variable(call->args()->at(1), this->index_var_))
  7218      return NULL;
  7219  
  7220    // Everything matches. Rewrite to mapclear(TYPE, MAP).
  7221    Expression* e1 = Expression::make_type_descriptor(map_type, loc);
  7222    Expression* e2 = this->make_range_ref(range_object, range_temp, loc);
  7223    call = Runtime::make_call(Runtime::MAPCLEAR, loc, 2, e1, e2);
  7224    return Statement::make_statement(call, true);
  7225  }
  7226  
  7227  // Match
  7228  //
  7229  //   for i := range a { a[i] = zero }
  7230  //
  7231  // Lower it to call memclr on match, and return the statement.  Return
  7232  // NULL otherwise.
  7233  
  7234  Statement*
  7235  For_range_statement::lower_array_range_clear(Gogo* gogo,
  7236                                               Type* array_type,
  7237                                               Expression* orig_range_expr,
  7238                                               Block* temp_block,
  7239                                               Named_object* range_object,
  7240                                               Temporary_statement* range_temp,
  7241                                               Location loc)
  7242  {
  7243    if (this->value_var_ != NULL)
  7244      return NULL;
  7245    if (this->index_var_ == NULL)
  7246      return NULL;
  7247  
  7248    // Match the body, a single assignment statement a[i] = zero.
  7249    const std::vector<Statement*>* statements = this->statements_->statements();
  7250    if (statements->size() != 1)
  7251      return NULL;
  7252    Assignment_statement* as = statements->at(0)->assignment_statement();
  7253    if (as == NULL || !as->rhs()->is_zero_value())
  7254      return NULL;
  7255    if (as->lhs()->type()->interface_type() != NULL
  7256        && as->rhs()->type()->interface_type() == NULL
  7257        && !as->rhs()->type()->is_nil_type())
  7258      // Implicit type conversion may change a zero value to non-zero, like
  7259      // interface{}(0).
  7260      return NULL;
  7261    Array_index_expression* aie = as->lhs()->array_index_expression();
  7262    if (aie == NULL || aie->end() != NULL
  7263        || !Expression::is_same_variable(orig_range_expr, aie->array())
  7264        || !Expression::is_same_variable(this->index_var_, aie->start()))
  7265      return NULL;
  7266  
  7267    // Everything matches. Rewrite to
  7268    //
  7269    //   if len(a) != 0 {
  7270    //     tmp1 = &a[0]
  7271    //     tmp2 = len(a)*sizeof(elem(a))
  7272    //     memclr{NoHeap,Has}Pointers(tmp1, tmp2)
  7273    //     i = len(a) - 1
  7274    //   }
  7275  
  7276    Type* elem_type = array_type->array_type()->element_type();
  7277    int64_t elme_sz;
  7278    bool ok = elem_type->backend_type_size(gogo, &elme_sz);
  7279    if (!ok)
  7280      return NULL;
  7281  
  7282    Block* b = new Block(temp_block, loc);
  7283  
  7284    Expression* ref;
  7285    if (range_object == NULL && range_temp == NULL)
  7286      // is_same_variable implies no side effect, so it is ok to copy.
  7287      ref = orig_range_expr->copy();
  7288    else
  7289      ref = this->make_range_ref(range_object, range_temp, loc);
  7290    Expression* len = this->call_builtin(gogo, "len", ref, loc);
  7291    Temporary_statement* tslen = Statement::make_temporary(NULL, len, loc);
  7292    temp_block->add_statement(tslen);
  7293  
  7294    Expression* zero = Expression::make_integer_ul(0, this->index_var_->type(), loc);
  7295    ref = ref->copy();
  7296    Expression* elem = Expression::make_array_index(ref, zero, NULL, NULL, loc);
  7297    elem->array_index_expression()->set_needs_bounds_check(false);
  7298    Expression* e1 = Expression::make_unary(OPERATOR_AND, elem, loc);
  7299    Temporary_statement* ts1 = Statement::make_temporary(NULL, e1, loc);
  7300    b->add_statement(ts1);
  7301  
  7302    len = Expression::make_temporary_reference(tslen, loc);
  7303    Expression* sz = Expression::make_integer_int64(elme_sz, len->type(), loc);
  7304    Expression* e2 = Expression::make_binary(OPERATOR_MULT, len, sz, loc);
  7305    Temporary_statement* ts2 = Statement::make_temporary(NULL, e2, loc);
  7306    b->add_statement(ts2);
  7307  
  7308    Expression* ptr_arg = Expression::make_temporary_reference(ts1, loc);
  7309    Expression* sz_arg = Expression::make_temporary_reference(ts2, loc);
  7310    Expression* call;
  7311    if (elem_type->has_pointer())
  7312      call = Runtime::make_call(Runtime::MEMCLRHASPTR, loc, 2, ptr_arg, sz_arg);
  7313    else
  7314      {
  7315        Type* int32_type = Type::lookup_integer_type("int32");
  7316        Expression* zero32 = Expression::make_integer_ul(0, int32_type, loc);
  7317        call = Runtime::make_call(Runtime::BUILTIN_MEMSET, loc, 3, ptr_arg,
  7318                                  zero32, sz_arg);
  7319      }
  7320    Statement* cs3 = Statement::make_statement(call, true);
  7321    b->add_statement(cs3);
  7322  
  7323    len = Expression::make_temporary_reference(tslen, loc);
  7324    Expression* one = Expression::make_integer_ul(1, len->type(), loc);
  7325    Expression* rhs = Expression::make_binary(OPERATOR_MINUS, len, one, loc);
  7326    Expression* lhs = this->index_var_->copy();
  7327    Statement* as4 = Statement::make_assignment(lhs, rhs, loc);
  7328    b->add_statement(as4);
  7329  
  7330    len = Expression::make_temporary_reference(tslen, loc);
  7331    zero = zero->copy();
  7332    Expression* cond = Expression::make_binary(OPERATOR_NOTEQ, len, zero, loc);
  7333    return Statement::make_if_statement(cond, b, NULL, loc);
  7334  }
  7335  
  7336  // Return the break LABEL_EXPR.
  7337  
  7338  Unnamed_label*
  7339  For_range_statement::break_label()
  7340  {
  7341    if (this->break_label_ == NULL)
  7342      this->break_label_ = new Unnamed_label(this->location());
  7343    return this->break_label_;
  7344  }
  7345  
  7346  // Return the continue LABEL_EXPR.
  7347  
  7348  Unnamed_label*
  7349  For_range_statement::continue_label()
  7350  {
  7351    if (this->continue_label_ == NULL)
  7352      this->continue_label_ = new Unnamed_label(this->location());
  7353    return this->continue_label_;
  7354  }
  7355  
  7356  // Dump the AST representation for a for range statement.
  7357  
  7358  void
  7359  For_range_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
  7360  {
  7361  
  7362    ast_dump_context->print_indent();
  7363    ast_dump_context->ostream() << "for ";
  7364    ast_dump_context->dump_expression(this->index_var_);
  7365    if (this->value_var_ != NULL)
  7366      {
  7367        ast_dump_context->ostream() << ", ";
  7368        ast_dump_context->dump_expression(this->value_var_);
  7369      }
  7370  
  7371    ast_dump_context->ostream() << " = range ";
  7372    ast_dump_context->dump_expression(this->range_);
  7373    if (ast_dump_context->dump_subblocks())
  7374      {
  7375        ast_dump_context->ostream() << " {" << std::endl;
  7376  
  7377        ast_dump_context->indent();
  7378  
  7379        ast_dump_context->dump_block(this->statements_);
  7380  
  7381        ast_dump_context->unindent();
  7382        ast_dump_context->print_indent();
  7383        ast_dump_context->ostream() << "}";
  7384      }
  7385    ast_dump_context->ostream() << dsuffix(location()) << std::endl;
  7386  }
  7387  
  7388  // Make a for statement with a range clause.
  7389  
  7390  For_range_statement*
  7391  Statement::make_for_range_statement(Expression* index_var,
  7392  				    Expression* value_var,
  7393  				    Expression* range,
  7394  				    Location location)
  7395  {
  7396    return new For_range_statement(index_var, value_var, range, location);
  7397  }