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