LCOV - code coverage report
Current view: top level - gcc/go/gofrontend - statements.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 85.7 % 3711 3182
Test Date: 2024-04-20 14:03:02 Functions: 84.4 % 295 249
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       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                 :     7689786 : Statement::Statement(Statement_classification classification,
      24                 :     7689786 :                      Location location)
      25                 :     7689786 :   : classification_(classification), location_(location)
      26                 :             : {
      27                 :     7689786 : }
      28                 :             : 
      29                 :           0 : Statement::~Statement()
      30                 :             : {
      31                 :           0 : }
      32                 :             : 
      33                 :             : // Traverse the tree.  The work of walking the components is handled
      34                 :             : // by the subclasses.
      35                 :             : 
      36                 :             : int
      37                 :    93714292 : Statement::traverse(Block* block, size_t* pindex, Traverse* traverse)
      38                 :             : {
      39                 :    93714292 :   if (this->classification_ == STATEMENT_ERROR)
      40                 :             :     return TRAVERSE_CONTINUE;
      41                 :             : 
      42                 :    93711483 :   unsigned int traverse_mask = traverse->traverse_mask();
      43                 :             : 
      44                 :    93711483 :   if ((traverse_mask & Traverse::traverse_statements) != 0)
      45                 :             :     {
      46                 :    56910177 :       int t = traverse->statement(block, pindex, this);
      47                 :    56910177 :       if (t == TRAVERSE_EXIT)
      48                 :             :         return TRAVERSE_EXIT;
      49                 :    56890990 :       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                 :    79643626 :   return this->do_traverse(traverse);
      57                 :             : }
      58                 :             : 
      59                 :             : // Traverse the contents of a statement.
      60                 :             : 
      61                 :             : int
      62                 :    24051832 : Statement::traverse_contents(Traverse* traverse)
      63                 :             : {
      64                 :    24051832 :   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                 :    70840114 : Statement::traverse_expression(Traverse* traverse, Expression** expr)
      72                 :             : {
      73                 :    70840114 :   if ((traverse->traverse_mask()
      74                 :    70840114 :        & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
      75                 :             :     return TRAVERSE_CONTINUE;
      76                 :    51020126 :   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                 :     7561206 : Statement::traverse_expression_list(Traverse* traverse,
      84                 :             :                                     Expression_list* expr_list)
      85                 :             : {
      86                 :     7561206 :   if (expr_list == NULL)
      87                 :             :     return TRAVERSE_CONTINUE;
      88                 :     1522037 :   if ((traverse->traverse_mask()
      89                 :     1522037 :        & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
      90                 :             :     return TRAVERSE_CONTINUE;
      91                 :     1522037 :   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                 :    11450419 : Statement::traverse_type(Traverse* traverse, Type* type)
      99                 :             : {
     100                 :    11450419 :   if ((traverse->traverse_mask()
     101                 :    11450419 :        & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
     102                 :             :     return TRAVERSE_CONTINUE;
     103                 :     8076252 :   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                 :     5803423 : Statement::determine_types(Gogo* gogo)
     111                 :             : {
     112                 :     5803423 :   this->do_determine_types(gogo);
     113                 :     5803423 : }
     114                 :             : 
     115                 :             : // Read a statement from export data.
     116                 :             : 
     117                 :             : Statement*
     118                 :       69326 : Statement::import_statement(Import_function_body* ifb, Location loc)
     119                 :             : {
     120                 :       69326 :   if (ifb->match_c_string("{"))
     121                 :             :     {
     122                 :       21059 :       bool is_lowered_for_statement;
     123                 :       21059 :       Block* block = Block_statement::do_import(ifb, loc,
     124                 :             :                                                 &is_lowered_for_statement);
     125                 :       21059 :       if (block == NULL)
     126                 :           0 :         return Statement::make_error_statement(loc);
     127                 :       21059 :       Block_statement* s = Statement::make_block_statement(block, loc);
     128                 :       21059 :       if (is_lowered_for_statement)
     129                 :           0 :         s->set_is_lowered_for_statement();
     130                 :       21059 :       return s;
     131                 :             :     }
     132                 :       48267 :   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                 :       12579 :       ifb->advance(6);
     137                 :       12579 :       return Statement::make_return_statement(ifb->function(), NULL, loc);
     138                 :             :     }
     139                 :       35688 :   else if (ifb->match_c_string("var $t"))
     140                 :        2661 :     return Temporary_statement::do_import(ifb, loc);
     141                 :       33027 :   else if (ifb->match_c_string("var "))
     142                 :        3280 :     return Variable_declaration_statement::do_import(ifb, loc);
     143                 :       29747 :   else if (ifb->match_c_string("if "))
     144                 :        5427 :     return If_statement::do_import(ifb, loc);
     145                 :       24320 :   else if (ifb->match_c_string(":"))
     146                 :        1434 :     return Label_statement::do_import(ifb, loc);
     147                 :       22886 :   else if (ifb->match_c_string("goto "))
     148                 :        1523 :     return Goto_statement::do_import(ifb, loc);
     149                 :             : 
     150                 :       21363 :   Expression* lhs = Expression::import_expression(ifb, loc);
     151                 :             : 
     152                 :       21363 :   if (ifb->match_c_string(" //"))
     153                 :        4246 :     return Statement::make_statement(lhs, true);
     154                 :             : 
     155                 :       17117 :   ifb->require_c_string(" = ");
     156                 :       17117 :   Expression* rhs = Expression::import_expression(ifb, loc);
     157                 :       17117 :   return Statement::make_assignment(lhs, rhs, loc);
     158                 :             : }
     159                 :             : 
     160                 :             : // If this is a thunk statement, return it.
     161                 :             : 
     162                 :             : Thunk_statement*
     163                 :     2146706 : Statement::thunk_statement()
     164                 :             : {
     165                 :     2146706 :   Thunk_statement* ret = this->convert<Thunk_statement, STATEMENT_GO>();
     166                 :     2141669 :   if (ret == NULL)
     167                 :     2141669 :     ret = this->convert<Thunk_statement, STATEMENT_DEFER>();
     168                 :     2146706 :   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                 :     7171967 : Statement::get_backend(Translate_context* context)
     176                 :             : {
     177                 :     7171967 :   if (this->classification_ == STATEMENT_ERROR)
     178                 :         580 :     return context->backend()->error_statement();
     179                 :     7171387 :   return this->do_get_backend(context);
     180                 :             : }
     181                 :             : 
     182                 :             : // Dump AST representation for a statement to a dump context.
     183                 :             : 
     184                 :             : void
     185                 :           0 : Statement::dump_statement(Ast_dump_context* ast_dump_context) const
     186                 :             : {
     187                 :           0 :   this->do_dump_statement(ast_dump_context);
     188                 :           0 : }
     189                 :             : 
     190                 :             : // Note that this statement is erroneous.  This is called by children
     191                 :             : // when they discover an error.
     192                 :             : 
     193                 :             : void
     194                 :         284 : Statement::set_is_error()
     195                 :             : {
     196                 :         284 :   this->classification_ = STATEMENT_ERROR;
     197                 :         284 : }
     198                 :             : 
     199                 :             : // For children to call to report an error conveniently.
     200                 :             : 
     201                 :             : void
     202                 :          28 : Statement::report_error(const char* msg)
     203                 :             : {
     204                 :          28 :   go_error_at(this->location_, "%s", msg);
     205                 :          28 :   this->set_is_error();
     206                 :          28 : }
     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                 :         362 :   Error_statement(Location location)
     215                 :         724 :     : Statement(STATEMENT_ERROR, location)
     216                 :             :   { }
     217                 :             : 
     218                 :             :  protected:
     219                 :             :   int
     220                 :         362 :   do_traverse(Traverse*)
     221                 :         362 :   { return TRAVERSE_CONTINUE; }
     222                 :             : 
     223                 :             :   Bstatement*
     224                 :           0 :   do_get_backend(Translate_context*)
     225                 :           0 :   { 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                 :           0 : dsuffix(Location location)
     237                 :             : {
     238                 :           0 :   std::string lstr = Linemap::location_to_string(location);
     239                 :           0 :   if (lstr == "")
     240                 :           0 :     return lstr;
     241                 :           0 :   std::string rval(" // ");
     242                 :           0 :   rval += lstr;
     243                 :           0 :   return rval;
     244                 :           0 : }
     245                 :             : 
     246                 :             : // Dump the AST representation for an error statement.
     247                 :             : 
     248                 :             : void
     249                 :           0 : Error_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
     250                 :             : {
     251                 :           0 :   ast_dump_context->print_indent();
     252                 :           0 :   ast_dump_context->ostream() << "Error statement" << std::endl;
     253                 :           0 : }
     254                 :             : 
     255                 :             : // Make an error statement.
     256                 :             : 
     257                 :             : Statement*
     258                 :         362 : Statement::make_error_statement(Location location)
     259                 :             : {
     260                 :         362 :   return new Error_statement(location);
     261                 :             : }
     262                 :             : 
     263                 :             : // Class Variable_declaration_statement.
     264                 :             : 
     265                 :      383759 : Variable_declaration_statement::Variable_declaration_statement(
     266                 :      383759 :     Named_object* var)
     267                 :             :   : Statement(STATEMENT_VARIABLE_DECLARATION, var->var_value()->location()),
     268                 :      383759 :     var_(var)
     269                 :             : {
     270                 :      383759 : }
     271                 :             : 
     272                 :             : // We don't actually traverse the variable here; it was traversed
     273                 :             : // while traversing the Block.
     274                 :             : 
     275                 :             : int
     276                 :     8686784 : Variable_declaration_statement::do_traverse(Traverse*)
     277                 :             : {
     278                 :     8686784 :   return TRAVERSE_CONTINUE;
     279                 :             : }
     280                 :             : 
     281                 :             : void
     282                 :      419776 : Variable_declaration_statement::do_determine_types(Gogo* gogo)
     283                 :             : {
     284                 :      419776 :   this->var_->var_value()->determine_type(gogo);
     285                 :      419776 : }
     286                 :             : 
     287                 :             : // Lower the variable's initialization expression.
     288                 :             : 
     289                 :             : Statement*
     290                 :      538542 : Variable_declaration_statement::do_lower(Gogo* gogo, Named_object* function,
     291                 :             :                                          Block*, Statement_inserter* inserter)
     292                 :             : {
     293                 :      538542 :   this->var_->var_value()->lower_init_expression(gogo, function, inserter);
     294                 :      538542 :   return this;
     295                 :             : }
     296                 :             : 
     297                 :             : // Flatten the variable's initialization expression.
     298                 :             : 
     299                 :             : Statement*
     300                 :      402413 : Variable_declaration_statement::do_flatten(Gogo* gogo, Named_object* function,
     301                 :             :                                            Block*, Statement_inserter* inserter)
     302                 :             : {
     303                 :      402413 :   Variable* var = this->var_->var_value();
     304                 :      402413 :   if (var->type()->is_error_type()
     305                 :      402413 :       || (var->init() != NULL
     306                 :      288428 :           && var->init()->is_error_expression()))
     307                 :             :     {
     308                 :          57 :       go_assert(saw_errors());
     309                 :          57 :       return Statement::make_error_statement(this->location());
     310                 :             :     }
     311                 :      402356 :   this->var_->var_value()->flatten_init_expression(gogo, function, inserter);
     312                 :      402356 :   return this;
     313                 :             : }
     314                 :             : 
     315                 :             : // Add explicit type conversions.
     316                 :             : 
     317                 :             : void
     318                 :      382634 : Variable_declaration_statement::do_add_conversions()
     319                 :             : {
     320                 :      382634 :   Variable* var = this->var_->var_value();
     321                 :      382634 :   Expression* init = var->init();
     322                 :      382634 :   if (init == NULL)
     323                 :             :     return;
     324                 :      280750 :   Type* lt = var->type();
     325                 :      280750 :   Type* rt = init->type();
     326                 :      280750 :   if (!Type::are_identical(lt, rt, 0, NULL)
     327                 :      280750 :       && lt->interface_type() != NULL)
     328                 :         341 :     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                 :      382460 : Variable_declaration_statement::do_get_backend(Translate_context* context)
     335                 :             : {
     336                 :      382460 :   if (this->var_->is_redefinition())
     337                 :           2 :     return context->backend()->error_statement();
     338                 :      382458 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
     339                 :      382458 :   Variable* var = this->var_->var_value();
     340                 :      382458 :   Bvariable* bvar = this->var_->get_backend_variable(context->gogo(),
     341                 :             :                                                      context->function());
     342                 :      382458 :   Bexpression* binit = var->get_init(context->gogo(), context->function());
     343                 :             : 
     344                 :      382458 :   if (!var->is_in_heap())
     345                 :             :     {
     346                 :      368506 :       go_assert(binit != NULL);
     347                 :      368506 :       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                 :       13952 :   Location loc = this->location();
     354                 :       13952 :   Named_object* newfn = context->gogo()->lookup_global("new");
     355                 :       13952 :   go_assert(newfn != NULL && newfn->is_function_declaration());
     356                 :       13952 :   Expression* func = Expression::make_func_reference(newfn, NULL, loc);
     357                 :       13952 :   Expression_list* params = new Expression_list();
     358                 :       13952 :   params->push_back(Expression::make_type(var->type(), loc));
     359                 :       13952 :   Expression* call = Expression::make_call(func, params, false, loc);
     360                 :       13952 :   context->gogo()->lower_expression(context->function(), NULL, &call);
     361                 :       13952 :   Temporary_statement* temp = Statement::make_temporary(NULL, call, loc);
     362                 :       13952 :   Bstatement* btemp = temp->get_backend(context);
     363                 :             : 
     364                 :       13952 :   Bstatement* set = NULL;
     365                 :       13952 :   if (binit != NULL)
     366                 :             :     {
     367                 :        1189 :       Expression* e = Expression::make_temporary_reference(temp, loc);
     368                 :        1189 :       e = Expression::make_dereference(e, Expression::NIL_CHECK_NOT_NEEDED,
     369                 :             :                                        loc);
     370                 :        1189 :       Bexpression* be = e->get_backend(context);
     371                 :        1189 :       set = context->backend()->assignment_statement(bfunction, be, binit, loc);
     372                 :             :     }
     373                 :             : 
     374                 :       13952 :   Expression* ref = Expression::make_temporary_reference(temp, loc);
     375                 :       13952 :   Bexpression* bref = ref->get_backend(context);
     376                 :       13952 :   Bstatement* sinit = context->backend()->init_statement(bfunction, bvar, bref);
     377                 :             : 
     378                 :       13952 :   std::vector<Bstatement*> stats;
     379                 :       13952 :   stats.reserve(3);
     380                 :       13952 :   stats.push_back(btemp);
     381                 :       13952 :   if (set != NULL)
     382                 :        1189 :     stats.push_back(set);
     383                 :       13952 :   stats.push_back(sinit);
     384                 :       13952 :   return context->backend()->statement_list(stats);
     385                 :       13952 : }
     386                 :             : 
     387                 :             : // Dump the AST representation for a variable declaration.
     388                 :             : 
     389                 :             : void
     390                 :           0 : Variable_declaration_statement::do_dump_statement(
     391                 :             :     Ast_dump_context* ast_dump_context) const
     392                 :             : {
     393                 :           0 :   ast_dump_context->print_indent();
     394                 :             : 
     395                 :           0 :   go_assert(var_->is_variable());
     396                 :           0 :   ast_dump_context->ostream() << "var " << this->var_->name() <<  " ";
     397                 :           0 :   Variable* var = this->var_->var_value();
     398                 :           0 :   if (var->has_type())
     399                 :             :     {
     400                 :           0 :       ast_dump_context->dump_type(var->type());
     401                 :           0 :       ast_dump_context->ostream() << " ";
     402                 :             :     }
     403                 :           0 :   if (var->init() != NULL)
     404                 :             :     {
     405                 :           0 :       ast_dump_context->ostream() <<  "= ";
     406                 :           0 :       ast_dump_context->dump_expression(var->init());
     407                 :             :     }
     408                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
     409                 :           0 : }
     410                 :             : 
     411                 :             : // Make a variable declaration.
     412                 :             : 
     413                 :             : Statement*
     414                 :      383759 : Statement::make_variable_declaration(Named_object* var)
     415                 :             : {
     416                 :      383759 :   return new Variable_declaration_statement(var);
     417                 :             : }
     418                 :             : 
     419                 :             : // Export a variable declaration.
     420                 :             : 
     421                 :             : void
     422                 :        4064 : Variable_declaration_statement::do_export_statement(Export_function_body* efb)
     423                 :             : {
     424                 :        4064 :   efb->write_c_string("var ");
     425                 :        4064 :   efb->write_string(Gogo::unpack_hidden_name(this->var_->name()));
     426                 :        4064 :   efb->write_c_string(" ");
     427                 :        4064 :   Variable* var = this->var_->var_value();
     428                 :        4064 :   Type* type = var->type();
     429                 :        4064 :   efb->write_type(type);
     430                 :        4064 :   Expression* init = var->init();
     431                 :        4064 :   if (init != NULL)
     432                 :             :     {
     433                 :        2885 :       efb->write_c_string(" = ");
     434                 :             : 
     435                 :        2885 :       go_assert(efb->type_context() == NULL);
     436                 :        2885 :       efb->set_type_context(type);
     437                 :             : 
     438                 :        2885 :       init->export_expression(efb);
     439                 :             : 
     440                 :        2885 :       efb->set_type_context(NULL);
     441                 :             :     }
     442                 :        4064 : }
     443                 :             : 
     444                 :             : // Import a variable declaration.
     445                 :             : 
     446                 :             : Statement*
     447                 :        3280 : Variable_declaration_statement::do_import(Import_function_body* ifb,
     448                 :             :                                           Location loc)
     449                 :             : {
     450                 :        3280 :   ifb->require_c_string("var ");
     451                 :        3280 :   std::string id = ifb->read_identifier();
     452                 :        3280 :   ifb->require_c_string(" ");
     453                 :        3280 :   Type* type = ifb->read_type();
     454                 :        3280 :   Expression* init = NULL;
     455                 :        3280 :   if (ifb->match_c_string(" = "))
     456                 :             :     {
     457                 :        2682 :       ifb->advance(3);
     458                 :        2682 :       init = Expression::import_expression(ifb, loc);
     459                 :             :     }
     460                 :        3280 :   Variable* var = new Variable(type, init, false, false, false, loc);
     461                 :        3280 :   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                 :        3280 :   Named_object* no = ifb->block()->bindings()->add_variable(id, NULL, var);
     465                 :        3280 :   return Statement::make_variable_declaration(no);
     466                 :        3280 : }
     467                 :             : 
     468                 :             : // Class Temporary_statement.
     469                 :             : 
     470                 :             : // Return the type of the temporary variable.
     471                 :             : 
     472                 :             : Type*
     473                 :    27309520 : Temporary_statement::type() const
     474                 :             : {
     475                 :    27309520 :   Type* type = this->type_ != NULL ? this->type_ : this->init_->type();
     476                 :             : 
     477                 :             :   // Temporary variables cannot have a void type.
     478                 :    27309520 :   if (type->is_void_type())
     479                 :             :     {
     480                 :           0 :       go_assert(saw_errors());
     481                 :           0 :       return Type::make_error_type();
     482                 :             :     }
     483                 :             :   return type;
     484                 :             : }
     485                 :             : 
     486                 :             : // Traversal.
     487                 :             : 
     488                 :             : int
     489                 :    17306857 : Temporary_statement::do_traverse(Traverse* traverse)
     490                 :             : {
     491                 :    17306857 :   if (this->type_ != NULL
     492                 :    17306857 :       && this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
     493                 :             :     return TRAVERSE_EXIT;
     494                 :    17306857 :   if (this->init_ == NULL)
     495                 :             :     return TRAVERSE_CONTINUE;
     496                 :             :   else
     497                 :    13616416 :     return this->traverse_expression(traverse, &this->init_);
     498                 :             : }
     499                 :             : 
     500                 :             : // Determine types.
     501                 :             : 
     502                 :             : void
     503                 :      656690 : Temporary_statement::do_determine_types(Gogo* gogo)
     504                 :             : {
     505                 :      656690 :   if (this->type_ != NULL && this->type_->is_abstract())
     506                 :         970 :     this->type_ = this->type_->make_non_abstract_type();
     507                 :             : 
     508                 :      656690 :   if (this->init_ != NULL)
     509                 :             :     {
     510                 :      613632 :       if (this->type_ == NULL)
     511                 :      363881 :         this->init_->determine_type_no_context(gogo);
     512                 :             :       else
     513                 :             :         {
     514                 :      249751 :           Type_context context(this->type_, false);
     515                 :      249751 :           this->init_->determine_type(gogo, &context);
     516                 :             :         }
     517                 :             :     }
     518                 :             : 
     519                 :      656690 :   if (this->type_ == NULL)
     520                 :             :     {
     521                 :      363881 :       this->type_ = this->init_->type();
     522                 :      363881 :       go_assert(!this->type_->is_abstract());
     523                 :             :     }
     524                 :      656690 : }
     525                 :             : 
     526                 :             : // Check types.
     527                 :             : 
     528                 :             : void
     529                 :        6221 : Temporary_statement::do_check_types(Gogo*)
     530                 :             : {
     531                 :        6221 :   if (this->type_ != NULL && this->init_ != NULL)
     532                 :             :     {
     533                 :        2012 :       std::string reason;
     534                 :        2012 :       if (!Type::are_assignable(this->type_, this->init_->type(), &reason))
     535                 :             :         {
     536                 :           0 :           if (reason.empty())
     537                 :           0 :             go_error_at(this->location(), "incompatible types in assignment");
     538                 :             :           else
     539                 :           0 :             go_error_at(this->location(), "incompatible types in assignment (%s)",
     540                 :             :                      reason.c_str());
     541                 :           0 :           this->set_is_error();
     542                 :             :         }
     543                 :        2012 :     }
     544                 :        6221 : }
     545                 :             : 
     546                 :             : // Flatten a temporary statement: add another temporary when it might
     547                 :             : // be needed for interface conversion.
     548                 :             : 
     549                 :             : Statement*
     550                 :     1463957 : Temporary_statement::do_flatten(Gogo*, Named_object*, Block*,
     551                 :             :                                 Statement_inserter* inserter)
     552                 :             : {
     553                 :     1463957 :   if (this->type()->is_error_type()
     554                 :     1463957 :       || (this->init_ != NULL
     555                 :     1252341 :           && this->init_->is_error_expression()))
     556                 :             :     {
     557                 :          35 :       go_assert(saw_errors());
     558                 :          35 :       return Statement::make_error_statement(this->location());
     559                 :             :     }
     560                 :             : 
     561                 :     1463922 :   if (this->type_ != NULL
     562                 :      823475 :       && this->init_ != NULL
     563                 :      611894 :       && !Type::are_identical(this->type_, this->init_->type(),
     564                 :             :                               Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
     565                 :             :                               NULL)
     566                 :       18581 :       && this->init_->type()->interface_type() != NULL
     567                 :     1463922 :       && !this->init_->is_multi_eval_safe())
     568                 :             :     {
     569                 :           0 :       Temporary_statement *temp =
     570                 :           0 :         Statement::make_temporary(NULL, this->init_, this->location());
     571                 :           0 :       inserter->insert(temp);
     572                 :           0 :       this->init_ = Expression::make_temporary_reference(temp,
     573                 :             :                                                          this->location());
     574                 :             :     }
     575                 :     1463922 :   return this;
     576                 :             : }
     577                 :             : 
     578                 :             : // Add explicit type conversions.
     579                 :             : 
     580                 :             : void
     581                 :      514598 : Temporary_statement::do_add_conversions()
     582                 :             : {
     583                 :      514598 :   if (this->init_ == NULL)
     584                 :             :     return;
     585                 :      342879 :   Type* lt = this->type();
     586                 :      342879 :   Type* rt = this->init_->type();
     587                 :      342879 :   if (!Type::are_identical(lt, rt, 0, NULL)
     588                 :      342879 :       && lt->interface_type() != NULL)
     589                 :       20988 :     this->init_ = Expression::make_cast(lt, this->init_, this->location());
     590                 :             : }
     591                 :             : 
     592                 :             : // Convert to backend representation.
     593                 :             : 
     594                 :             : Bstatement*
     595                 :     1903823 : Temporary_statement::do_get_backend(Translate_context* context)
     596                 :             : {
     597                 :     1903823 :   go_assert(this->bvariable_ == NULL);
     598                 :             : 
     599                 :     1903823 :   Named_object* function = context->function();
     600                 :     1903823 :   go_assert(function != NULL);
     601                 :     1903823 :   Bfunction* bfunction = function->func_value()->get_decl();
     602                 :     1903823 :   Btype* btype = this->type()->get_backend(context->gogo());
     603                 :             : 
     604                 :     1903823 :   Bexpression* binit;
     605                 :     1903823 :   if (this->init_ == NULL)
     606                 :             :     binit = NULL;
     607                 :     1692809 :   else if (this->type_ == NULL)
     608                 :      832493 :     binit = this->init_->get_backend(context);
     609                 :             :   else
     610                 :             :     {
     611                 :      860316 :       Expression* init = Expression::convert_for_assignment(context->gogo(),
     612                 :             :                                                             this->type_,
     613                 :             :                                                             this->init_,
     614                 :             :                                                             this->location());
     615                 :      860316 :       binit = init->get_backend(context);
     616                 :             :     }
     617                 :             : 
     618                 :     1692809 :   if (binit != NULL)
     619                 :     1692809 :     binit = context->backend()->convert_expression(btype, binit,
     620                 :             :                                                    this->location());
     621                 :             : 
     622                 :     1903823 :   unsigned int flags = 0;
     623                 :     1903823 :   if (this->is_address_taken_)
     624                 :       43829 :     flags |= Backend::variable_address_is_taken;
     625                 :     1903823 :   Bstatement* statement;
     626                 :     1903823 :   this->bvariable_ =
     627                 :     1903823 :     context->backend()->temporary_variable(bfunction, context->bblock(),
     628                 :             :                                            btype, binit, flags,
     629                 :             :                                            this->location(), &statement);
     630                 :     1903823 :   return statement;
     631                 :             : }
     632                 :             : 
     633                 :             : // Return the backend variable.
     634                 :             : 
     635                 :             : Bvariable*
     636                 :     3816319 : Temporary_statement::get_backend_variable(Translate_context* context) const
     637                 :             : {
     638                 :     3816319 :   if (this->bvariable_ == NULL)
     639                 :             :     {
     640                 :           0 :       go_assert(saw_errors());
     641                 :           0 :       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                 :           0 : Temporary_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
     650                 :             : {
     651                 :           0 :   ast_dump_context->print_indent();
     652                 :           0 :   ast_dump_context->dump_temp_variable_name(this);
     653                 :           0 :   if (this->type_ != NULL)
     654                 :             :     {
     655                 :           0 :       ast_dump_context->ostream() << " ";
     656                 :           0 :       ast_dump_context->dump_type(this->type_);
     657                 :             :     }
     658                 :           0 :   if (this->init_ != NULL)
     659                 :             :     {
     660                 :           0 :       ast_dump_context->ostream() << " = ";
     661                 :           0 :       ast_dump_context->dump_expression(this->init_);
     662                 :             :     }
     663                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
     664                 :           0 : }
     665                 :             : 
     666                 :             : // Make and initialize a temporary variable in BLOCK.
     667                 :             : 
     668                 :             : Temporary_statement*
     669                 :     1907166 : Statement::make_temporary(Type* type, Expression* init,
     670                 :             :                           Location location)
     671                 :             : {
     672                 :     1907166 :   return new Temporary_statement(type, init, location);
     673                 :             : }
     674                 :             : 
     675                 :             : // Export a temporary statement.
     676                 :             : 
     677                 :             : void
     678                 :        4501 : Temporary_statement::do_export_statement(Export_function_body* efb)
     679                 :             : {
     680                 :        4501 :   unsigned int idx = efb->record_temporary(this);
     681                 :        4501 :   char buf[100];
     682                 :        4501 :   snprintf(buf, sizeof buf, "var $t%u", idx);
     683                 :        4501 :   efb->write_c_string(buf);
     684                 :        4501 :   if (this->type_ != NULL)
     685                 :             :     {
     686                 :        3641 :       efb->write_c_string(" ");
     687                 :        3641 :       efb->write_type(this->type_);
     688                 :             :     }
     689                 :        4501 :   if (this->init_ != NULL)
     690                 :             :     {
     691                 :        3924 :       efb->write_c_string(" = ");
     692                 :             : 
     693                 :        3924 :       go_assert(efb->type_context() == NULL);
     694                 :        3924 :       efb->set_type_context(this->type_);
     695                 :             : 
     696                 :        3924 :       this->init_->export_expression(efb);
     697                 :             : 
     698                 :        3924 :       efb->set_type_context(NULL);
     699                 :             :     }
     700                 :        4501 : }
     701                 :             : 
     702                 :             : // Import a temporary statement.
     703                 :             : 
     704                 :             : Statement*
     705                 :        2661 : Temporary_statement::do_import(Import_function_body* ifb, Location loc)
     706                 :             : {
     707                 :        2661 :   ifb->require_c_string("var ");
     708                 :        2661 :   std::string id = ifb->read_identifier();
     709                 :        2661 :   go_assert(id[0] == '$' && id[1] == 't');
     710                 :        2661 :   const char *p = id.c_str();
     711                 :        2661 :   char *end;
     712                 :        2661 :   long idx = strtol(p + 2, &end, 10);
     713                 :        2661 :   if (*end != '\0' || idx > 0x7fffffff)
     714                 :             :     {
     715                 :           0 :       if (!ifb->saw_error())
     716                 :           0 :         go_error_at(loc,
     717                 :             :                     ("invalid export data for %qs: "
     718                 :             :                      "bad temporary statement index at %lu"),
     719                 :           0 :                     ifb->name().c_str(),
     720                 :           0 :                     static_cast<unsigned long>(ifb->off()));
     721                 :           0 :       ifb->set_saw_error();
     722                 :           0 :       return Statement::make_error_statement(loc);
     723                 :             :     }
     724                 :             : 
     725                 :        2661 :   Type* type = NULL;
     726                 :        2661 :   if (!ifb->match_c_string(" = "))
     727                 :             :     {
     728                 :        2661 :       ifb->require_c_string(" ");
     729                 :        2661 :       type = ifb->read_type();
     730                 :             :     }
     731                 :        2661 :   Expression* init = NULL;
     732                 :        2661 :   if (ifb->match_c_string(" = "))
     733                 :             :     {
     734                 :        2309 :       ifb->advance(3);
     735                 :        2309 :       init = Expression::import_expression(ifb, loc);
     736                 :             :     }
     737                 :        2661 :   if (type == NULL && init == NULL)
     738                 :             :     {
     739                 :           0 :       if (!ifb->saw_error())
     740                 :           0 :         go_error_at(loc,
     741                 :             :                     ("invalid export data for %qs: "
     742                 :             :                      "temporary statement has neither type nor init at %lu"),
     743                 :           0 :                     ifb->name().c_str(),
     744                 :           0 :                     static_cast<unsigned long>(ifb->off()));
     745                 :           0 :       ifb->set_saw_error();
     746                 :             :       return Statement::make_error_statement(loc);
     747                 :             :     }
     748                 :             : 
     749                 :        2661 :   Temporary_statement* temp = Statement::make_temporary(type, init, loc);
     750                 :             : 
     751                 :        2661 :   ifb->record_temporary(temp, static_cast<unsigned int>(idx));
     752                 :             : 
     753                 :        2661 :   return temp;
     754                 :        2661 : }
     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                 :       16568 : class Move_subexpressions : public Traverse
     762                 :             : {
     763                 :             :  public:
     764                 :       19017 :   Move_subexpressions(int skip, Block* block)
     765                 :       19017 :     : Traverse(traverse_expressions),
     766                 :       19017 :       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                 :       23414 : Move_subexpressions::expression(Expression** pexpr)
     783                 :             : {
     784                 :       23414 :   if (this->skip_ > 0)
     785                 :        2017 :     --this->skip_;
     786                 :       21397 :   else if ((*pexpr)->temporary_reference_expression() == NULL
     787                 :       21103 :            && !(*pexpr)->is_nil_expression()
     788                 :       21089 :            && !(*pexpr)->is_constant())
     789                 :             :     {
     790                 :       19685 :       Location loc = (*pexpr)->location();
     791                 :       19685 :       Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
     792                 :       19685 :       this->block_->add_statement(temp);
     793                 :       19685 :       *pexpr = Expression::make_temporary_reference(temp, loc);
     794                 :             :     }
     795                 :             :   // We only need to move top-level subexpressions.
     796                 :       23414 :   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                 :       84127 : class Move_ordered_evals : public Traverse
     804                 :             : {
     805                 :             :  public:
     806                 :      202938 :   Move_ordered_evals(Block* block)
     807                 :      202938 :     : Traverse(traverse_expressions),
     808                 :      202938 :       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                 :      277244 : Move_ordered_evals::expression(Expression** pexpr)
     822                 :             : {
     823                 :             :   // We have to look at subexpressions first.
     824                 :      277244 :   if ((*pexpr)->traverse_subexpressions(this) == TRAVERSE_EXIT)
     825                 :             :     return TRAVERSE_EXIT;
     826                 :             : 
     827                 :      277244 :   int i;
     828                 :      277244 :   if ((*pexpr)->must_eval_subexpressions_in_order(&i))
     829                 :             :     {
     830                 :       16568 :       Move_subexpressions ms(i, this->block_);
     831                 :       16568 :       if ((*pexpr)->traverse_subexpressions(&ms) == TRAVERSE_EXIT)
     832                 :           0 :         return TRAVERSE_EXIT;
     833                 :       16568 :     }
     834                 :             : 
     835                 :      277244 :   if ((*pexpr)->must_eval_in_order())
     836                 :             :     {
     837                 :         667 :       Call_expression* call = (*pexpr)->call_expression();
     838                 :         666 :       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                 :           0 :           return TRAVERSE_SKIP_COMPONENTS;
     846                 :             :         }
     847                 :             : 
     848                 :         667 :       Location loc = (*pexpr)->location();
     849                 :         667 :       Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
     850                 :         667 :       this->block_->add_statement(temp);
     851                 :         667 :       *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                 :    18720094 : Assignment_statement::do_traverse(Traverse* traverse)
     862                 :             : {
     863                 :    18720094 :   if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
     864                 :             :     return TRAVERSE_EXIT;
     865                 :    18654250 :   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                 :     1388001 : Assignment_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
     873                 :             :                                Statement_inserter*)
     874                 :             : {
     875                 :     1388001 :   Map_index_expression* mie = this->lhs_->map_index_expression();
     876                 :     1388001 :   if (mie != NULL)
     877                 :             :     {
     878                 :        5656 :       Location loc = this->location();
     879                 :             : 
     880                 :        5656 :       Expression* map = mie->map();
     881                 :        5656 :       Map_type* mt = map->type()->map_type();
     882                 :        5656 :       if (mt == NULL)
     883                 :             :         {
     884                 :           0 :           go_assert(saw_errors());
     885                 :           0 :           return Statement::make_error_statement(loc);
     886                 :             :         }
     887                 :             : 
     888                 :        5656 :       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                 :        5656 :       Move_ordered_evals moe(b);
     893                 :        5656 :       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                 :        5656 :       Temporary_statement* key_temp = Statement::make_temporary(mt->key_type(),
     900                 :             :                                                                 mie->index(),
     901                 :             :                                                                 loc);
     902                 :        5656 :       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                 :        5656 :       Temporary_statement* val_temp = Statement::make_temporary(mt->val_type(),
     910                 :             :                                                                 this->rhs_,
     911                 :             :                                                                 loc);
     912                 :        5656 :       b->add_statement(val_temp);
     913                 :             : 
     914                 :             :       // *mapassign(TYPE, MAP, &key_temp) = RHS
     915                 :        5656 :       Expression* a1 = Expression::make_type_descriptor(mt, loc);
     916                 :        5656 :       Expression* a2 = mie->map();
     917                 :        5656 :       Temporary_reference_expression* ref =
     918                 :        5656 :         Expression::make_temporary_reference(key_temp, loc);
     919                 :        5656 :       Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc);
     920                 :        5656 :       Runtime::Function code;
     921                 :        5656 :       Map_type::Map_alg alg = mt->algorithm(gogo);
     922                 :        5656 :       switch (alg)
     923                 :             :         {
     924                 :         323 :           case Map_type::MAP_ALG_FAST32:
     925                 :         323 :             {
     926                 :         323 :               code = Runtime::MAPASSIGN_FAST32;
     927                 :         323 :               Type* uint32_type = Type::lookup_integer_type("uint32");
     928                 :         323 :               Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
     929                 :         323 :               a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3,
     930                 :             :                                                 loc);
     931                 :         323 :               a3 = Expression::make_dereference(a3,
     932                 :             :                                                 Expression::NIL_CHECK_NOT_NEEDED,
     933                 :             :                                                 loc);
     934                 :         323 :               break;
     935                 :             :             }
     936                 :         776 :           case Map_type::MAP_ALG_FAST64:
     937                 :         776 :             {
     938                 :         776 :               code = Runtime::MAPASSIGN_FAST64;
     939                 :         776 :               Type* uint64_type = Type::lookup_integer_type("uint64");
     940                 :         776 :               Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
     941                 :         776 :               a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3,
     942                 :             :                                                 loc);
     943                 :         776 :               a3 = Expression::make_dereference(a3,
     944                 :             :                                                 Expression::NIL_CHECK_NOT_NEEDED,
     945                 :             :                                                 loc);
     946                 :         776 :               break;
     947                 :             :             }
     948                 :         593 :           case Map_type::MAP_ALG_FAST32PTR:
     949                 :         593 :           case Map_type::MAP_ALG_FAST64PTR:
     950                 :         593 :             {
     951                 :        1186 :               code = (alg == Map_type::MAP_ALG_FAST32PTR
     952                 :         593 :                       ? Runtime::MAPASSIGN_FAST32PTR
     953                 :             :                       : Runtime::MAPASSIGN_FAST64PTR);
     954                 :         593 :               Type* ptr_type =
     955                 :         593 :                 Type::make_pointer_type(Type::make_void_type());
     956                 :         593 :               Type* ptr_ptr_type = Type::make_pointer_type(ptr_type);
     957                 :         593 :               a3 = Expression::make_unsafe_cast(ptr_ptr_type, a3,
     958                 :             :                                                 loc);
     959                 :         593 :               a3 = Expression::make_dereference(a3,
     960                 :             :                                                 Expression::NIL_CHECK_NOT_NEEDED,
     961                 :             :                                                 loc);
     962                 :         593 :               break;
     963                 :             :             }
     964                 :             :           case Map_type::MAP_ALG_FASTSTR:
     965                 :             :             code = Runtime::MAPASSIGN_FASTSTR;
     966                 :             :             a3 = ref;
     967                 :             :             break;
     968                 :        1309 :           default:
     969                 :        1309 :             code = Runtime::MAPASSIGN;
     970                 :        1309 :             break;
     971                 :             :         }
     972                 :        5656 :       Expression* call = Runtime::make_call(gogo, code, loc, 3,
     973                 :             :                                             a1, a2, a3);
     974                 :        5656 :       Type* ptrval_type = Type::make_pointer_type(mt->val_type());
     975                 :        5656 :       call = Expression::make_cast(ptrval_type, call, loc);
     976                 :        5656 :       Expression* indir =
     977                 :        5656 :           Expression::make_dereference(call, Expression::NIL_CHECK_NOT_NEEDED,
     978                 :             :                                        loc);
     979                 :        5656 :       ref = Expression::make_temporary_reference(val_temp, loc);
     980                 :        5656 :       Statement* s = Statement::make_assignment(indir, ref, loc);
     981                 :        5656 :       s->determine_types(gogo);
     982                 :        5656 :       b->add_statement(s);
     983                 :             : 
     984                 :        5656 :       return Statement::make_block_statement(b, loc);
     985                 :        5656 :     }
     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                 :     1382345 :   Array_index_expression* aie = this->rhs_->array_index_expression();
     990                 :       70177 :   if (aie != NULL
     991                 :       70177 :       && aie->end() != NULL
     992                 :       14092 :       && Expression::is_same_variable(this->lhs_, aie->array()))
     993                 :             :     {
     994                 :        8161 :       Numeric_constant nc;
     995                 :        8161 :       unsigned long ival;
     996                 :        8161 :       if (aie->start()->numeric_constant_value(&nc)
     997                 :        6158 :           && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID
     998                 :       14319 :           && ival == 0)
     999                 :        4034 :         this->omit_write_barrier_ = true;
    1000                 :        8161 :     }
    1001                 :     1382345 :   String_index_expression* sie = this->rhs_->string_index_expression();
    1002                 :        6799 :   if (sie != NULL
    1003                 :        6799 :       && sie->end() != NULL
    1004                 :        5973 :       && Expression::is_same_variable(this->lhs_, sie->string()))
    1005                 :             :     {
    1006                 :        3978 :       Numeric_constant nc;
    1007                 :        3978 :       unsigned long ival;
    1008                 :        3978 :       if (sie->start()->numeric_constant_value(&nc)
    1009                 :        2917 :           && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID
    1010                 :        6895 :           && ival == 0)
    1011                 :         829 :         this->omit_write_barrier_ = true;
    1012                 :        3978 :     }
    1013                 :             : 
    1014                 :     1382345 :   return this;
    1015                 :             : }
    1016                 :             : 
    1017                 :             : // Set types for the assignment.
    1018                 :             : 
    1019                 :             : void
    1020                 :     1468333 : Assignment_statement::do_determine_types(Gogo* gogo)
    1021                 :             : {
    1022                 :     1468333 :   this->lhs_->determine_type_no_context(gogo);
    1023                 :     1468333 :   Type* rhs_context_type = this->lhs_->type();
    1024                 :     1468333 :   if (rhs_context_type->is_sink_type())
    1025                 :        7388 :     rhs_context_type = NULL;
    1026                 :     1468333 :   Type_context context(rhs_context_type, false);
    1027                 :     1468333 :   this->rhs_->determine_type(gogo, &context);
    1028                 :     1468333 : }
    1029                 :             : 
    1030                 :             : // Check types for an assignment from RHS to LHS.  Returns true if the
    1031                 :             : // assignment is OK.
    1032                 :             : 
    1033                 :             : bool
    1034                 :      318331 : 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                 :      318331 :   if (!lhs->is_addressable()
    1041                 :       33028 :       && !Index_expression::is_map_index(lhs)
    1042                 :      345940 :       && !lhs->is_sink_expression())
    1043                 :             :     {
    1044                 :           8 :       if (!lhs->type()->is_error())
    1045                 :           8 :         go_error_at(lhs->location(), "invalid left hand side of assignment");
    1046                 :           8 :       return false;
    1047                 :             :     }
    1048                 :             : 
    1049                 :      318323 :   Type* lhs_type = lhs->type();
    1050                 :             : 
    1051                 :             :   // Check for invalid assignment of nil to the blank identifier.
    1052                 :      318323 :   if (lhs_type->is_sink_type() && rhs_type->is_nil_type())
    1053                 :             :     {
    1054                 :           3 :       go_error_at(loc, "use of untyped nil");
    1055                 :           3 :       return false;
    1056                 :             :     }
    1057                 :             : 
    1058                 :      318320 :   std::string reason;
    1059                 :      318320 :   if (!Type::are_assignable(lhs_type, rhs_type, &reason))
    1060                 :             :     {
    1061                 :          96 :       if (reason.empty())
    1062                 :           0 :         go_error_at(loc, "incompatible types in assignment");
    1063                 :             :       else
    1064                 :          96 :         go_error_at(loc, "incompatible types in assignment (%s)",
    1065                 :             :                     reason.c_str());
    1066                 :          96 :       return false;
    1067                 :             :     }
    1068                 :             : 
    1069                 :      318224 :   if (lhs_type->is_error_type() || rhs_type->is_error_type())
    1070                 :          61 :     return false;
    1071                 :             : 
    1072                 :             :   return true;
    1073                 :      318320 : }
    1074                 :             : 
    1075                 :             : // Check types for an assignment.
    1076                 :             : 
    1077                 :             : void
    1078                 :      193257 : Assignment_statement::do_check_types(Gogo*)
    1079                 :             : {
    1080                 :      193257 :   if (!Assignment_statement::check_assignment_types(this->lhs_,
    1081                 :      193257 :                                                     this->rhs_->type(),
    1082                 :             :                                                     this->location()))
    1083                 :         159 :     this->set_is_error();
    1084                 :      193257 : }
    1085                 :             : 
    1086                 :             : void
    1087                 :       20287 : Assignment_statement::do_export_statement(Export_function_body* efb)
    1088                 :             : {
    1089                 :       20287 :   this->lhs_->export_expression(efb);
    1090                 :       20287 :   efb->write_c_string(" = ");
    1091                 :       20287 :   this->rhs_->export_expression(efb);
    1092                 :       20287 : }
    1093                 :             : 
    1094                 :             : // Flatten an assignment statement.  We may need a temporary for
    1095                 :             : // interface conversion.
    1096                 :             : 
    1097                 :             : Statement*
    1098                 :     1141788 : Assignment_statement::do_flatten(Gogo*, Named_object*, Block*,
    1099                 :             :                                  Statement_inserter* inserter)
    1100                 :             : {
    1101                 :     1141788 :   if (this->lhs_->is_error_expression()
    1102                 :     1141787 :       || this->lhs_->type()->is_error_type()
    1103                 :     1141786 :       || this->rhs_->is_error_expression()
    1104                 :     2283312 :       || this->rhs_->type()->is_error_type())
    1105                 :             :     {
    1106                 :         269 :       go_assert(saw_errors());
    1107                 :         269 :       return Statement::make_error_statement(this->location());
    1108                 :             :     }
    1109                 :             : 
    1110                 :     1141519 :   if (!this->lhs_->is_sink_expression()
    1111                 :     1134940 :       && !Type::are_identical(this->lhs_->type(), this->rhs_->type(),
    1112                 :             :                               Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
    1113                 :             :                               NULL)
    1114                 :       16722 :       && this->rhs_->type()->interface_type() != NULL
    1115                 :     1141519 :       && !this->rhs_->is_multi_eval_safe())
    1116                 :             :     {
    1117                 :           0 :       Temporary_statement* temp =
    1118                 :           0 :         Statement::make_temporary(NULL, this->rhs_, this->location());
    1119                 :           0 :       inserter->insert(temp);
    1120                 :           0 :       this->rhs_ = Expression::make_temporary_reference(temp,
    1121                 :             :                                                         this->location());
    1122                 :             :     }
    1123                 :     1141519 :   return this;
    1124                 :             : }
    1125                 :             : 
    1126                 :             : // Add explicit type conversions.
    1127                 :             : 
    1128                 :             : void
    1129                 :      727205 : Assignment_statement::do_add_conversions()
    1130                 :             : {
    1131                 :      727205 :   Type* lt = this->lhs_->type();
    1132                 :      727205 :   Type* rt = this->rhs_->type();
    1133                 :      727205 :   if (!Type::are_identical(lt, rt, 0, NULL)
    1134                 :      727205 :       && lt->interface_type() != NULL)
    1135                 :       20556 :     this->rhs_ = Expression::make_cast(lt, this->rhs_, this->location());
    1136                 :      727205 : }
    1137                 :             : 
    1138                 :             : // Convert an assignment statement to the backend representation.
    1139                 :             : 
    1140                 :             : Bstatement*
    1141                 :     1224772 : Assignment_statement::do_get_backend(Translate_context* context)
    1142                 :             : {
    1143                 :     1224772 :   if (this->lhs_->is_sink_expression())
    1144                 :             :     {
    1145                 :        4494 :       Bexpression* rhs = this->rhs_->get_backend(context);
    1146                 :        4494 :       Bfunction* bfunction = context->function()->func_value()->get_decl();
    1147                 :        4494 :       return context->backend()->expression_statement(bfunction, rhs);
    1148                 :             :     }
    1149                 :             : 
    1150                 :     1220278 :   Bexpression* lhs = this->lhs_->get_backend(context);
    1151                 :     1220278 :   Expression* conv =
    1152                 :     1220278 :       Expression::convert_for_assignment(context->gogo(), this->lhs_->type(),
    1153                 :             :                                          this->rhs_, this->location());
    1154                 :     1220278 :   Bexpression* rhs = conv->get_backend(context);
    1155                 :     1220278 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    1156                 :     1220278 :   return context->backend()->assignment_statement(bfunction, lhs, rhs,
    1157                 :     1220278 :                                                   this->location());
    1158                 :             : }
    1159                 :             : 
    1160                 :             : // Dump the AST representation for an assignment statement.
    1161                 :             : 
    1162                 :             : void
    1163                 :           0 : Assignment_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    1164                 :             :     const
    1165                 :             : {
    1166                 :           0 :   ast_dump_context->print_indent();
    1167                 :           0 :   ast_dump_context->dump_expression(this->lhs_);
    1168                 :           0 :   ast_dump_context->ostream() << " = " ;
    1169                 :           0 :   ast_dump_context->dump_expression(this->rhs_);
    1170                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    1171                 :           0 : }
    1172                 :             : 
    1173                 :             : // Make an assignment statement.
    1174                 :             : 
    1175                 :             : Assignment_statement*
    1176                 :     1340852 : Statement::make_assignment(Expression* lhs, Expression* rhs,
    1177                 :             :                            Location location)
    1178                 :             : {
    1179                 :     1340852 :   Temporary_reference_expression* tre = lhs->temporary_reference_expression();
    1180                 :      214261 :   if (tre != NULL)
    1181                 :      214261 :     tre->statement()->set_assigned();
    1182                 :     1340852 :   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                 :       84155 :   Assignment_operation_statement(Operator op, Expression* lhs, Expression* rhs,
    1191                 :             :                                  Location location)
    1192                 :       84155 :     : Statement(STATEMENT_ASSIGNMENT_OPERATION, location),
    1193                 :      168310 :       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                 :           0 :   do_get_backend(Translate_context*)
    1211                 :           0 :   { 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                 :      185363 : Assignment_operation_statement::do_traverse(Traverse* traverse)
    1232                 :             : {
    1233                 :      185363 :   if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
    1234                 :             :     return TRAVERSE_EXIT;
    1235                 :      185363 :   return this->traverse_expression(traverse, &this->rhs_);
    1236                 :             : }
    1237                 :             : 
    1238                 :             : void
    1239                 :       25309 : Assignment_operation_statement::do_determine_types(Gogo* gogo)
    1240                 :             : {
    1241                 :       25309 :   this->lhs_->determine_type_no_context(gogo);
    1242                 :       25309 :   Type* rhs_context_type = this->lhs_->type();
    1243                 :       25309 :   if (rhs_context_type->is_sink_type())
    1244                 :           0 :     rhs_context_type = NULL;
    1245                 :       25309 :   Type_context context(rhs_context_type, false);
    1246                 :       25309 :   this->rhs_->determine_type(gogo, &context);
    1247                 :       25309 : }
    1248                 :             : 
    1249                 :             : // Get the binary operator from the assignment operator.
    1250                 :             : 
    1251                 :             : Operator
    1252                 :      107708 : Assignment_operation_statement::get_binop()
    1253                 :             : {
    1254                 :      107708 :   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                 :           0 :     default:
    1279                 :           0 :       go_unreachable();
    1280                 :             :     }
    1281                 :             : }
    1282                 :             : 
    1283                 :             : void
    1284                 :       25309 : Assignment_operation_statement::do_check_types(Gogo*)
    1285                 :             : {
    1286                 :       25309 :   if (this->lhs_->is_sink_expression())
    1287                 :             :     {
    1288                 :           0 :       this->report_error(_("cannot use %<_%> as value"));
    1289                 :           0 :       return;
    1290                 :             :     }
    1291                 :             : 
    1292                 :             : 
    1293                 :       25309 :   Type* lhs_type = this->lhs_->type();
    1294                 :       25309 :   Type* rhs_type = this->rhs_->type();
    1295                 :             : 
    1296                 :       25309 :   if (!this->lhs_->is_addressable()
    1297                 :       25309 :       && !Index_expression::is_map_index(this->lhs_))
    1298                 :             :     {
    1299                 :           0 :       if (!lhs_type->is_error())
    1300                 :           0 :         this->report_error(_("invalid left hand side of assignment"));
    1301                 :           0 :       this->set_is_error();
    1302                 :           0 :       return;
    1303                 :             :     }
    1304                 :             : 
    1305                 :       25309 :   if (this->op_ != OPERATOR_LSHIFTEQ && this->op_ != OPERATOR_RSHIFTEQ)
    1306                 :             :     {
    1307                 :       23581 :       if (!Type::are_compatible_for_binop(lhs_type, rhs_type))
    1308                 :             :         {
    1309                 :           0 :           this->report_error(_("incompatible type in binary expression"));
    1310                 :           0 :           return;
    1311                 :             :         }
    1312                 :       23581 :       if (!Binary_expression::check_operator_type(this->get_binop(), lhs_type,
    1313                 :             :                                                   rhs_type, this->location()))
    1314                 :             :         {
    1315                 :           1 :           this->set_is_error();
    1316                 :           1 :           return;
    1317                 :             :         }
    1318                 :       23580 :       if (this->op_ == OPERATOR_DIVEQ || this->op_ == OPERATOR_MODEQ)
    1319                 :             :         {
    1320                 :         461 :           Numeric_constant rconst;
    1321                 :         461 :           unsigned long rval;
    1322                 :         461 :           if (lhs_type->integer_type() != NULL
    1323                 :         370 :               && this->rhs_->numeric_constant_value(&rconst)
    1324                 :         332 :               && rconst.to_unsigned_long(&rval) == Numeric_constant::NC_UL_VALID
    1325                 :         332 :               && rval == 0)
    1326                 :             :             {
    1327                 :           0 :               this->report_error(_("integer division by zero"));
    1328                 :           0 :               return;
    1329                 :             :             }
    1330                 :         461 :         }
    1331                 :             :     }
    1332                 :             :   else
    1333                 :             :     {
    1334                 :        1728 :       if (lhs_type->integer_type() == NULL)
    1335                 :             :         {
    1336                 :           0 :           this->report_error(_("shift of non-integer operand"));
    1337                 :           0 :           return;
    1338                 :             :         }
    1339                 :             : 
    1340                 :        1728 :       if (rhs_type->is_string_type()
    1341                 :        1728 :           || (!rhs_type->is_abstract()
    1342                 :        1728 :               && rhs_type->integer_type() == NULL))
    1343                 :             :         {
    1344                 :           0 :           this->report_error(_("shift count not integer"));
    1345                 :           0 :           return;
    1346                 :             :         }
    1347                 :             : 
    1348                 :        1728 :       Numeric_constant nc;
    1349                 :        1728 :       if (this->rhs_->numeric_constant_value(&nc))
    1350                 :             :         {
    1351                 :        1462 :           mpz_t val;
    1352                 :        1462 :           if (!nc.to_int(&val))
    1353                 :             :             {
    1354                 :           0 :               this->report_error(_("shift count not integer"));
    1355                 :           0 :               return;
    1356                 :             :             }
    1357                 :        1462 :           if (mpz_sgn(val) < 0)
    1358                 :           0 :             this->report_error(_("negative shift count"));
    1359                 :        1462 :           mpz_clear(val);
    1360                 :             :         }
    1361                 :        1728 :     }
    1362                 :             : }
    1363                 :             : 
    1364                 :             : // Lower an assignment operation statement to a regular assignment
    1365                 :             : // statement.
    1366                 :             : 
    1367                 :             : Statement*
    1368                 :       84127 : Assignment_operation_statement::do_lower(Gogo* gogo, Named_object*,
    1369                 :             :                                          Block* enclosing, Statement_inserter*)
    1370                 :             : {
    1371                 :       84127 :   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                 :       84127 :   Block* b = new Block(enclosing, loc);
    1376                 :       84127 :   Move_ordered_evals moe(b);
    1377                 :       84127 :   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                 :       84127 :   int i;
    1383                 :       84127 :   if (this->lhs_->must_eval_subexpressions_in_order(&i))
    1384                 :             :     {
    1385                 :        2449 :       Move_subexpressions ms(i, b);
    1386                 :        2449 :       this->lhs_->traverse_subexpressions(&ms);
    1387                 :        2449 :     }
    1388                 :             : 
    1389                 :       84127 :   Expression* lval = this->lhs_->copy();
    1390                 :             : 
    1391                 :       84127 :   Expression* binop = Expression::make_binary(this->get_binop(), lval,
    1392                 :             :                                               this->rhs_, loc);
    1393                 :       84127 :   Statement* s = Statement::make_assignment(this->lhs_, binop, loc);
    1394                 :       84127 :   s->determine_types(gogo);
    1395                 :       84127 :   if (b->statements()->empty())
    1396                 :             :     {
    1397                 :       75389 :       delete b;
    1398                 :       75389 :       return s;
    1399                 :             :     }
    1400                 :             :   else
    1401                 :             :     {
    1402                 :        8738 :       b->add_statement(s);
    1403                 :        8738 :       return Statement::make_block_statement(b, loc);
    1404                 :             :     }
    1405                 :       84127 : }
    1406                 :             : 
    1407                 :             : // Dump the AST representation for an assignment operation statement
    1408                 :             : 
    1409                 :             : void
    1410                 :           0 : Assignment_operation_statement::do_dump_statement(
    1411                 :             :     Ast_dump_context* ast_dump_context) const
    1412                 :             : {
    1413                 :           0 :   ast_dump_context->print_indent();
    1414                 :           0 :   ast_dump_context->dump_expression(this->lhs_);
    1415                 :           0 :   ast_dump_context->dump_operator(this->op_);
    1416                 :           0 :   ast_dump_context->dump_expression(this->rhs_);
    1417                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    1418                 :           0 : }
    1419                 :             : 
    1420                 :             : // Make an assignment operation statement.
    1421                 :             : 
    1422                 :             : Statement*
    1423                 :       84155 : Statement::make_assignment_operation(Operator op, Expression* lhs,
    1424                 :             :                                      Expression* rhs, Location location)
    1425                 :             : {
    1426                 :       84155 :   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                 :      103919 :   Tuple_assignment_statement(Expression_list* lhs, Expression_list* rhs,
    1437                 :             :                              Location location)
    1438                 :      103919 :     : Statement(STATEMENT_TUPLE_ASSIGNMENT, location),
    1439                 :      207838 :       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                 :           0 :   do_get_backend(Translate_context*)
    1457                 :           0 :   { 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                 :      214525 : Tuple_assignment_statement::do_traverse(Traverse* traverse)
    1473                 :             : {
    1474                 :      214525 :   if (this->traverse_expression_list(traverse, this->lhs_) == TRAVERSE_EXIT)
    1475                 :             :     return TRAVERSE_EXIT;
    1476                 :      214525 :   return this->traverse_expression_list(traverse, this->rhs_);
    1477                 :             : }
    1478                 :             : 
    1479                 :             : void
    1480                 :      126171 : Tuple_assignment_statement::do_determine_types(Gogo* gogo)
    1481                 :             : {
    1482                 :      126171 :   Expression_list::iterator pr = this->rhs_->begin();
    1483                 :      126171 :   for (Expression_list::iterator pl = this->lhs_->begin();
    1484                 :      391441 :        pl != this->lhs_->end();
    1485                 :      265270 :        ++pl, ++pr)
    1486                 :             :     {
    1487                 :      265270 :       go_assert(pr != this->rhs_->end());
    1488                 :      265270 :       (*pl)->determine_type_no_context(gogo);
    1489                 :      265270 :       Type* rhs_context_type = (*pl)->type();
    1490                 :      265270 :       if (rhs_context_type->is_sink_type())
    1491                 :       36878 :         rhs_context_type = NULL;
    1492                 :      265270 :       Type_context context(rhs_context_type, false);
    1493                 :      265270 :       (*pr)->determine_type(gogo, &context);
    1494                 :             :     }
    1495                 :      126171 :   go_assert(pr == this->rhs_->end());
    1496                 :      126171 : }
    1497                 :             : 
    1498                 :             : void
    1499                 :       27653 : Tuple_assignment_statement::do_check_types(Gogo*)
    1500                 :             : {
    1501                 :       27653 :   Expression_list::iterator pr = this->rhs_->begin();
    1502                 :       27653 :   for (Expression_list::iterator pl = this->lhs_->begin();
    1503                 :       86520 :        pl != this->lhs_->end();
    1504                 :       58867 :        ++pl, ++pr)
    1505                 :             :     {
    1506                 :       58867 :       go_assert(pr != this->rhs_->end());
    1507                 :       58867 :       if (!Assignment_statement::check_assignment_types(*pl, (*pr)->type(),
    1508                 :             :                                                         this->location()))
    1509                 :           8 :         this->set_is_error();
    1510                 :             :     }
    1511                 :       27653 :   go_assert(pr == this->rhs_->end());
    1512                 :       27653 : }
    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                 :      103913 : Tuple_assignment_statement::do_lower(Gogo* gogo, Named_object*,
    1519                 :             :                                      Block* enclosing, Statement_inserter*)
    1520                 :             : {
    1521                 :      103913 :   Location loc = this->location();
    1522                 :             : 
    1523                 :      103913 :   if (this->classification() == STATEMENT_ERROR)
    1524                 :           0 :     return Statement::make_error_statement(loc);
    1525                 :             : 
    1526                 :      103913 :   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                 :      103913 :   Move_ordered_evals moe(b);
    1531                 :      324664 :   for (Expression_list::iterator plhs = this->lhs_->begin();
    1532                 :      324664 :        plhs != this->lhs_->end();
    1533                 :      220751 :        ++plhs)
    1534                 :      220751 :     Expression::traverse(&*plhs, &moe);
    1535                 :             : 
    1536                 :      103913 :   std::vector<Temporary_statement*> temps;
    1537                 :      103913 :   temps.reserve(this->lhs_->size());
    1538                 :             : 
    1539                 :      103913 :   Expression_list::const_iterator prhs = this->rhs_->begin();
    1540                 :      103913 :   for (Expression_list::const_iterator plhs = this->lhs_->begin();
    1541                 :      324664 :        plhs != this->lhs_->end();
    1542                 :      220751 :        ++plhs, ++prhs)
    1543                 :             :     {
    1544                 :      220751 :       go_assert(prhs != this->rhs_->end());
    1545                 :             : 
    1546                 :      220751 :       if ((*plhs)->is_error_expression()
    1547                 :      220751 :           || (*plhs)->type()->is_error()
    1548                 :      220750 :           || (*prhs)->is_error_expression()
    1549                 :      441495 :           || (*prhs)->type()->is_error())
    1550                 :       20510 :         continue;
    1551                 :             : 
    1552                 :      220744 :       if ((*plhs)->is_sink_expression())
    1553                 :             :         {
    1554                 :       20503 :           if ((*prhs)->type()->is_nil_type())
    1555                 :           0 :             this->report_error(_("use of untyped nil"));
    1556                 :             :           else
    1557                 :       20503 :             b->add_statement(Statement::make_statement(*prhs, true));
    1558                 :       20503 :           continue;
    1559                 :             :         }
    1560                 :             : 
    1561                 :      200241 :       Temporary_statement* temp = Statement::make_temporary((*plhs)->type(),
    1562                 :      200241 :                                                             *prhs, loc);
    1563                 :      200241 :       b->add_statement(temp);
    1564                 :      200241 :       temps.push_back(temp);
    1565                 :             : 
    1566                 :             :     }
    1567                 :      103913 :   go_assert(prhs == this->rhs_->end());
    1568                 :             : 
    1569                 :      103913 :   prhs = this->rhs_->begin();
    1570                 :      103913 :   std::vector<Temporary_statement*>::const_iterator ptemp = temps.begin();
    1571                 :      103913 :   for (Expression_list::const_iterator plhs = this->lhs_->begin();
    1572                 :      324664 :        plhs != this->lhs_->end();
    1573                 :      220751 :        ++plhs, ++prhs)
    1574                 :             :     {
    1575                 :      220751 :       if ((*plhs)->is_error_expression()
    1576                 :      220751 :           || (*plhs)->type()->is_error()
    1577                 :      220750 :           || (*prhs)->is_error_expression()
    1578                 :      441495 :           || (*prhs)->type()->is_error())
    1579                 :           7 :         continue;
    1580                 :             : 
    1581                 :      220744 :       if ((*plhs)->is_sink_expression())
    1582                 :       20503 :         continue;
    1583                 :             : 
    1584                 :      200241 :       Expression* ref = Expression::make_temporary_reference(*ptemp, loc);
    1585                 :      200241 :       Statement* s = Statement::make_assignment(*plhs, ref, loc);
    1586                 :      200241 :       s->determine_types(gogo);
    1587                 :      200241 :       b->add_statement(s);
    1588                 :      200241 :       ++ptemp;
    1589                 :             :     }
    1590                 :      103913 :   go_assert(ptemp == temps.end() || saw_errors());
    1591                 :             : 
    1592                 :      103913 :   return Statement::make_block_statement(b, loc);
    1593                 :      103913 : }
    1594                 :             : 
    1595                 :             : // Dump the AST representation for a tuple assignment statement.
    1596                 :             : 
    1597                 :             : void
    1598                 :           0 : Tuple_assignment_statement::do_dump_statement(
    1599                 :             :     Ast_dump_context* ast_dump_context) const
    1600                 :             : {
    1601                 :           0 :   ast_dump_context->print_indent();
    1602                 :           0 :   ast_dump_context->dump_expression_list(this->lhs_);
    1603                 :           0 :   ast_dump_context->ostream() << " = ";
    1604                 :           0 :   ast_dump_context->dump_expression_list(this->rhs_);
    1605                 :           0 :   ast_dump_context->ostream()  << dsuffix(location()) << std::endl;
    1606                 :           0 : }
    1607                 :             : 
    1608                 :             : // Make a tuple assignment statement.
    1609                 :             : 
    1610                 :             : Statement*
    1611                 :      103919 : Statement::make_tuple_assignment(Expression_list* lhs, Expression_list* rhs,
    1612                 :             :                                  Location location)
    1613                 :             : {
    1614                 :      103919 :   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                 :        2365 :   Tuple_map_assignment_statement(Expression* val, Expression* present,
    1624                 :             :                                  Expression* map_index,
    1625                 :             :                                  Location location)
    1626                 :        2365 :     : Statement(STATEMENT_TUPLE_MAP_ASSIGNMENT, location),
    1627                 :        4730 :       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                 :           0 :   do_get_backend(Translate_context*)
    1645                 :           0 :   { 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                 :       11825 : Tuple_map_assignment_statement::do_traverse(Traverse* traverse)
    1663                 :             : {
    1664                 :       11825 :   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
    1665                 :       11825 :       || this->traverse_expression(traverse, &this->present_) == TRAVERSE_EXIT)
    1666                 :           0 :     return TRAVERSE_EXIT;
    1667                 :       11825 :   return this->traverse_expression(traverse, &this->map_index_);
    1668                 :             : }
    1669                 :             : 
    1670                 :             : void
    1671                 :        2365 : Tuple_map_assignment_statement::do_determine_types(Gogo* gogo)
    1672                 :             : {
    1673                 :        2365 :   this->val_->determine_type_no_context(gogo);
    1674                 :        2365 :   this->present_->determine_type_no_context(gogo);
    1675                 :        2365 :   this->map_index_->determine_type_no_context(gogo);
    1676                 :        2365 : }
    1677                 :             : 
    1678                 :             : void
    1679                 :        2365 : Tuple_map_assignment_statement::do_check_types(Gogo*)
    1680                 :             : {
    1681                 :        2365 :   Expression* map_expr = this->map_index_;
    1682                 :        2365 :   Map_type* map_type;
    1683                 :        2365 :   if (map_expr->map_index_expression() != NULL)
    1684                 :           0 :     map_type = map_expr->map_index_expression()->get_map_type();
    1685                 :        2365 :   else if (map_expr->index_expression() != NULL)
    1686                 :        2365 :     map_type = map_expr->index_expression()->left()->type()->map_type();
    1687                 :             :   else
    1688                 :             :     {
    1689                 :           0 :       this->report_error(_("expected map index on right hand side"));
    1690                 :           0 :       return;
    1691                 :             :     }
    1692                 :        2365 :   if (map_type == NULL || map_type->is_error())
    1693                 :             :     {
    1694                 :           0 :       go_assert(saw_errors());
    1695                 :           0 :       this->set_is_error();
    1696                 :           0 :       return;
    1697                 :             :     }
    1698                 :             : 
    1699                 :        2365 :   if (!Assignment_statement::check_assignment_types(this->val_,
    1700                 :             :                                                     map_type->val_type(),
    1701                 :             :                                                     this->location()))
    1702                 :           0 :     this->set_is_error();
    1703                 :        2365 :   if (!Assignment_statement::check_assignment_types(this->present_,
    1704                 :             :                                                     Type::make_boolean_type(),
    1705                 :             :                                                     this->location()))
    1706                 :           0 :     this->set_is_error();
    1707                 :             : }
    1708                 :             : 
    1709                 :             : // Lower a tuple map assignment.
    1710                 :             : 
    1711                 :             : Statement*
    1712                 :        2365 : Tuple_map_assignment_statement::do_lower(Gogo* gogo, Named_object*,
    1713                 :             :                                          Block* enclosing, Statement_inserter*)
    1714                 :             : {
    1715                 :        2365 :   Location loc = this->location();
    1716                 :             : 
    1717                 :        2365 :   if (this->classification() == STATEMENT_ERROR)
    1718                 :           0 :     return Statement::make_error_statement(loc);
    1719                 :             : 
    1720                 :        2365 :   Map_index_expression* map_index = this->map_index_->map_index_expression();
    1721                 :           0 :   go_assert(map_index != NULL);
    1722                 :        2365 :   Map_type* map_type = map_index->get_map_type();
    1723                 :        2365 :   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                 :        2365 :   Type_conversion_expression* ce = map_index->index()->conversion_expression();
    1728                 :          31 :   if (ce != NULL && ce->type()->is_string_type()
    1729                 :          26 :       && ce->expr()->type()->is_slice_type())
    1730                 :          26 :     ce->set_no_copy(true);
    1731                 :             : 
    1732                 :        2365 :   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                 :        2365 :   Move_ordered_evals moe(b);
    1737                 :        2365 :   this->val_->traverse_subexpressions(&moe);
    1738                 :        2365 :   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                 :        2365 :   Temporary_statement* key_temp =
    1745                 :        2365 :     Statement::make_temporary(map_type->key_type(), map_index->index(), loc);
    1746                 :        2365 :   b->add_statement(key_temp);
    1747                 :             : 
    1748                 :             :   // var val_ptr_temp *VAL_TYPE
    1749                 :        2365 :   Type* val_ptr_type = Type::make_pointer_type(map_type->val_type());
    1750                 :        2365 :   Temporary_statement* val_ptr_temp = Statement::make_temporary(val_ptr_type,
    1751                 :             :                                                                 NULL, loc);
    1752                 :        2365 :   b->add_statement(val_ptr_temp);
    1753                 :             : 
    1754                 :             :   // var present_temp bool
    1755                 :        2365 :   Temporary_statement* present_temp =
    1756                 :        4730 :     Statement::make_temporary((this->present_->type()->is_boolean_type()
    1757                 :        2337 :                                ? this->present_->type()
    1758                 :          28 :                                : Type::lookup_bool_type()),
    1759                 :             :                               NULL, loc);
    1760                 :        2365 :   b->add_statement(present_temp);
    1761                 :             : 
    1762                 :             :   // val_ptr_temp, present_temp = mapaccess2(DESCRIPTOR, MAP, &key_temp)
    1763                 :        2365 :   Expression* a1 = Expression::make_type_descriptor(map_type, loc);
    1764                 :        2365 :   Expression* a2 = map_index->map();
    1765                 :        2365 :   Temporary_reference_expression* ref =
    1766                 :        2365 :     Expression::make_temporary_reference(key_temp, loc);
    1767                 :        2365 :   Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc);
    1768                 :        2365 :   Expression* a4 = map_type->fat_zero_value(gogo);
    1769                 :        2365 :   Call_expression* call;
    1770                 :        2365 :   if (a4 == NULL)
    1771                 :             :     {
    1772                 :        2362 :       Runtime::Function code;
    1773                 :        2362 :       Map_type::Map_alg alg = map_type->algorithm(gogo);
    1774                 :        2362 :       switch (alg)
    1775                 :             :         {
    1776                 :         261 :           case Map_type::MAP_ALG_FAST32:
    1777                 :         261 :           case Map_type::MAP_ALG_FAST32PTR:
    1778                 :         261 :             {
    1779                 :         261 :               code = Runtime::MAPACCESS2_FAST32;
    1780                 :         261 :               Type* uint32_type = Type::lookup_integer_type("uint32");
    1781                 :         261 :               Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
    1782                 :         261 :               a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3,
    1783                 :             :                                                 loc);
    1784                 :         261 :               a3 = Expression::make_dereference(a3,
    1785                 :             :                                                 Expression::NIL_CHECK_NOT_NEEDED,
    1786                 :             :                                                 loc);
    1787                 :         261 :               break;
    1788                 :             :             }
    1789                 :         299 :           case Map_type::MAP_ALG_FAST64:
    1790                 :         299 :           case Map_type::MAP_ALG_FAST64PTR:
    1791                 :         299 :             {
    1792                 :         299 :               code = Runtime::MAPACCESS2_FAST64;
    1793                 :         299 :               Type* uint64_type = Type::lookup_integer_type("uint64");
    1794                 :         299 :               Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
    1795                 :         299 :               a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3,
    1796                 :             :                                                 loc);
    1797                 :         299 :               a3 = Expression::make_dereference(a3,
    1798                 :             :                                                 Expression::NIL_CHECK_NOT_NEEDED,
    1799                 :             :                                                 loc);
    1800                 :         299 :               break;
    1801                 :             :             }
    1802                 :             :           case Map_type::MAP_ALG_FASTSTR:
    1803                 :             :             code = Runtime::MAPACCESS2_FASTSTR;
    1804                 :             :             a3 = ref;
    1805                 :             :             break;
    1806                 :         523 :           default:
    1807                 :         523 :             code = Runtime::MAPACCESS2;
    1808                 :         523 :             break;
    1809                 :             :         }
    1810                 :        2362 :       call = Runtime::make_call(gogo, code, loc, 3, a1, a2, a3);
    1811                 :             :     }
    1812                 :             :   else
    1813                 :           3 :     call = Runtime::make_call(gogo, Runtime::MAPACCESS2_FAT, loc, 4,
    1814                 :             :                               a1, a2, a3, a4);
    1815                 :        2365 :   ref = Expression::make_temporary_reference(val_ptr_temp, loc);
    1816                 :        2365 :   ref->set_is_lvalue();
    1817                 :        2365 :   Expression* res = Expression::make_call_result(call, 0);
    1818                 :        2365 :   res = Expression::make_unsafe_cast(val_ptr_type, res, loc);
    1819                 :        2365 :   Statement* s = Statement::make_assignment(ref, res, loc);
    1820                 :        2365 :   s->determine_types(gogo);
    1821                 :        2365 :   b->add_statement(s);
    1822                 :        2365 :   ref = Expression::make_temporary_reference(present_temp, loc);
    1823                 :        2365 :   ref->set_is_lvalue();
    1824                 :        2365 :   res = Expression::make_call_result(call, 1);
    1825                 :        2365 :   s = Statement::make_assignment(ref, res, loc);
    1826                 :        2365 :   s->determine_types(gogo);
    1827                 :        2365 :   b->add_statement(s);
    1828                 :             : 
    1829                 :             :   // val = *val__ptr_temp
    1830                 :        2365 :   ref = Expression::make_temporary_reference(val_ptr_temp, loc);
    1831                 :        2365 :   Expression* ind =
    1832                 :        2365 :       Expression::make_dereference(ref, Expression::NIL_CHECK_NOT_NEEDED, loc);
    1833                 :        2365 :   s = Statement::make_assignment(this->val_, ind, loc);
    1834                 :        2365 :   s->determine_types(gogo);
    1835                 :        2365 :   b->add_statement(s);
    1836                 :             : 
    1837                 :             :   // present = present_temp
    1838                 :        2365 :   ref = Expression::make_temporary_reference(present_temp, loc);
    1839                 :        2365 :   s = Statement::make_assignment(this->present_, ref, loc);
    1840                 :        2365 :   s->determine_types(gogo);
    1841                 :        2365 :   b->add_statement(s);
    1842                 :             : 
    1843                 :        2365 :   return Statement::make_block_statement(b, loc);
    1844                 :        2365 : }
    1845                 :             : 
    1846                 :             : // Dump the AST representation for a tuple map assignment statement.
    1847                 :             : 
    1848                 :             : void
    1849                 :           0 : Tuple_map_assignment_statement::do_dump_statement(
    1850                 :             :     Ast_dump_context* ast_dump_context) const
    1851                 :             : {
    1852                 :           0 :   ast_dump_context->print_indent();
    1853                 :           0 :   ast_dump_context->dump_expression(this->val_);
    1854                 :           0 :   ast_dump_context->ostream() << ", ";
    1855                 :           0 :   ast_dump_context->dump_expression(this->present_);
    1856                 :           0 :   ast_dump_context->ostream() << " = ";
    1857                 :           0 :   ast_dump_context->dump_expression(this->map_index_);
    1858                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    1859                 :           0 : }
    1860                 :             : 
    1861                 :             : // Make a map assignment statement which returns a pair of values.
    1862                 :             : 
    1863                 :             : Statement*
    1864                 :        2365 : Statement::make_tuple_map_assignment(Expression* val, Expression* present,
    1865                 :             :                                      Expression* map_index,
    1866                 :             :                                      Location location)
    1867                 :             : {
    1868                 :        2365 :   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                 :         186 :   Tuple_receive_assignment_statement(Expression* val, Expression* closed,
    1877                 :             :                                      Expression* channel, Location location)
    1878                 :         186 :     : Statement(STATEMENT_TUPLE_RECEIVE_ASSIGNMENT, location),
    1879                 :         372 :       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                 :           0 :   do_get_backend(Translate_context*)
    1897                 :           0 :   { 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                 :         505 : Tuple_receive_assignment_statement::do_traverse(Traverse* traverse)
    1915                 :             : {
    1916                 :         505 :   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
    1917                 :         505 :       || this->traverse_expression(traverse, &this->closed_) == TRAVERSE_EXIT)
    1918                 :           0 :     return TRAVERSE_EXIT;
    1919                 :         505 :   return this->traverse_expression(traverse, &this->channel_);
    1920                 :             : }
    1921                 :             : 
    1922                 :             : void
    1923                 :         287 : Tuple_receive_assignment_statement::do_determine_types(Gogo* gogo)
    1924                 :             : {
    1925                 :         287 :   this->val_->determine_type_no_context(gogo);
    1926                 :         287 :   this->closed_->determine_type_no_context(gogo);
    1927                 :         287 :   this->channel_->determine_type_no_context(gogo);
    1928                 :         287 : }
    1929                 :             : 
    1930                 :             : void
    1931                 :          80 : Tuple_receive_assignment_statement::do_check_types(Gogo*)
    1932                 :             : {
    1933                 :          80 :   Channel_type* ct = this->channel_->type()->channel_type();
    1934                 :          80 :   if (ct == NULL)
    1935                 :             :     {
    1936                 :           0 :       this->report_error(_("expected channel"));
    1937                 :           0 :       return;
    1938                 :             :     }
    1939                 :          80 :   if (!ct->may_receive())
    1940                 :             :     {
    1941                 :           1 :       this->report_error(_("invalid receive on send-only channel"));
    1942                 :           1 :       return;
    1943                 :             :     }
    1944                 :             : 
    1945                 :          79 :   if (!Assignment_statement::check_assignment_types(this->val_,
    1946                 :             :                                                     ct->element_type(),
    1947                 :             :                                                     this->location()))
    1948                 :           0 :     this->set_is_error();
    1949                 :          79 :   if (!Assignment_statement::check_assignment_types(this->closed_,
    1950                 :             :                                                     Type::make_boolean_type(),
    1951                 :             :                                                     this->location()))
    1952                 :           0 :     this->set_is_error();
    1953                 :             : }
    1954                 :             : 
    1955                 :             : // Lower to a function call.
    1956                 :             : 
    1957                 :             : Statement*
    1958                 :         185 : Tuple_receive_assignment_statement::do_lower(Gogo* gogo, Named_object*,
    1959                 :             :                                              Block* enclosing,
    1960                 :             :                                              Statement_inserter*)
    1961                 :             : {
    1962                 :         185 :   Location loc = this->location();
    1963                 :             : 
    1964                 :         185 :   if (this->classification() == STATEMENT_ERROR)
    1965                 :           0 :     return Statement::make_error_statement(loc);
    1966                 :             : 
    1967                 :         185 :   Channel_type* channel_type = this->channel_->type()->channel_type();
    1968                 :         185 :   go_assert(channel_type != NULL && channel_type->may_receive());
    1969                 :             : 
    1970                 :         185 :   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                 :         185 :   Move_ordered_evals moe(b);
    1975                 :         185 :   this->val_->traverse_subexpressions(&moe);
    1976                 :         185 :   this->closed_->traverse_subexpressions(&moe);
    1977                 :             : 
    1978                 :             :   // var val_temp ELEMENT_TYPE
    1979                 :         185 :   Temporary_statement* val_temp =
    1980                 :         185 :     Statement::make_temporary(channel_type->element_type(), NULL, loc);
    1981                 :         185 :   b->add_statement(val_temp);
    1982                 :             : 
    1983                 :             :   // var closed_temp bool
    1984                 :         185 :   Temporary_statement* closed_temp =
    1985                 :         370 :     Statement::make_temporary((this->closed_->type()->is_boolean_type()
    1986                 :         182 :                                ? this->closed_->type()
    1987                 :           3 :                                : Type::lookup_bool_type()),
    1988                 :             :                               NULL, loc);
    1989                 :         185 :   b->add_statement(closed_temp);
    1990                 :             : 
    1991                 :             :   // closed_temp = chanrecv2(channel, &val_temp)
    1992                 :         185 :   Temporary_reference_expression* ref =
    1993                 :         185 :     Expression::make_temporary_reference(val_temp, loc);
    1994                 :         185 :   Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
    1995                 :         185 :   Expression* call = Runtime::make_call(gogo, Runtime::CHANRECV2,
    1996                 :             :                                         loc, 2, this->channel_, p2);
    1997                 :         185 :   ref = Expression::make_temporary_reference(closed_temp, loc);
    1998                 :         185 :   ref->set_is_lvalue();
    1999                 :         185 :   Statement* s = Statement::make_assignment(ref, call, loc);
    2000                 :         185 :   s->determine_types(gogo);
    2001                 :         185 :   b->add_statement(s);
    2002                 :             : 
    2003                 :             :   // val = val_temp
    2004                 :         185 :   ref = Expression::make_temporary_reference(val_temp, loc);
    2005                 :         185 :   s = Statement::make_assignment(this->val_, ref, loc);
    2006                 :         185 :   s->determine_types(gogo);
    2007                 :         185 :   b->add_statement(s);
    2008                 :             : 
    2009                 :             :   // closed = closed_temp
    2010                 :         185 :   ref = Expression::make_temporary_reference(closed_temp, loc);
    2011                 :         185 :   s = Statement::make_assignment(this->closed_, ref, loc);
    2012                 :         185 :   s->determine_types(gogo);
    2013                 :         185 :   b->add_statement(s);
    2014                 :             : 
    2015                 :         185 :   return Statement::make_block_statement(b, loc);
    2016                 :         185 : }
    2017                 :             : 
    2018                 :             : // Dump the AST representation for a tuple receive statement.
    2019                 :             : 
    2020                 :             : void
    2021                 :           0 : Tuple_receive_assignment_statement::do_dump_statement(
    2022                 :             :     Ast_dump_context* ast_dump_context) const
    2023                 :             : {
    2024                 :           0 :   ast_dump_context->print_indent();
    2025                 :           0 :   ast_dump_context->dump_expression(this->val_);
    2026                 :           0 :   ast_dump_context->ostream() << ", ";
    2027                 :           0 :   ast_dump_context->dump_expression(this->closed_);
    2028                 :           0 :   ast_dump_context->ostream() << " <- ";
    2029                 :           0 :   ast_dump_context->dump_expression(this->channel_);
    2030                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    2031                 :           0 : }
    2032                 :             : 
    2033                 :             : // Make a nonblocking receive statement.
    2034                 :             : 
    2035                 :             : Statement*
    2036                 :         186 : Statement::make_tuple_receive_assignment(Expression* val, Expression* closed,
    2037                 :             :                                          Expression* channel,
    2038                 :             :                                          Location location)
    2039                 :             : {
    2040                 :         186 :   return new Tuple_receive_assignment_statement(val, closed, channel,
    2041                 :         186 :                                                 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                 :        6693 :   Tuple_type_guard_assignment_statement(Expression* val, Expression* ok,
    2051                 :             :                                         Expression* expr, Type* type,
    2052                 :             :                                         Location location)
    2053                 :        6693 :     : Statement(STATEMENT_TUPLE_TYPE_GUARD_ASSIGNMENT, location),
    2054                 :       13386 :       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                 :           0 :   do_get_backend(Translate_context*)
    2072                 :           0 :   { 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                 :       33464 : Tuple_type_guard_assignment_statement::do_traverse(Traverse* traverse)
    2098                 :             : {
    2099                 :       33464 :   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
    2100                 :       33464 :       || this->traverse_expression(traverse, &this->ok_) == TRAVERSE_EXIT
    2101                 :       66928 :       || this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
    2102                 :           0 :     return TRAVERSE_EXIT;
    2103                 :       33464 :   return this->traverse_expression(traverse, &this->expr_);
    2104                 :             : }
    2105                 :             : 
    2106                 :             : void
    2107                 :        6693 : Tuple_type_guard_assignment_statement::do_determine_types(Gogo* gogo)
    2108                 :             : {
    2109                 :        6693 :   this->val_->determine_type_no_context(gogo);
    2110                 :        6693 :   this->ok_->determine_type_no_context(gogo);
    2111                 :        6693 :   this->expr_->determine_type_no_context(gogo);
    2112                 :        6693 : }
    2113                 :             : 
    2114                 :             : void
    2115                 :        6693 : Tuple_type_guard_assignment_statement::do_check_types(Gogo*)
    2116                 :             : {
    2117                 :        6693 :   Type* expr_type = this->expr_->type();
    2118                 :        6693 :   if (expr_type->interface_type() == NULL)
    2119                 :             :     {
    2120                 :           0 :       if (!expr_type->is_error() && !this->type_->is_error())
    2121                 :           0 :         this->report_error(_("type assertion only valid for interface types"));
    2122                 :           0 :       return;
    2123                 :             :     }
    2124                 :             : 
    2125                 :        6693 :   if (!Assignment_statement::check_assignment_types(this->val_, this->type_,
    2126                 :             :                                                     this->location()))
    2127                 :           1 :     this->set_is_error();
    2128                 :        6693 :   if (!Assignment_statement::check_assignment_types(this->ok_,
    2129                 :             :                                                     Type::make_boolean_type(),
    2130                 :             :                                                     this->location()))
    2131                 :           0 :     this->set_is_error();
    2132                 :             : }
    2133                 :             : 
    2134                 :             : // Lower to a function call.
    2135                 :             : 
    2136                 :             : Statement*
    2137                 :        6692 : Tuple_type_guard_assignment_statement::do_lower(Gogo* gogo, Named_object*,
    2138                 :             :                                                 Block* enclosing,
    2139                 :             :                                                 Statement_inserter*)
    2140                 :             : {
    2141                 :        6692 :   Location loc = this->location();
    2142                 :             : 
    2143                 :        6692 :   if (this->classification() == STATEMENT_ERROR)
    2144                 :           0 :     return Statement::make_error_statement(loc);
    2145                 :             : 
    2146                 :        6692 :   Type* expr_type = this->expr_->type();
    2147                 :        6692 :   go_assert(expr_type->interface_type() != NULL);
    2148                 :             : 
    2149                 :        6692 :   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                 :        6692 :   Move_ordered_evals moe(b);
    2154                 :        6692 :   this->val_->traverse_subexpressions(&moe);
    2155                 :        6692 :   this->ok_->traverse_subexpressions(&moe);
    2156                 :             : 
    2157                 :       13384 :   bool expr_is_empty = expr_type->interface_type()->is_empty();
    2158                 :        6692 :   Call_expression* call;
    2159                 :        6692 :   if (this->type_->interface_type() != NULL)
    2160                 :             :     {
    2161                 :        2684 :       if (this->type_->interface_type()->is_empty())
    2162                 :          20 :         call = Runtime::make_call(gogo,
    2163                 :             :                                   (expr_is_empty
    2164                 :             :                                    ? Runtime::IFACEE2E2
    2165                 :             :                                    : Runtime::IFACEI2E2),
    2166                 :             :                                   loc, 1, this->expr_);
    2167                 :             :       else
    2168                 :        2362 :         call = this->lower_to_type(gogo,
    2169                 :             :                                    (expr_is_empty
    2170                 :             :                                     ? Runtime::IFACEE2I2
    2171                 :             :                                     : Runtime::IFACEI2I2));
    2172                 :             :     }
    2173                 :        5350 :   else if (this->type_->points_to() != NULL)
    2174                 :        7610 :     call = this->lower_to_type(gogo,
    2175                 :             :                                (expr_is_empty
    2176                 :             :                                 ? Runtime::IFACEE2T2P
    2177                 :             :                                 : Runtime::IFACEI2T2P));
    2178                 :             :   else
    2179                 :             :     {
    2180                 :        1300 :       this->lower_to_object_type(gogo, b,
    2181                 :             :                                  (expr_is_empty
    2182                 :             :                                   ? Runtime::IFACEE2T2
    2183                 :             :                                   : Runtime::IFACEI2T2));
    2184                 :        1300 :       call = NULL;
    2185                 :             :     }
    2186                 :             : 
    2187                 :        6692 :   if (call != NULL)
    2188                 :             :     {
    2189                 :        5392 :       Expression* res = Expression::make_call_result(call, 0);
    2190                 :        5392 :       res = Expression::make_unsafe_cast(this->type_, res, loc);
    2191                 :        5392 :       Statement* s = Statement::make_assignment(this->val_, res, loc);
    2192                 :        5392 :       s->determine_types(gogo);
    2193                 :        5392 :       b->add_statement(s);
    2194                 :             : 
    2195                 :        5392 :       res = Expression::make_call_result(call, 1);
    2196                 :        5392 :       if (!this->ok_->type()->is_boolean_type())
    2197                 :        1209 :         res = Expression::make_cast(Type::lookup_bool_type(), res, loc);
    2198                 :        5392 :       s = Statement::make_assignment(this->ok_, res, loc);
    2199                 :        5392 :       s->determine_types(gogo);
    2200                 :        5392 :       b->add_statement(s);
    2201                 :             :     }
    2202                 :             : 
    2203                 :        6692 :   return Statement::make_block_statement(b, loc);
    2204                 :        6692 : }
    2205                 :             : 
    2206                 :             : // Lower a conversion to a non-empty interface type or a pointer type.
    2207                 :             : 
    2208                 :             : Call_expression*
    2209                 :        5378 : Tuple_type_guard_assignment_statement::lower_to_type(Gogo* gogo,
    2210                 :             :                                                      Runtime::Function code)
    2211                 :             : {
    2212                 :        5378 :   Location loc = this->location();
    2213                 :        5378 :   return Runtime::make_call(gogo, code, loc, 2,
    2214                 :             :                             Expression::make_type_descriptor(this->type_, loc),
    2215                 :        5378 :                             this->expr_);
    2216                 :             : }
    2217                 :             : 
    2218                 :             : // Lower a conversion to a non-interface non-pointer type.
    2219                 :             : 
    2220                 :             : void
    2221                 :        1300 : Tuple_type_guard_assignment_statement::lower_to_object_type(
    2222                 :             :     Gogo* gogo,
    2223                 :             :     Block* b,
    2224                 :             :     Runtime::Function code)
    2225                 :             : {
    2226                 :        1300 :   Location loc = this->location();
    2227                 :             : 
    2228                 :             :   // var val_temp TYPE
    2229                 :        1300 :   Temporary_statement* val_temp = Statement::make_temporary(this->type_,
    2230                 :             :                                                             NULL, loc);
    2231                 :        1300 :   b->add_statement(val_temp);
    2232                 :             : 
    2233                 :             :   // var ok_temp bool
    2234                 :        1300 :   Temporary_statement* ok_temp = NULL;
    2235                 :        1300 :   if (!this->ok_->is_sink_expression())
    2236                 :             :     {
    2237                 :        1924 :       ok_temp = Statement::make_temporary((this->ok_->type()->is_boolean_type()
    2238                 :         962 :                                            ? this->ok_->type()
    2239                 :           0 :                                            : Type::lookup_bool_type()),
    2240                 :             :                                           NULL, loc);
    2241                 :         962 :       b->add_statement(ok_temp);
    2242                 :             :     }
    2243                 :             : 
    2244                 :             :   // ok_temp = CODE(type_descriptor, expr, &val_temp)
    2245                 :        1300 :   Expression* p1 = Expression::make_type_descriptor(this->type_, loc);
    2246                 :        1300 :   Expression* ref = Expression::make_temporary_reference(val_temp, loc);
    2247                 :        1300 :   Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
    2248                 :        1300 :   Expression* call = Runtime::make_call(gogo, code, loc, 3,
    2249                 :             :                                         p1, this->expr_, p3);
    2250                 :        1300 :   Statement* s;
    2251                 :        1300 :   if (ok_temp == NULL)
    2252                 :         338 :     s = Statement::make_statement(call, true);
    2253                 :             :   else
    2254                 :             :     {
    2255                 :         962 :       Expression* ok_ref = Expression::make_temporary_reference(ok_temp, loc);
    2256                 :         962 :       s = Statement::make_assignment(ok_ref, call, loc);
    2257                 :             :     }
    2258                 :        1300 :   s->determine_types(gogo);
    2259                 :        1300 :   b->add_statement(s);
    2260                 :             : 
    2261                 :             :   // val = val_temp
    2262                 :        1300 :   ref = Expression::make_temporary_reference(val_temp, loc);
    2263                 :        1300 :   s = Statement::make_assignment(this->val_, ref, loc);
    2264                 :        1300 :   s->determine_types(gogo);
    2265                 :        1300 :   b->add_statement(s);
    2266                 :             : 
    2267                 :             :   // ok = ok_temp
    2268                 :        1300 :   if (ok_temp != NULL)
    2269                 :             :     {
    2270                 :         962 :       ref = Expression::make_temporary_reference(ok_temp, loc);
    2271                 :         962 :       s = Statement::make_assignment(this->ok_, ref, loc);
    2272                 :         962 :       s->determine_types(gogo);
    2273                 :         962 :       b->add_statement(s);
    2274                 :             :     }
    2275                 :        1300 : }
    2276                 :             : 
    2277                 :             : // Dump the AST representation for a tuple type guard statement.
    2278                 :             : 
    2279                 :             : void
    2280                 :           0 : Tuple_type_guard_assignment_statement::do_dump_statement(
    2281                 :             :     Ast_dump_context* ast_dump_context) const
    2282                 :             : {
    2283                 :           0 :   ast_dump_context->print_indent();
    2284                 :           0 :   ast_dump_context->dump_expression(this->val_);
    2285                 :           0 :   ast_dump_context->ostream() << ", ";
    2286                 :           0 :   ast_dump_context->dump_expression(this->ok_);
    2287                 :           0 :   ast_dump_context->ostream() << " = ";
    2288                 :           0 :   ast_dump_context->dump_expression(this->expr_);
    2289                 :           0 :   ast_dump_context->ostream() << " . ";
    2290                 :           0 :   ast_dump_context->dump_type(this->type_);
    2291                 :           0 :   ast_dump_context->ostream()  << dsuffix(location()) << std::endl;
    2292                 :           0 : }
    2293                 :             : 
    2294                 :             : // Make an assignment from a type guard to a pair of variables.
    2295                 :             : 
    2296                 :             : Statement*
    2297                 :        6693 : Statement::make_tuple_type_guard_assignment(Expression* val, Expression* ok,
    2298                 :             :                                             Expression* expr, Type* type,
    2299                 :             :                                             Location location)
    2300                 :             : {
    2301                 :        6693 :   return new Tuple_type_guard_assignment_statement(val, ok, expr, type,
    2302                 :        6693 :                                                    location);
    2303                 :             : }
    2304                 :             : 
    2305                 :             : // Class Expression_statement.
    2306                 :             : 
    2307                 :             : // Constructor.
    2308                 :             : 
    2309                 :      829786 : Expression_statement::Expression_statement(Expression* expr, bool is_ignored)
    2310                 :             :   : Statement(STATEMENT_EXPRESSION, expr->location()),
    2311                 :      829786 :     expr_(expr), is_ignored_(is_ignored)
    2312                 :             : {
    2313                 :      829786 : }
    2314                 :             : 
    2315                 :             : // Determine types.
    2316                 :             : 
    2317                 :             : void
    2318                 :      765204 : Expression_statement::do_determine_types(Gogo* gogo)
    2319                 :             : {
    2320                 :      765204 :   this->expr_->determine_type_no_context(gogo);
    2321                 :      765204 : }
    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                 :      259468 : Expression_statement::do_check_types(Gogo*)
    2329                 :             : {
    2330                 :      259468 :   if (!this->is_ignored_)
    2331                 :      251818 :     this->expr_->discarding_value();
    2332                 :      259468 : }
    2333                 :             : 
    2334                 :             : // An expression statement is only a terminating statement if it is
    2335                 :             : // a call to panic.
    2336                 :             : 
    2337                 :             : bool
    2338                 :        1239 : Expression_statement::do_may_fall_through() const
    2339                 :             : {
    2340                 :             :   // The builtin function panic does not return.
    2341                 :        1308 :   const Call_expression* call = this->expr_->call_expression();
    2342                 :        1239 :   if (call == NULL)
    2343                 :             :     return true;
    2344                 :        1239 :   const Builtin_call_expression* bce = call->builtin_call_expression();
    2345                 :        1228 :   return bce == NULL || bce->code() != Builtin_call_expression::BUILTIN_PANIC;
    2346                 :             : }
    2347                 :             : 
    2348                 :             : // Export an expression statement.
    2349                 :             : 
    2350                 :             : void
    2351                 :        4909 : Expression_statement::do_export_statement(Export_function_body* efb)
    2352                 :             : {
    2353                 :        4909 :   this->expr_->export_expression(efb);
    2354                 :        4909 : }
    2355                 :             : 
    2356                 :             : // Convert to backend representation.
    2357                 :             : 
    2358                 :             : Bstatement*
    2359                 :      823922 : Expression_statement::do_get_backend(Translate_context* context)
    2360                 :             : {
    2361                 :      823922 :   Bexpression* bexpr = this->expr_->get_backend(context);
    2362                 :      823922 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    2363                 :      823922 :   return context->backend()->expression_statement(bfunction, bexpr);
    2364                 :             : }
    2365                 :             : 
    2366                 :             : // Dump the AST representation for an expression statement
    2367                 :             : 
    2368                 :             : void
    2369                 :           0 : Expression_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    2370                 :             :     const
    2371                 :             : {
    2372                 :           0 :   ast_dump_context->print_indent();
    2373                 :           0 :   ast_dump_context->dump_expression(expr_);
    2374                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    2375                 :           0 : }
    2376                 :             : 
    2377                 :             : // Make an expression statement from an Expression.
    2378                 :             : 
    2379                 :             : Statement*
    2380                 :      829786 : Statement::make_statement(Expression* expr, bool is_ignored)
    2381                 :             : {
    2382                 :      829786 :   return new Expression_statement(expr, is_ignored);
    2383                 :             : }
    2384                 :             : 
    2385                 :             : // Export data for a block.
    2386                 :             : 
    2387                 :             : void
    2388                 :       22817 : Block_statement::do_export_statement(Export_function_body* efb)
    2389                 :             : {
    2390                 :       22817 :   Block_statement::export_block(efb, this->block_,
    2391                 :       22817 :                                 this->is_lowered_for_statement_);
    2392                 :       22817 : }
    2393                 :             : 
    2394                 :             : void
    2395                 :       27416 : 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                 :       27416 :   char buf[50];
    2400                 :       27416 :   efb->write_c_string("{");
    2401                 :       27416 :   if (is_lowered_for_statement)
    2402                 :         445 :     efb->write_c_string(" /*for*/");
    2403                 :       27416 :   snprintf(buf, sizeof buf, " //%d\n",
    2404                 :             :            Linemap::location_to_line(block->start_location()));
    2405                 :       27416 :   efb->write_c_string(buf);
    2406                 :             : 
    2407                 :       27416 :   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                 :       27416 :   efb->decrement_indent();
    2411                 :       27416 :   efb->indent();
    2412                 :       27416 :   efb->write_c_string("}");
    2413                 :             :   // Increment back to the value the caller thinks it has.
    2414                 :       27416 :   efb->increment_indent();
    2415                 :       27416 : }
    2416                 :             : 
    2417                 :             : // Import a block statement, returning the block.
    2418                 :             : 
    2419                 :             : Block*
    2420                 :       26622 : Block_statement::do_import(Import_function_body* ifb, Location loc,
    2421                 :             :                            bool* is_lowered_for_statement)
    2422                 :             : {
    2423                 :       26622 :   go_assert(ifb->match_c_string("{"));
    2424                 :       26622 :   *is_lowered_for_statement = false;
    2425                 :       26622 :   if (ifb->match_c_string(" /*for*/"))
    2426                 :             :     {
    2427                 :           0 :       ifb->advance(8);
    2428                 :           0 :       *is_lowered_for_statement = true;
    2429                 :             :     }
    2430                 :       26622 :   size_t nl = ifb->body().find('\n', ifb->off());
    2431                 :       26622 :   if (nl == std::string::npos)
    2432                 :             :     {
    2433                 :           0 :       if (!ifb->saw_error())
    2434                 :           0 :         go_error_at(ifb->location(),
    2435                 :             :                     "import error: no newline after %<{%> at %lu",
    2436                 :           0 :                     static_cast<unsigned long>(ifb->off()));
    2437                 :           0 :       ifb->set_saw_error();
    2438                 :           0 :       return NULL;
    2439                 :             :     }
    2440                 :       26622 :   ifb->set_off(nl + 1);
    2441                 :       26622 :   ifb->increment_indent();
    2442                 :       26622 :   Block* block = new Block(ifb->block(), loc);
    2443                 :       26622 :   ifb->begin_block(block);
    2444                 :       26622 :   bool ok = Block::import_block(block, ifb, loc);
    2445                 :       26622 :   ifb->finish_block();
    2446                 :       26622 :   ifb->decrement_indent();
    2447                 :       26622 :   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                 :     1359483 : Block_statement::do_get_backend(Translate_context* context)
    2456                 :             : {
    2457                 :     1359483 :   Bblock* bblock = this->block_->get_backend(context);
    2458                 :     1359483 :   return context->backend()->block_statement(bblock);
    2459                 :             : }
    2460                 :             : 
    2461                 :             : // Dump the AST for a block statement
    2462                 :             : 
    2463                 :             : void
    2464                 :           0 : Block_statement::do_dump_statement(Ast_dump_context*) const
    2465                 :             : {
    2466                 :             :   // block statement braces are dumped when traversing.
    2467                 :           0 : }
    2468                 :             : 
    2469                 :             : // Make a block statement.
    2470                 :             : 
    2471                 :             : Block_statement*
    2472                 :     1362668 : Statement::make_block_statement(Block* block, Location location)
    2473                 :             : {
    2474                 :     1362668 :   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                 :       58820 :   Inc_dec_statement(bool is_inc, Expression* expr)
    2483                 :       58820 :     : Statement(STATEMENT_INCDEC, expr->location()),
    2484                 :      117640 :       expr_(expr), is_inc_(is_inc)
    2485                 :             :   { }
    2486                 :             : 
    2487                 :             :  protected:
    2488                 :             :   int
    2489                 :      168631 :   do_traverse(Traverse* traverse)
    2490                 :      168631 :   { 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                 :           0 :   do_get_backend(Translate_context*)
    2503                 :           0 :   { 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                 :       90187 : Inc_dec_statement::do_determine_types(Gogo* gogo)
    2517                 :             : {
    2518                 :       90187 :   this->expr_->determine_type_no_context(gogo);
    2519                 :       90187 : }
    2520                 :             : 
    2521                 :             : void
    2522                 :       27453 : Inc_dec_statement::do_check_types(Gogo*)
    2523                 :             : {
    2524                 :       27453 :   if (!this->expr_->is_addressable()
    2525                 :       27453 :       && !Index_expression::is_map_index(this->expr_))
    2526                 :             :     {
    2527                 :           0 :       if (!this->expr_->type()->is_error())
    2528                 :           0 :         this->report_error(_("invalid left hand side of assignment"));
    2529                 :           0 :       this->set_is_error();
    2530                 :           0 :       return;
    2531                 :             :     }
    2532                 :       27453 :   if (!this->expr_->type()->is_numeric_type())
    2533                 :             :     {
    2534                 :           1 :       this->report_error(_("increment or decrement of non-numeric type"));
    2535                 :           1 :       return;
    2536                 :             :     }
    2537                 :             : }
    2538                 :             : 
    2539                 :             : // Lower to += or -=.
    2540                 :             : 
    2541                 :             : Statement*
    2542                 :       58819 : Inc_dec_statement::do_lower(Gogo*, Named_object*, Block*, Statement_inserter*)
    2543                 :             : {
    2544                 :       58819 :   Location loc = this->location();
    2545                 :       58819 :   Expression* oexpr = Expression::make_integer_ul(1, this->expr_->type(), loc);
    2546                 :       58819 :   Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ;
    2547                 :       58819 :   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                 :           0 : Inc_dec_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    2554                 :             : {
    2555                 :           0 :   ast_dump_context->print_indent();
    2556                 :           0 :   ast_dump_context->dump_expression(expr_);
    2557                 :           0 :   ast_dump_context->ostream() << (is_inc_? "++": "--") << dsuffix(location()) << std::endl;
    2558                 :           0 : }
    2559                 :             : 
    2560                 :             : // Make an increment statement.
    2561                 :             : 
    2562                 :             : Statement*
    2563                 :       54549 : Statement::make_inc_statement(Expression* expr)
    2564                 :             : {
    2565                 :       54549 :   return new Inc_dec_statement(true, expr);
    2566                 :             : }
    2567                 :             : 
    2568                 :             : // Make a decrement statement.
    2569                 :             : 
    2570                 :             : Statement*
    2571                 :        4271 : Statement::make_dec_statement(Expression* expr)
    2572                 :             : {
    2573                 :        4271 :   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                 :       27523 : Thunk_statement::Thunk_statement(Statement_classification classification,
    2582                 :             :                                  Call_expression* call,
    2583                 :       27523 :                                  Location location)
    2584                 :             :     : Statement(classification, location),
    2585                 :       27523 :       call_(call)
    2586                 :             : {
    2587                 :       27523 : }
    2588                 :             : 
    2589                 :             : // Return whether this is a simple statement which does not require a
    2590                 :             : // thunk.
    2591                 :             : 
    2592                 :             : bool
    2593                 :       13743 : 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                 :       13743 :   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                 :       13432 :   if (this->classification() == STATEMENT_DEFER)
    2603                 :             :     return false;
    2604                 :             : 
    2605                 :             :   // We can only permit a single parameter of pointer type.
    2606                 :        2501 :   const Typed_identifier_list* parameters = fntype->parameters();
    2607                 :        2501 :   if (parameters != NULL
    2608                 :        2501 :       && (parameters->size() > 1
    2609                 :         403 :           || (parameters->size() == 1
    2610                 :         403 :               && parameters->begin()->type()->points_to() == NULL)))
    2611                 :         771 :     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                 :        1730 :   const Typed_identifier_list* results = fntype->results();
    2619                 :        1730 :   if (results != NULL
    2620                 :        1730 :       && (results->size() > 1
    2621                 :          25 :           || (results->size() == 1
    2622                 :          25 :               && !results->begin()->type()->is_basic_type()
    2623                 :          24 :               && results->begin()->type()->points_to() == NULL)))
    2624                 :          24 :     return false;
    2625                 :             : 
    2626                 :             :   // If this calls something that is not a simple function, then we
    2627                 :             :   // need a thunk.
    2628                 :        1706 :   Expression* fn = this->call_->call_expression()->fn();
    2629                 :       15200 :   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                 :        1559 :   if (fn->func_expression()->closure() != NULL)
    2635                 :             :     return false;
    2636                 :             : 
    2637                 :             :   return true;
    2638                 :             : }
    2639                 :             : 
    2640                 :             : // Traverse a thunk statement.
    2641                 :             : 
    2642                 :             : int
    2643                 :      328818 : Thunk_statement::do_traverse(Traverse* traverse)
    2644                 :             : {
    2645                 :      328818 :   return this->traverse_expression(traverse, &this->call_);
    2646                 :             : }
    2647                 :             : 
    2648                 :             : // Determine types in a thunk statement.
    2649                 :             : 
    2650                 :             : void
    2651                 :       27901 : Thunk_statement::do_determine_types(Gogo* gogo)
    2652                 :             : {
    2653                 :       27901 :   this->call_->determine_type_no_context(gogo);
    2654                 :       27901 : }
    2655                 :             : 
    2656                 :             : // Check types in a thunk statement.
    2657                 :             : 
    2658                 :             : void
    2659                 :       27523 : Thunk_statement::do_check_types(Gogo*)
    2660                 :             : {
    2661                 :       27523 :   if (!this->call_->discarding_value())
    2662                 :             :     {
    2663                 :          42 :       this->set_is_error();
    2664                 :          42 :       return;
    2665                 :             :     }
    2666                 :       27481 :   Call_expression* ce = this->call_->call_expression();
    2667                 :           2 :   if (ce == NULL)
    2668                 :             :     {
    2669                 :           2 :       if (!this->call_->is_error_expression())
    2670                 :           0 :         this->report_error("expected call expression");
    2671                 :           2 :       this->set_is_error();
    2672                 :           2 :       return;
    2673                 :             :     }
    2674                 :             : }
    2675                 :             : 
    2676                 :             : // The Traverse class used to find and simplify thunk statements.
    2677                 :             : 
    2678                 :        9288 : class Simplify_thunk_traverse : public Traverse
    2679                 :             : {
    2680                 :             :  public:
    2681                 :        4644 :   Simplify_thunk_traverse(Gogo* gogo)
    2682                 :        4644 :     : Traverse(traverse_functions | traverse_blocks),
    2683                 :        4644 :       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                 :      203079 : Simplify_thunk_traverse::function(Named_object* no)
    2703                 :             : {
    2704                 :      203079 :   go_assert(this->function_ == NULL);
    2705                 :      203079 :   this->function_ = no;
    2706                 :      203079 :   int t = no->func_value()->traverse(this);
    2707                 :      203079 :   this->function_ = NULL;
    2708                 :      203079 :   if (t == TRAVERSE_EXIT)
    2709                 :           0 :     return t;
    2710                 :             :   return TRAVERSE_SKIP_COMPONENTS;
    2711                 :             : }
    2712                 :             : 
    2713                 :             : // Look for thunks in a block.
    2714                 :             : 
    2715                 :             : int
    2716                 :     1722692 : Simplify_thunk_traverse::block(Block* b)
    2717                 :             : {
    2718                 :             :   // The parser ensures that thunk statements always appear at the end
    2719                 :             :   // of a block.
    2720                 :     1722692 :   if (b->statements()->size() < 1)
    2721                 :             :     return TRAVERSE_CONTINUE;
    2722                 :     1718077 :   Thunk_statement* stat = b->statements()->back()->thunk_statement();
    2723                 :     1718077 :   if (stat == NULL)
    2724                 :             :     return TRAVERSE_CONTINUE;
    2725                 :       13743 :   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                 :        4644 : Gogo::simplify_thunk_statements()
    2734                 :             : {
    2735                 :        4644 :   Simplify_thunk_traverse thunk_traverse(this);
    2736                 :        4644 :   this->traverse(&thunk_traverse);
    2737                 :        4644 : }
    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                 :       40923 : Thunk_statement::is_constant_function() const
    2744                 :             : {
    2745                 :       40923 :   Call_expression* ce = this->call_->call_expression();
    2746                 :       40923 :   Function_type* fntype = ce->get_function_type();
    2747                 :       40923 :   if (fntype == NULL)
    2748                 :             :     {
    2749                 :           0 :       go_assert(saw_errors());
    2750                 :             :       return false;
    2751                 :             :     }
    2752                 :       40923 :   if (fntype->is_builtin())
    2753                 :             :     return true;
    2754                 :       39930 :   Expression* fn = ce->fn();
    2755                 :       39930 :   if (fn->func_expression() != NULL)
    2756                 :       18543 :     return fn->func_expression()->closure() == NULL;
    2757                 :       21387 :   if (fn->interface_field_reference_expression() != NULL)
    2758                 :             :     return true;
    2759                 :       18645 :   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                 :       13743 : Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
    2773                 :             :                                     Block* block)
    2774                 :             : {
    2775                 :       13743 :   if (this->classification() == STATEMENT_ERROR)
    2776                 :             :     return false;
    2777                 :       13743 :   if (this->call_->is_error_expression())
    2778                 :             :     return false;
    2779                 :             : 
    2780                 :       13743 :   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                 :       11230 :       function->func_value()->defer_stack(this->location());
    2787                 :             :     }
    2788                 :             : 
    2789                 :       13743 :   Call_expression* ce = this->call_->call_expression();
    2790                 :       13743 :   Function_type* fntype = ce->get_function_type();
    2791                 :       13743 :   if (fntype == NULL)
    2792                 :             :     {
    2793                 :           0 :       go_assert(saw_errors());
    2794                 :           0 :       this->set_is_error();
    2795                 :           0 :       return false;
    2796                 :             :     }
    2797                 :       13743 :   if (this->is_simple(fntype))
    2798                 :             :     return false;
    2799                 :             : 
    2800                 :       13641 :   Struct_type* struct_type = this->build_struct(fntype);
    2801                 :             : 
    2802                 :       13641 :   Expression* fn = ce->fn();
    2803                 :       13641 :   Interface_field_reference_expression* interface_method =
    2804                 :       13641 :     fn->interface_field_reference_expression();
    2805                 :       13641 :   Bound_method_expression* bme = fn->bound_method_expression();
    2806                 :             : 
    2807                 :       13641 :   Location location = this->location();
    2808                 :             : 
    2809                 :       13641 :   bool is_constant_function = this->is_constant_function();
    2810                 :       13641 :   Temporary_statement* fn_temp = NULL;
    2811                 :       13641 :   if (!is_constant_function)
    2812                 :             :     {
    2813                 :        3781 :       fn_temp = Statement::make_temporary(NULL, fn, location);
    2814                 :        3781 :       block->insert_statement_before(block->statements()->size() - 1, fn_temp);
    2815                 :        3781 :       fn = Expression::make_temporary_reference(fn_temp, location);
    2816                 :             :     }
    2817                 :             : 
    2818                 :       13641 :   std::string thunk_name = gogo->thunk_name();
    2819                 :             : 
    2820                 :             :   // Build the thunk.
    2821                 :       13641 :   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                 :       13641 :   Expression_list* vals = new Expression_list();
    2829                 :       13641 :   if (!is_constant_function)
    2830                 :        3781 :     vals->push_back(fn);
    2831                 :             : 
    2832                 :       13641 :   if (interface_method != NULL)
    2833                 :         914 :     vals->push_back(interface_method->expr());
    2834                 :       13641 :   if (bme != NULL)
    2835                 :        5513 :     vals->push_back(bme->first_argument());
    2836                 :             : 
    2837                 :       13641 :   if (ce->args() != NULL)
    2838                 :             :     {
    2839                 :        8610 :       for (Expression_list::const_iterator p = ce->args()->begin();
    2840                 :        8610 :            p != ce->args()->end();
    2841                 :        4990 :            ++p)
    2842                 :             :         {
    2843                 :        4990 :           if ((*p)->is_constant())
    2844                 :         499 :             continue;
    2845                 :        4491 :           vals->push_back(*p);
    2846                 :             :         }
    2847                 :             :     }
    2848                 :             : 
    2849                 :             :   // Build the struct.
    2850                 :       13641 :   Expression* constructor =
    2851                 :       13641 :     Expression::make_struct_composite_literal(struct_type, vals, location);
    2852                 :             : 
    2853                 :             :   // Allocate the initialized struct on the heap.
    2854                 :       13641 :   constructor = Expression::make_heap_expression(constructor, location);
    2855                 :       13641 :   if ((Node::make_node(this)->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
    2856                 :       10957 :     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                 :       13641 :   Expression* param = constructor;
    2862                 :       13641 :   if (!is_constant_function && this->classification() == STATEMENT_GO)
    2863                 :             :     {
    2864                 :        1758 :       fn = Expression::make_temporary_reference(fn_temp, location);
    2865                 :        1758 :       Expression* nil = Expression::make_nil(location);
    2866                 :        1758 :       Expression* isnil = Expression::make_binary(OPERATOR_EQEQ, fn, nil,
    2867                 :             :                                                   location);
    2868                 :        1758 :       Expression* crash = Runtime::make_call(gogo, Runtime::PANIC_GO_NIL,
    2869                 :             :                                              location, 0);
    2870                 :        1758 :       crash = Expression::make_conditional(isnil, crash,
    2871                 :             :                                            Expression::make_nil(location),
    2872                 :             :                                            location);
    2873                 :        1758 :       param = Expression::make_compound(crash, constructor, location);
    2874                 :             :     }
    2875                 :             : 
    2876                 :             :   // Look up the thunk.
    2877                 :       13641 :   Named_object* named_thunk = gogo->lookup(thunk_name, NULL);
    2878                 :       13641 :   go_assert(named_thunk != NULL && named_thunk->is_function());
    2879                 :             : 
    2880                 :             :   // Build the call.
    2881                 :       13641 :   Expression* func = Expression::make_func_reference(named_thunk, NULL,
    2882                 :             :                                                      location);
    2883                 :       13641 :   Expression_list* params = new Expression_list();
    2884                 :       13641 :   params->push_back(param);
    2885                 :       13641 :   Call_expression* call = Expression::make_call(func, params, false, location);
    2886                 :             : 
    2887                 :             :   // Build the simple go or defer statement.
    2888                 :       13641 :   Statement* s;
    2889                 :       13641 :   if (this->classification() == STATEMENT_GO)
    2890                 :        2411 :     s = Statement::make_go_statement(call, location);
    2891                 :       11230 :   else if (this->classification() == STATEMENT_DEFER)
    2892                 :             :     {
    2893                 :       11230 :       s = Statement::make_defer_statement(call, location);
    2894                 :       11230 :       if ((Node::make_node(this)->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
    2895                 :       10957 :         s->defer_statement()->set_on_stack();
    2896                 :             :     }
    2897                 :             :   else
    2898                 :           0 :     go_unreachable();
    2899                 :             : 
    2900                 :             :   // The current block should end with the go statement.
    2901                 :       13641 :   go_assert(block->statements()->size() >= 1);
    2902                 :       13641 :   go_assert(block->statements()->back() == this);
    2903                 :       13641 :   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                 :       13641 :   s->determine_types(gogo);
    2908                 :             : 
    2909                 :             :   // Sanity check.
    2910                 :       13641 :   gogo->check_types_in_block(block);
    2911                 :             : 
    2912                 :             :   // Return true to tell the block not to keep looking at statements.
    2913                 :       13641 :   return true;
    2914                 :       13641 : }
    2915                 :             : 
    2916                 :             : // Set the name to use for thunk parameter N.
    2917                 :             : 
    2918                 :             : void
    2919                 :        4491 : Thunk_statement::thunk_field_param(int n, char* buf, size_t buflen)
    2920                 :             : {
    2921                 :        4491 :   snprintf(buf, buflen, "a%d", n);
    2922                 :        4491 : }
    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                 :       13641 : Thunk_statement::build_struct(Function_type* fntype)
    2929                 :             : {
    2930                 :       13641 :   Location location = this->location();
    2931                 :             : 
    2932                 :       13641 :   Struct_field_list* fields = new Struct_field_list();
    2933                 :             : 
    2934                 :       13641 :   Call_expression* ce = this->call_->call_expression();
    2935                 :       13641 :   Expression* fn = ce->fn();
    2936                 :             : 
    2937                 :       13641 :   if (!this->is_constant_function())
    2938                 :             :     {
    2939                 :             :       // The function to call.
    2940                 :        3781 :       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                 :       13641 :   Interface_field_reference_expression* interface_method =
    2947                 :       14555 :     fn->interface_field_reference_expression();
    2948                 :         914 :   if (interface_method != NULL)
    2949                 :             :     {
    2950                 :         914 :       Typed_identifier tid("object", interface_method->expr()->type(),
    2951                 :         914 :                            location);
    2952                 :         914 :       fields->push_back(Struct_field(tid));
    2953                 :         914 :     }
    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                 :       13641 :   Bound_method_expression* bme = fn->bound_method_expression();
    2959                 :        5513 :   if (bme != NULL)
    2960                 :             :     {
    2961                 :        5513 :       Typed_identifier tid("object", bme->first_argument()->type(), location);
    2962                 :        5513 :       fields->push_back(Struct_field(tid));
    2963                 :        5513 :     }
    2964                 :             : 
    2965                 :       13641 :   const Expression_list* args = ce->args();
    2966                 :       13641 :   if (args != NULL)
    2967                 :             :     {
    2968                 :        3620 :       int i = 0;
    2969                 :        3620 :       for (Expression_list::const_iterator p = args->begin();
    2970                 :        8610 :            p != args->end();
    2971                 :        4990 :            ++p, ++i)
    2972                 :             :         {
    2973                 :        4990 :           if ((*p)->is_constant())
    2974                 :         499 :             continue;
    2975                 :             : 
    2976                 :        4491 :           char buf[50];
    2977                 :        4491 :           this->thunk_field_param(i, buf, sizeof buf);
    2978                 :        4491 :           fields->push_back(Struct_field(Typed_identifier(buf, (*p)->type(),
    2979                 :             :                                                           location)));
    2980                 :             :         }
    2981                 :             :     }
    2982                 :             : 
    2983                 :       13641 :   Struct_type *st = Type::make_struct_type(fields, location);
    2984                 :       13641 :   st->set_is_struct_incomparable();
    2985                 :       13641 :   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                 :       13641 : Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name,
    2993                 :             :                              Struct_type* struct_type)
    2994                 :             : {
    2995                 :       13641 :   Location location = this->location();
    2996                 :             : 
    2997                 :       13641 :   Call_expression* ce = this->call_->call_expression();
    2998                 :             : 
    2999                 :       13641 :   bool may_call_recover = false;
    3000                 :       13641 :   if (this->classification() == STATEMENT_DEFER)
    3001                 :             :     {
    3002                 :       11230 :       Func_expression* fn = ce->fn()->func_expression();
    3003                 :        4474 :       if (fn == NULL)
    3004                 :             :         may_call_recover = true;
    3005                 :             :       else
    3006                 :             :         {
    3007                 :        4474 :           const Named_object* no = fn->named_object();
    3008                 :        4474 :           if (!no->is_function())
    3009                 :             :             may_call_recover = true;
    3010                 :             :           else
    3011                 :        3391 :             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                 :       13641 :   const char* const parameter_name = "__go_thunk_parameter";
    3018                 :       13641 :   Typed_identifier_list* thunk_parameters = new Typed_identifier_list();
    3019                 :       13641 :   Type* pointer_to_struct_type = Type::make_pointer_type(struct_type);
    3020                 :       13641 :   thunk_parameters->push_back(Typed_identifier(parameter_name,
    3021                 :             :                                                pointer_to_struct_type,
    3022                 :             :                                                location));
    3023                 :             : 
    3024                 :       13641 :   Typed_identifier_list* thunk_results = NULL;
    3025                 :       13641 :   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                 :        8840 :       thunk_results = new Typed_identifier_list();
    3031                 :        8840 :       thunk_results->push_back(Typed_identifier("", Type::lookup_bool_type(),
    3032                 :             :                                                 location));
    3033                 :             :     }
    3034                 :             : 
    3035                 :       13641 :   Function_type* thunk_type = Type::make_function_type(NULL, thunk_parameters,
    3036                 :             :                                                        thunk_results,
    3037                 :             :                                                        location);
    3038                 :             : 
    3039                 :             :   // Start building the thunk.
    3040                 :       13641 :   Named_object* function = gogo->start_function(thunk_name, thunk_type, true,
    3041                 :             :                                                 location);
    3042                 :             : 
    3043                 :       13641 :   gogo->start_block(location);
    3044                 :             : 
    3045                 :             :   // For a defer statement, start with a call to
    3046                 :             :   // __go_set_defer_retaddr.  */
    3047                 :       13641 :   Label* retaddr_label = NULL;
    3048                 :       13641 :   if (may_call_recover)
    3049                 :             :     {
    3050                 :        8840 :       retaddr_label = gogo->add_label_reference("retaddr", location, false);
    3051                 :        8840 :       Expression* arg = Expression::make_label_addr(retaddr_label, location);
    3052                 :        8840 :       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                 :        8840 :       gogo->start_block(location);
    3058                 :        8840 :       gogo->add_statement(Statement::make_goto_statement(retaddr_label,
    3059                 :             :                                                          location));
    3060                 :        8840 :       Block* then_block = gogo->finish_block(location);
    3061                 :        8840 :       then_block->determine_types(gogo);
    3062                 :             : 
    3063                 :        8840 :       Statement* s = Statement::make_if_statement(call, then_block, NULL,
    3064                 :             :                                                   location);
    3065                 :        8840 :       s->determine_types(gogo);
    3066                 :        8840 :       gogo->add_statement(s);
    3067                 :             : 
    3068                 :        8840 :       function->func_value()->set_calls_defer_retaddr();
    3069                 :             :     }
    3070                 :             : 
    3071                 :             :   // Get a reference to the parameter.
    3072                 :       13641 :   Named_object* named_parameter = gogo->lookup(parameter_name, NULL);
    3073                 :       13641 :   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                 :       13641 :   Expression* thunk_parameter = Expression::make_var_reference(named_parameter,
    3078                 :             :                                                                location);
    3079                 :       13641 :   thunk_parameter =
    3080                 :       13641 :       Expression::make_dereference(thunk_parameter,
    3081                 :             :                                    Expression::NIL_CHECK_NOT_NEEDED,
    3082                 :             :                                    location);
    3083                 :             : 
    3084                 :       13641 :   Interface_field_reference_expression* interface_method =
    3085                 :       13641 :     ce->fn()->interface_field_reference_expression();
    3086                 :       13641 :   Bound_method_expression* bme = ce->fn()->bound_method_expression();
    3087                 :             : 
    3088                 :       13641 :   Expression* func_to_call;
    3089                 :       13641 :   unsigned int next_index;
    3090                 :       13641 :   if (this->is_constant_function())
    3091                 :             :     {
    3092                 :        9860 :       func_to_call = ce->fn();
    3093                 :        9860 :       next_index = 0;
    3094                 :             :     }
    3095                 :             :   else
    3096                 :             :     {
    3097                 :        3781 :       func_to_call = Expression::make_field_reference(thunk_parameter,
    3098                 :             :                                                       0, location);
    3099                 :        3781 :       next_index = 1;
    3100                 :             :     }
    3101                 :             : 
    3102                 :       13641 :   if (interface_method != NULL)
    3103                 :             :     {
    3104                 :             :       // The main program passes the interface object.
    3105                 :         914 :       go_assert(next_index == 0);
    3106                 :         914 :       Expression* r = Expression::make_field_reference(thunk_parameter, 0,
    3107                 :             :                                                        location);
    3108                 :         914 :       const std::string& name(interface_method->name());
    3109                 :         914 :       func_to_call = Expression::make_interface_field_reference(r, name,
    3110                 :             :                                                                 location);
    3111                 :         914 :       next_index = 1;
    3112                 :             :     }
    3113                 :             : 
    3114                 :       13641 :   if (bme != NULL)
    3115                 :             :     {
    3116                 :             :       // This is a call to a method.
    3117                 :        5513 :       go_assert(next_index == 0);
    3118                 :        5513 :       Expression* r = Expression::make_field_reference(thunk_parameter, 0,
    3119                 :             :                                                        location);
    3120                 :        5513 :       func_to_call = Expression::make_bound_method(r, bme->method(),
    3121                 :             :                                                    bme->function(), location);
    3122                 :        5513 :       next_index = 1;
    3123                 :             :     }
    3124                 :             : 
    3125                 :       13641 :   Expression_list* call_params = new Expression_list();
    3126                 :       13641 :   const Struct_field_list* fields = struct_type->fields();
    3127                 :       13641 :   Struct_field_list::const_iterator p = fields->begin();
    3128                 :       13641 :   for (unsigned int i = 0; i < next_index; ++i)
    3129                 :             :     ++p;
    3130                 :       13641 :   bool is_recover_call = ce->is_recover_call();
    3131                 :       13641 :   Expression* recover_arg = NULL;
    3132                 :             : 
    3133                 :       13641 :   const Expression_list* args = ce->args();
    3134                 :       13641 :   if (args != NULL)
    3135                 :             :     {
    3136                 :        8610 :       for (Expression_list::const_iterator arg = args->begin();
    3137                 :        8610 :            arg != args->end();
    3138                 :        4990 :            ++arg)
    3139                 :             :         {
    3140                 :        4990 :           Expression* param;
    3141                 :        4990 :           if ((*arg)->is_constant())
    3142                 :         499 :             param = *arg;
    3143                 :             :           else
    3144                 :             :             {
    3145                 :        4491 :               Expression* thunk_param =
    3146                 :        4491 :                 Expression::make_var_reference(named_parameter, location);
    3147                 :        4491 :              thunk_param =
    3148                 :        4491 :                  Expression::make_dereference(thunk_param,
    3149                 :             :                                               Expression::NIL_CHECK_NOT_NEEDED,
    3150                 :             :                                               location);
    3151                 :        4491 :               param = Expression::make_field_reference(thunk_param,
    3152                 :             :                                                        next_index,
    3153                 :             :                                                        location);
    3154                 :        4491 :               ++next_index;
    3155                 :             :             }
    3156                 :             : 
    3157                 :        4990 :           if (!is_recover_call)
    3158                 :        4980 :             call_params->push_back(param);
    3159                 :             :           else
    3160                 :             :             {
    3161                 :          10 :               go_assert(call_params->empty());
    3162                 :             :               recover_arg = param;
    3163                 :             :             }
    3164                 :             :         }
    3165                 :             :     }
    3166                 :             : 
    3167                 :       13641 :   if (call_params->empty())
    3168                 :             :     {
    3169                 :       10031 :       delete call_params;
    3170                 :       10031 :       call_params = NULL;
    3171                 :             :     }
    3172                 :             : 
    3173                 :       13641 :   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                 :       13641 :   call->set_varargs_are_lowered();
    3181                 :             : 
    3182                 :       13641 :   Statement* call_statement = Statement::make_statement(call, true);
    3183                 :             : 
    3184                 :       13641 :   call_statement->determine_types(gogo);
    3185                 :       13641 :   gogo->add_statement(call_statement);
    3186                 :             : 
    3187                 :             :   // If this is a defer statement, the label comes immediately after
    3188                 :             :   // the call.
    3189                 :       13641 :   if (may_call_recover)
    3190                 :             :     {
    3191                 :        8840 :       gogo->add_label_definition("retaddr", location);
    3192                 :             : 
    3193                 :        8840 :       Expression_list* vals = new Expression_list();
    3194                 :        8840 :       vals->push_back(Expression::make_boolean(false, location));
    3195                 :        8840 :       Statement* s = Statement::make_return_statement(function, vals,
    3196                 :             :                                                       location);
    3197                 :        8840 :       s->determine_types(gogo);
    3198                 :        8840 :       gogo->add_statement(s);
    3199                 :             :     }
    3200                 :             : 
    3201                 :       13641 :   Block* b = gogo->finish_block(location);
    3202                 :             : 
    3203                 :       13641 :   gogo->add_block(b, location);
    3204                 :             : 
    3205                 :       13641 :   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                 :       13641 :   call_statement->determine_types(gogo);
    3210                 :             : 
    3211                 :       13641 :   gogo->add_conversions_in_block(b);
    3212                 :             : 
    3213                 :       13641 :   if (may_call_recover
    3214                 :       13641 :       || recover_arg != NULL
    3215                 :       13641 :       || this->classification() == STATEMENT_GO)
    3216                 :             :     {
    3217                 :             :       // Dig up the call expression, which may have been changed
    3218                 :             :       // during lowering.
    3219                 :       11251 :       go_assert(call_statement->classification() == STATEMENT_EXPRESSION);
    3220                 :       11251 :       Expression_statement* es =
    3221                 :             :         static_cast<Expression_statement*>(call_statement);
    3222                 :       11251 :       ce = es->expr()->call_expression();
    3223                 :       11251 :       if (ce == NULL)
    3224                 :           0 :         go_assert(saw_errors());
    3225                 :             :       else
    3226                 :             :         {
    3227                 :       11251 :           if (may_call_recover)
    3228                 :        8840 :             ce->set_is_deferred();
    3229                 :       11251 :           if (this->classification() == STATEMENT_GO)
    3230                 :        2411 :             ce->set_is_concurrent();
    3231                 :       11251 :           if (recover_arg != NULL)
    3232                 :          10 :             ce->set_recover_arg(recover_arg);
    3233                 :             :         }
    3234                 :             :     }
    3235                 :             : 
    3236                 :       13641 :   gogo->flatten_block(function, b);
    3237                 :             : 
    3238                 :             :   // That is all the thunk has to do.
    3239                 :       13641 :   gogo->finish_function(location);
    3240                 :       13641 : }
    3241                 :             : 
    3242                 :             : // Get the function and argument expressions.
    3243                 :             : 
    3244                 :             : bool
    3245                 :       13741 : Thunk_statement::get_fn_and_arg(Expression** pfn, Expression** parg)
    3246                 :             : {
    3247                 :       13741 :   if (this->call_->is_error_expression())
    3248                 :             :     return false;
    3249                 :             : 
    3250                 :       13741 :   Call_expression* ce = this->call_->call_expression();
    3251                 :             : 
    3252                 :       13741 :   Expression* fn = ce->fn();
    3253                 :       13741 :   Func_expression* fe = fn->func_expression();
    3254                 :           0 :   go_assert(fe != NULL);
    3255                 :       13741 :   *pfn = Expression::make_func_code_reference(fe->named_object(),
    3256                 :             :                                               fe->location());
    3257                 :             : 
    3258                 :       13741 :   const Expression_list* args = ce->args();
    3259                 :       13741 :   if (args == NULL || args->empty())
    3260                 :          81 :     *parg = Expression::make_nil(this->location());
    3261                 :             :   else
    3262                 :             :     {
    3263                 :       13660 :       go_assert(args->size() == 1);
    3264                 :       13660 :       *parg = args->front();
    3265                 :             :     }
    3266                 :             : 
    3267                 :             :   return true;
    3268                 :             : }
    3269                 :             : 
    3270                 :             : // Class Go_statement.
    3271                 :             : 
    3272                 :             : Bstatement*
    3273                 :        2512 : Go_statement::do_get_backend(Translate_context* context)
    3274                 :             : {
    3275                 :        2512 :   Expression* fn;
    3276                 :        2512 :   Expression* arg;
    3277                 :        2512 :   if (!this->get_fn_and_arg(&fn, &arg))
    3278                 :           0 :     return context->backend()->error_statement();
    3279                 :             : 
    3280                 :        2512 :   Gogo* gogo = context->gogo();
    3281                 :        2512 :   Expression* call = Runtime::make_call(gogo, Runtime::GO, this->location(), 2,
    3282                 :             :                                         fn, arg);
    3283                 :        2512 :   call->determine_type_no_context(gogo);
    3284                 :        2512 :   Bexpression* bcall = call->get_backend(context);
    3285                 :        2512 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    3286                 :        2512 :   return context->backend()->expression_statement(bfunction, bcall);
    3287                 :             : }
    3288                 :             : 
    3289                 :             : // Dump the AST representation for go statement.
    3290                 :             : 
    3291                 :             : void
    3292                 :           0 : Go_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    3293                 :             : {
    3294                 :           0 :   ast_dump_context->print_indent();
    3295                 :           0 :   ast_dump_context->ostream() << "go ";
    3296                 :           0 :   ast_dump_context->dump_expression(this->call());
    3297                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    3298                 :           0 : }
    3299                 :             : 
    3300                 :             : // Make a go statement.
    3301                 :             : 
    3302                 :             : Statement*
    3303                 :        4941 : Statement::make_go_statement(Call_expression* call, Location location)
    3304                 :             : {
    3305                 :        4941 :   return new Go_statement(call, location);
    3306                 :             : }
    3307                 :             : 
    3308                 :             : // Class Defer_statement.
    3309                 :             : 
    3310                 :             : Bstatement*
    3311                 :       11229 : Defer_statement::do_get_backend(Translate_context* context)
    3312                 :             : {
    3313                 :       11229 :   Expression* fn;
    3314                 :       11229 :   Expression* arg;
    3315                 :       11229 :   if (!this->get_fn_and_arg(&fn, &arg))
    3316                 :           0 :     return context->backend()->error_statement();
    3317                 :             : 
    3318                 :       11229 :   Gogo* gogo = context->gogo();
    3319                 :       11229 :   Location loc = this->location();
    3320                 :       11229 :   Expression* ds = context->function()->func_value()->defer_stack(loc);
    3321                 :             : 
    3322                 :       11229 :   Expression* call;
    3323                 :       11229 :   if (this->on_stack_)
    3324                 :             :     {
    3325                 :       10957 :       if (gogo->debug_optimization())
    3326                 :           0 :         go_debug(loc, "stack allocated defer");
    3327                 :             : 
    3328                 :       10957 :       Type* defer_type = Defer_statement::defer_struct_type();
    3329                 :       10957 :       Expression* defer = Expression::make_allocation(defer_type, loc);
    3330                 :       10957 :       defer->allocation_expression()->set_allocate_on_stack();
    3331                 :       10957 :       defer->allocation_expression()->set_no_zero();
    3332                 :       10957 :       call = Runtime::make_call(gogo, Runtime::DEFERPROCSTACK, loc, 4,
    3333                 :             :                                 defer, ds, fn, arg);
    3334                 :             :     }
    3335                 :             :   else
    3336                 :         272 :     call = Runtime::make_call(gogo, Runtime::DEFERPROC, loc, 3,
    3337                 :             :                               ds, fn, arg);
    3338                 :       11229 :   call->determine_type_no_context(gogo);
    3339                 :       11229 :   Bexpression* bcall = call->get_backend(context);
    3340                 :       11229 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    3341                 :       11229 :   return context->backend()->expression_statement(bfunction, bcall);
    3342                 :             : }
    3343                 :             : 
    3344                 :             : Type*
    3345                 :       10957 : Defer_statement::defer_struct_type()
    3346                 :             : {
    3347                 :       10957 :   Type* ptr_type = Type::make_pointer_type(Type::make_void_type());
    3348                 :       10957 :   Type* uintptr_type = Type::lookup_integer_type("uintptr");
    3349                 :       10957 :   Type* bool_type = Type::make_boolean_type();
    3350                 :       10957 :   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                 :       10957 :                                         "heap", bool_type);
    3360                 :             : }
    3361                 :             : 
    3362                 :             : // Dump the AST representation for defer statement.
    3363                 :             : 
    3364                 :             : void
    3365                 :           0 : Defer_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    3366                 :             : {
    3367                 :           0 :   ast_dump_context->print_indent();
    3368                 :           0 :   ast_dump_context->ostream() << "defer ";
    3369                 :           0 :   ast_dump_context->dump_expression(this->call());
    3370                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    3371                 :           0 : }
    3372                 :             : 
    3373                 :             : // Make a defer statement.
    3374                 :             : 
    3375                 :             : Statement*
    3376                 :       22582 : Statement::make_defer_statement(Call_expression* call,
    3377                 :             :                                 Location location)
    3378                 :             : {
    3379                 :       22582 :   return new Defer_statement(call, location);
    3380                 :             : }
    3381                 :             : 
    3382                 :             : // Class Return_statement.
    3383                 :             : 
    3384                 :             : void
    3385                 :      603263 : Return_statement::do_determine_types(Gogo* gogo)
    3386                 :             : {
    3387                 :      603263 :   if (this->types_are_determined_)
    3388                 :             :     return;
    3389                 :      372819 :   this->types_are_determined_ = true;
    3390                 :             : 
    3391                 :      372819 :   size_t vals_count = this->vals_ == NULL ? 0 : this->vals_->size();
    3392                 :      341287 :   if (vals_count == 0)
    3393                 :             :     return;
    3394                 :             : 
    3395                 :      341287 :   Function::Results* results =
    3396                 :      341287 :     this->function_->func_value()->result_variables();
    3397                 :      341287 :   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                 :      341287 :   if (results_count > 1
    3402                 :      341287 :       && vals_count == 1
    3403                 :      341287 :       && this->vals_->front()->call_expression() != NULL)
    3404                 :             :     {
    3405                 :        4963 :       Call_expression* call = this->vals_->front()->call_expression();
    3406                 :        4963 :       call->set_expected_result_count(results_count);
    3407                 :        4963 :       call->determine_type_no_context(gogo);
    3408                 :        9926 :       delete this->vals_;
    3409                 :        4963 :       this->vals_ = new Expression_list();
    3410                 :       15266 :       for (size_t i = 0; i < results_count; ++i)
    3411                 :       10303 :         this->vals_->push_back(Expression::make_call_result(call, i));
    3412                 :             :       vals_count = results_count;
    3413                 :             :     }
    3414                 :             : 
    3415                 :      341287 :   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                 :          42 :       for (Expression_list::const_iterator pe = this->vals_->begin();
    3420                 :          42 :            pe != this->vals_->end();
    3421                 :          27 :            ++pe)
    3422                 :          27 :         (*pe)->determine_type_no_context(gogo);
    3423                 :             :       return;
    3424                 :             :     }
    3425                 :             : 
    3426                 :      341272 :   Expression_list::const_iterator pe = this->vals_->begin();
    3427                 :      341272 :   for (Function::Results::const_iterator pr = results->begin();
    3428                 :      745927 :        pr != results->end();
    3429                 :      404655 :        ++pr, ++pe)
    3430                 :             :     {
    3431                 :      404655 :       Type* rvtype = (*pr)->result_var_value()->type();
    3432                 :      404655 :       Type_context context(rvtype, false);
    3433                 :      404655 :       (*pe)->determine_type(gogo, &context);
    3434                 :             :     }
    3435                 :             : }
    3436                 :             : 
    3437                 :             : void
    3438                 :      210143 : Return_statement::do_check_types(Gogo*)
    3439                 :             : {
    3440                 :      210143 :   size_t vals_count = this->vals_ == NULL ? 0 : this->vals_->size();
    3441                 :      210143 :   Function::Results* results =
    3442                 :      210143 :     this->function_->func_value()->result_variables();
    3443                 :      210143 :   size_t results_count = results == NULL ? 0 : results->size();
    3444                 :             : 
    3445                 :      210143 :   if (vals_count == 0)
    3446                 :             :     {
    3447                 :       18953 :       if (results_count > 0
    3448                 :       18953 :           && !this->function_->func_value()->results_are_named())
    3449                 :           1 :         this->report_error(_("not enough arguments to return"));
    3450                 :       18953 :       return;
    3451                 :             :     }
    3452                 :             : 
    3453                 :      191190 :   if (results_count == 0)
    3454                 :             :     {
    3455                 :           4 :       this->report_error(_("return with value in function "
    3456                 :             :                            "with no return type"));
    3457                 :           8 :       delete this->vals_;
    3458                 :           4 :       this->vals_ = NULL;
    3459                 :           4 :       return;
    3460                 :             :     }
    3461                 :             : 
    3462                 :      191186 :   if (vals_count < results_count)
    3463                 :             :     {
    3464                 :           8 :       this->report_error(_("not enough arguments to return"));
    3465                 :           8 :       return;
    3466                 :             :     }
    3467                 :             : 
    3468                 :      191178 :   if (vals_count > results_count)
    3469                 :             :     {
    3470                 :           3 :       this->report_error(_("too many values in return statement"));
    3471                 :           3 :       return;
    3472                 :             :     }
    3473                 :             : 
    3474                 :      191175 :   Expression_list::const_iterator pe = this->vals_->begin();
    3475                 :      191175 :   int i = 1;
    3476                 :      191175 :   for (Function::Results::const_iterator pr = results->begin();
    3477                 :      445661 :        pr != results->end();
    3478                 :      254486 :        ++pr, ++pe, ++i)
    3479                 :             :     {
    3480                 :      254486 :       Named_object* rv = *pr;
    3481                 :      254486 :       Expression* e = *pe;
    3482                 :             : 
    3483                 :      254486 :       std::string reason;
    3484                 :      254486 :       if (!Type::are_assignable(rv->result_var_value()->type(), e->type(),
    3485                 :             :                                 &reason))
    3486                 :             :         {
    3487                 :           7 :           if (reason.empty())
    3488                 :           0 :             go_error_at(e->location(),
    3489                 :             :                         "incompatible type for return value %d", i);
    3490                 :             :           else
    3491                 :           7 :             go_error_at(e->location(),
    3492                 :             :                         "incompatible type for return value %d (%s)",
    3493                 :             :                         i, reason.c_str());
    3494                 :           7 :           this->set_is_error();
    3495                 :             :         }
    3496                 :      254486 :     }
    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                 :      789172 : Return_statement::do_lower(Gogo* gogo, Named_object*,
    3508                 :             :                            Block* enclosing, Statement_inserter*)
    3509                 :             : {
    3510                 :      789172 :   Location loc = this->location();
    3511                 :             : 
    3512                 :      789172 :   if (this->classification() == STATEMENT_ERROR)
    3513                 :           0 :     return Statement::make_error_statement(loc);
    3514                 :             : 
    3515                 :      789172 :   if (this->is_lowered_)
    3516                 :      416377 :     return this;
    3517                 :             : 
    3518                 :      372795 :   Expression_list* vals = this->vals_;
    3519                 :      372795 :   this->vals_ = NULL;
    3520                 :      372795 :   this->is_lowered_ = true;
    3521                 :             : 
    3522                 :      372795 :   size_t vals_count = vals == NULL ? 0 : vals->size();
    3523                 :             : 
    3524                 :      341264 :   if (vals_count == 0)
    3525                 :       31531 :     return this;
    3526                 :             : 
    3527                 :      341264 :   Function::Results* results =
    3528                 :      341264 :     this->function_->func_value()->result_variables();
    3529                 :      341264 :   size_t results_count = results == NULL ? 0 : results->size();
    3530                 :             : 
    3531                 :      341264 :   go_assert(vals_count == results_count);
    3532                 :             : 
    3533                 :      341264 :   Block* b = new Block(enclosing, loc);
    3534                 :             : 
    3535                 :      341264 :   Expression_list* lhs = new Expression_list();
    3536                 :      341264 :   Expression_list* rhs = new Expression_list();
    3537                 :             : 
    3538                 :      341264 :   Expression_list::const_iterator pe = vals->begin();
    3539                 :      341264 :   for (Function::Results::const_iterator pr = results->begin();
    3540                 :      745909 :        pr != results->end();
    3541                 :      404645 :        ++pr, ++pe)
    3542                 :             :     {
    3543                 :      404645 :       Named_object* rv = *pr;
    3544                 :      404645 :       Expression* e = *pe;
    3545                 :      404645 :       Expression* ve = Expression::make_var_reference(rv, e->location());
    3546                 :      404645 :       lhs->push_back(ve);
    3547                 :      404645 :       rhs->push_back(e);
    3548                 :             :     }
    3549                 :             : 
    3550                 :      341264 :   if (lhs->size() == 1)
    3551                 :             :     {
    3552                 :      287250 :       Statement* s = Statement::make_assignment(lhs->front(), rhs->front(),
    3553                 :             :                                                 loc);
    3554                 :      287250 :       s->determine_types(gogo);
    3555                 :      287250 :       b->add_statement(s);
    3556                 :      287250 :       delete lhs;
    3557                 :      287250 :       delete rhs;
    3558                 :             :     }
    3559                 :             :   else
    3560                 :             :     {
    3561                 :       54014 :       Statement* s = Statement::make_tuple_assignment(lhs, rhs, loc);
    3562                 :       54014 :       s->determine_types(gogo);
    3563                 :       54014 :       b->add_statement(s);
    3564                 :             :     }
    3565                 :             : 
    3566                 :      341264 :   b->add_statement(this);
    3567                 :             : 
    3568                 :      341264 :   delete vals;
    3569                 :             : 
    3570                 :      341264 :   return Statement::make_block_statement(b, loc);
    3571                 :             : }
    3572                 :             : 
    3573                 :             : // Convert a return statement to the backend representation.
    3574                 :             : 
    3575                 :             : Bstatement*
    3576                 :      372263 : Return_statement::do_get_backend(Translate_context* context)
    3577                 :             : {
    3578                 :      372263 :   Location loc = this->location();
    3579                 :             : 
    3580                 :      372263 :   Function* function = context->function()->func_value();
    3581                 :      372263 :   Function::Results* results = function->result_variables();
    3582                 :      372263 :   std::vector<Bexpression*> retvals;
    3583                 :      372263 :   if (results != NULL && !results->empty())
    3584                 :             :     {
    3585                 :      361320 :       retvals.reserve(results->size());
    3586                 :      361320 :       for (Function::Results::const_iterator p = results->begin();
    3587                 :      795229 :            p != results->end();
    3588                 :      433909 :            p++)
    3589                 :             :         {
    3590                 :      433909 :           Expression* vr = Expression::make_var_reference(*p, loc);
    3591                 :      433909 :           retvals.push_back(vr->get_backend(context));
    3592                 :             :         }
    3593                 :             :     }
    3594                 :             : 
    3595                 :      372263 :   return context->backend()->return_statement(function->get_decl(),
    3596                 :      372263 :                                               retvals, loc);
    3597                 :      372263 : }
    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                 :       14161 : Return_statement::do_export_statement(Export_function_body* efb)
    3605                 :             : {
    3606                 :       14161 :   efb->write_c_string("return");
    3607                 :       14161 : }
    3608                 :             : 
    3609                 :             : // Dump the AST representation for a return statement.
    3610                 :             : 
    3611                 :             : void
    3612                 :           0 : Return_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    3613                 :             : {
    3614                 :           0 :   ast_dump_context->print_indent();
    3615                 :           0 :   ast_dump_context->ostream() << "return " ;
    3616                 :           0 :   ast_dump_context->dump_expression_list(this->vals_);
    3617                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    3618                 :           0 : }
    3619                 :             : 
    3620                 :             : // Make a return statement.
    3621                 :             : 
    3622                 :             : Return_statement*
    3623                 :      372819 : Statement::make_return_statement(Named_object* function, Expression_list* vals,
    3624                 :             :                                  Location location)
    3625                 :             : {
    3626                 :      372819 :   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                 :        2137 : Statement::make_return_from_call(Named_object* function, Call_expression* call,
    3633                 :             :                                  Location location)
    3634                 :             : {
    3635                 :        2137 :   size_t rc = call->result_count();
    3636                 :        2137 :   if (rc == 0)
    3637                 :        1349 :     return Statement::make_statement(call, true);
    3638                 :             :   else
    3639                 :             :     {
    3640                 :         788 :       Expression_list* vals = new Expression_list();
    3641                 :         788 :       if (rc == 1)
    3642                 :         672 :         vals->push_back(call);
    3643                 :             :       else
    3644                 :             :         {
    3645                 :         354 :           for (size_t i = 0; i < rc; ++i)
    3646                 :         238 :             vals->push_back(Expression::make_call_result(call, i));
    3647                 :             :         }
    3648                 :         788 :       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                 :       18944 :   Bc_statement(bool is_break, Unnamed_label* label, Location location)
    3658                 :       18944 :     : Statement(STATEMENT_BREAK_OR_CONTINUE, location),
    3659                 :       37888 :       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                 :      475942 :   do_traverse(Traverse*)
    3669                 :      475942 :   { return TRAVERSE_CONTINUE; }
    3670                 :             : 
    3671                 :             :   bool
    3672                 :           0 :   do_may_fall_through() const
    3673                 :           0 :   { return false; }
    3674                 :             : 
    3675                 :             :   Bstatement*
    3676                 :       18830 :   do_get_backend(Translate_context* context)
    3677                 :       18830 :   { 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                 :           0 : Bc_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    3693                 :             : {
    3694                 :           0 :   ast_dump_context->print_indent();
    3695                 :           0 :   ast_dump_context->ostream() << (this->is_break_ ? "break" : "continue");
    3696                 :           0 :   if (this->label_ != NULL)
    3697                 :             :     {
    3698                 :           0 :       ast_dump_context->ostream() << " ";
    3699                 :           0 :       ast_dump_context->dump_label_name(this->label_);
    3700                 :             :     }
    3701                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    3702                 :           0 : }
    3703                 :             : 
    3704                 :             : // Make a break statement.
    3705                 :             : 
    3706                 :             : Statement*
    3707                 :        8149 : Statement::make_break_statement(Unnamed_label* label, Location location)
    3708                 :             : {
    3709                 :        8149 :   return new Bc_statement(true, label, location);
    3710                 :             : }
    3711                 :             : 
    3712                 :             : // Make a continue statement.
    3713                 :             : 
    3714                 :             : Statement*
    3715                 :       10795 : Statement::make_continue_statement(Unnamed_label* label,
    3716                 :             :                                    Location location)
    3717                 :             : {
    3718                 :       10795 :   return new Bc_statement(false, label, location);
    3719                 :             : }
    3720                 :             : 
    3721                 :             : // Class Goto_statement.
    3722                 :             : 
    3723                 :             : int
    3724                 :      130014 : Goto_statement::do_traverse(Traverse*)
    3725                 :             : {
    3726                 :      130014 :   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                 :        2101 : Goto_statement::do_check_types(Gogo*)
    3734                 :             : {
    3735                 :        2101 :   if (!this->label_->is_defined())
    3736                 :             :     {
    3737                 :           3 :       go_error_at(this->location(), "reference to undefined label %qs",
    3738                 :           3 :                   Gogo::message_name(this->label_->name()).c_str());
    3739                 :           3 :       this->set_is_error();
    3740                 :             :     }
    3741                 :        2101 : }
    3742                 :             : 
    3743                 :             : // Convert the goto statement to the backend representation.
    3744                 :             : 
    3745                 :             : Bstatement*
    3746                 :       10842 : Goto_statement::do_get_backend(Translate_context* context)
    3747                 :             : {
    3748                 :       10842 :   Blabel* blabel = this->label_->get_backend_label(context);
    3749                 :       10842 :   return context->backend()->goto_statement(blabel, this->location());
    3750                 :             : }
    3751                 :             : 
    3752                 :             : // Export a goto statement.
    3753                 :             : 
    3754                 :             : void
    3755                 :           8 : Goto_statement::do_export_statement(Export_function_body *efb)
    3756                 :             : {
    3757                 :           8 :   efb->write_c_string("goto ");
    3758                 :           8 :   efb->write_string(this->label_->name());
    3759                 :           8 : }
    3760                 :             : 
    3761                 :             : // Import a goto or goto unnamed statement.
    3762                 :             : 
    3763                 :             : Statement*
    3764                 :        1523 : Goto_statement::do_import(Import_function_body* ifb, Location loc)
    3765                 :             : {
    3766                 :        1523 :   ifb->require_c_string("goto ");
    3767                 :        1523 :   std::string id = ifb->read_identifier();
    3768                 :        1523 :   if (id[0] != '$')
    3769                 :             :     {
    3770                 :           1 :       Function* fn = ifb->function()->func_value();
    3771                 :           1 :       Label* label = fn->add_label_reference(ifb->gogo(), id, loc, false);
    3772                 :           1 :       return Statement::make_goto_statement(label, loc);
    3773                 :             :     }
    3774                 :             :   else
    3775                 :             :     {
    3776                 :        1522 :       if (id[1] != 'l')
    3777                 :             :         {
    3778                 :           0 :           if (!ifb->saw_error())
    3779                 :           0 :             go_error_at(loc,
    3780                 :             :                         ("invalid export data for %qs: "
    3781                 :             :                          "bad unnamed label at %lu"),
    3782                 :           0 :                         ifb->name().c_str(),
    3783                 :           0 :                         static_cast<unsigned long>(ifb->off()));
    3784                 :           0 :           ifb->set_saw_error();
    3785                 :           0 :           return Statement::make_error_statement(loc);
    3786                 :             :         }
    3787                 :        1522 :       const char* p = id.c_str();
    3788                 :        1522 :       char* end;
    3789                 :        1522 :       long idx = strtol(p + 2, &end, 10);
    3790                 :        1522 :       if (*end != '\0' || idx > 0x7fffffff)
    3791                 :             :         {
    3792                 :           0 :           if (!ifb->saw_error())
    3793                 :           0 :             go_error_at(loc,
    3794                 :             :                         ("invalid export data for %qs: "
    3795                 :             :                          "bad unnamed label index at %lu"),
    3796                 :           0 :                         ifb->name().c_str(),
    3797                 :           0 :                         static_cast<unsigned long>(ifb->off()));
    3798                 :           0 :           ifb->set_saw_error();
    3799                 :           0 :           return Statement::make_error_statement(loc);
    3800                 :             :         }
    3801                 :             : 
    3802                 :        1522 :       Unnamed_label* label = ifb->unnamed_label(idx, loc);
    3803                 :        1522 :       return Statement::make_goto_unnamed_statement(label, loc);
    3804                 :             :     }
    3805                 :        1523 : }
    3806                 :             : 
    3807                 :             : // Dump the AST representation for a goto statement.
    3808                 :             : 
    3809                 :             : void
    3810                 :           0 : Goto_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    3811                 :             : {
    3812                 :           0 :   ast_dump_context->print_indent();
    3813                 :           0 :   ast_dump_context->ostream() << "goto " << this->label_->name() << dsuffix(location()) << std::endl;
    3814                 :           0 : }
    3815                 :             : 
    3816                 :             : // Make a goto statement.
    3817                 :             : 
    3818                 :             : Statement*
    3819                 :       10942 : Statement::make_goto_statement(Label* label, Location location)
    3820                 :             : {
    3821                 :       10942 :   return new Goto_statement(label, location);
    3822                 :             : }
    3823                 :             : 
    3824                 :             : // Class Goto_unnamed_statement.
    3825                 :             : 
    3826                 :             : int
    3827                 :     3378213 : Goto_unnamed_statement::do_traverse(Traverse*)
    3828                 :             : {
    3829                 :     3378213 :   return TRAVERSE_CONTINUE;
    3830                 :             : }
    3831                 :             : 
    3832                 :             : // Convert the goto unnamed statement to the backend representation.
    3833                 :             : 
    3834                 :             : Bstatement*
    3835                 :      175104 : Goto_unnamed_statement::do_get_backend(Translate_context* context)
    3836                 :             : {
    3837                 :      175104 :   return this->label_->get_goto(context, this->location());
    3838                 :             : }
    3839                 :             : 
    3840                 :             : // Export a goto unnamed statement.
    3841                 :             : 
    3842                 :             : void
    3843                 :        1703 : Goto_unnamed_statement::do_export_statement(Export_function_body *efb)
    3844                 :             : {
    3845                 :        1703 :   unsigned int index = efb->unnamed_label_index(this->label_);
    3846                 :        1703 :   char buf[100];
    3847                 :        1703 :   snprintf(buf, sizeof buf, "goto $l%u", index);
    3848                 :        1703 :   efb->write_c_string(buf);
    3849                 :        1703 : }
    3850                 :             : 
    3851                 :             : // Dump the AST representation for an unnamed goto statement
    3852                 :             : 
    3853                 :             : void
    3854                 :           0 : Goto_unnamed_statement::do_dump_statement(
    3855                 :             :     Ast_dump_context* ast_dump_context) const
    3856                 :             : {
    3857                 :           0 :   ast_dump_context->print_indent();
    3858                 :           0 :   ast_dump_context->ostream() << "goto ";
    3859                 :           0 :   ast_dump_context->dump_label_name(this->label_);
    3860                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    3861                 :           0 : }
    3862                 :             : 
    3863                 :             : // Make a goto statement to an unnamed label.
    3864                 :             : 
    3865                 :             : Statement*
    3866                 :      175691 : Statement::make_goto_unnamed_statement(Unnamed_label* label,
    3867                 :             :                                        Location location)
    3868                 :             : {
    3869                 :      175691 :   return new Goto_unnamed_statement(label, location);
    3870                 :             : }
    3871                 :             : 
    3872                 :             : // Class Label_statement.
    3873                 :             : 
    3874                 :             : // Traversal.
    3875                 :             : 
    3876                 :             : int
    3877                 :      120608 : Label_statement::do_traverse(Traverse*)
    3878                 :             : {
    3879                 :      120608 :   return TRAVERSE_CONTINUE;
    3880                 :             : }
    3881                 :             : 
    3882                 :             : // Return the backend representation of the statement defining this
    3883                 :             : // label.
    3884                 :             : 
    3885                 :             : Bstatement*
    3886                 :       10415 : Label_statement::do_get_backend(Translate_context* context)
    3887                 :             : {
    3888                 :       10415 :   if (this->label_->is_dummy_label())
    3889                 :             :     {
    3890                 :           3 :       Bexpression* bce = context->backend()->boolean_constant_expression(false);
    3891                 :           3 :       Bfunction* bfunction = context->function()->func_value()->get_decl();
    3892                 :           3 :       return context->backend()->expression_statement(bfunction, bce);
    3893                 :             :     }
    3894                 :       10412 :   Blabel* blabel = this->label_->get_backend_label(context);
    3895                 :       10412 :   return context->backend()->label_definition_statement(blabel);
    3896                 :             : }
    3897                 :             : 
    3898                 :             : // Export a label.
    3899                 :             : 
    3900                 :             : void
    3901                 :           8 : Label_statement::do_export_statement(Export_function_body* efb)
    3902                 :             : {
    3903                 :           8 :   if (this->label_->is_dummy_label())
    3904                 :             :     return;
    3905                 :             :   // We use a leading colon, not a trailing one, to simplify import.
    3906                 :           8 :   efb->write_c_string(":");
    3907                 :           8 :   efb->write_string(this->label_->name());
    3908                 :             : }
    3909                 :             : 
    3910                 :             : // Import a label or an unnamed label.
    3911                 :             : 
    3912                 :             : Statement*
    3913                 :        1434 : Label_statement::do_import(Import_function_body* ifb, Location loc)
    3914                 :             : {
    3915                 :        1434 :   ifb->require_c_string(":");
    3916                 :        1434 :   std::string id = ifb->read_identifier();
    3917                 :        1434 :   if (id[0] != '$')
    3918                 :             :     {
    3919                 :           1 :       Function* fn = ifb->function()->func_value();
    3920                 :           1 :       Label* label = fn->add_label_definition(ifb->gogo(), id, loc);
    3921                 :           1 :       return Statement::make_label_statement(label, loc);
    3922                 :             :     }
    3923                 :             :   else
    3924                 :             :     {
    3925                 :        1433 :       if (id[1] != 'l')
    3926                 :             :         {
    3927                 :           0 :           if (!ifb->saw_error())
    3928                 :           0 :             go_error_at(loc,
    3929                 :             :                         ("invalid export data for %qs: "
    3930                 :             :                          "bad unnamed label at %lu"),
    3931                 :           0 :                         ifb->name().c_str(),
    3932                 :           0 :                         static_cast<unsigned long>(ifb->off()));
    3933                 :           0 :           ifb->set_saw_error();
    3934                 :           0 :           return Statement::make_error_statement(loc);
    3935                 :             :         }
    3936                 :        1433 :       const char* p = id.c_str();
    3937                 :        1433 :       char* end;
    3938                 :        1433 :       long idx = strtol(p + 2, &end, 10);
    3939                 :        1433 :       if (*end != '\0' || idx > 0x7fffffff)
    3940                 :             :         {
    3941                 :           0 :           if (!ifb->saw_error())
    3942                 :           0 :             go_error_at(loc,
    3943                 :             :                         ("invalid export data for %qs: "
    3944                 :             :                          "bad unnamed label index at %lu"),
    3945                 :           0 :                         ifb->name().c_str(),
    3946                 :           0 :                         static_cast<unsigned long>(ifb->off()));
    3947                 :           0 :           ifb->set_saw_error();
    3948                 :           0 :           return Statement::make_error_statement(loc);
    3949                 :             :         }
    3950                 :             : 
    3951                 :        1433 :       Unnamed_label* label = ifb->unnamed_label(idx, loc);
    3952                 :        1433 :       return Statement::make_unnamed_label_statement(label);
    3953                 :             :     }
    3954                 :        1434 : }
    3955                 :             : 
    3956                 :             : // Dump the AST for a label definition statement.
    3957                 :             : 
    3958                 :             : void
    3959                 :           0 : Label_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    3960                 :             : {
    3961                 :           0 :   ast_dump_context->print_indent();
    3962                 :           0 :   ast_dump_context->ostream() << this->label_->name() << ":" << dsuffix(location()) << std::endl;
    3963                 :           0 : }
    3964                 :             : 
    3965                 :             : // Make a label statement.
    3966                 :             : 
    3967                 :             : Statement*
    3968                 :       10526 : Statement::make_label_statement(Label* label, Location location)
    3969                 :             : {
    3970                 :       10526 :   return new Label_statement(label, location);
    3971                 :             : }
    3972                 :             : 
    3973                 :             : // Class Unnamed_label_statement.
    3974                 :             : 
    3975                 :      167230 : Unnamed_label_statement::Unnamed_label_statement(Unnamed_label* label)
    3976                 :             :   : Statement(STATEMENT_UNNAMED_LABEL, label->location()),
    3977                 :      167230 :     label_(label)
    3978                 :      167230 : { }
    3979                 :             : 
    3980                 :             : int
    3981                 :     3185853 : Unnamed_label_statement::do_traverse(Traverse*)
    3982                 :             : {
    3983                 :     3185853 :   return TRAVERSE_CONTINUE;
    3984                 :             : }
    3985                 :             : 
    3986                 :             : // Get the backend definition for this unnamed label statement.
    3987                 :             : 
    3988                 :             : Bstatement*
    3989                 :      166614 : Unnamed_label_statement::do_get_backend(Translate_context* context)
    3990                 :             : {
    3991                 :      166614 :   return this->label_->get_definition(context);
    3992                 :             : }
    3993                 :             : 
    3994                 :             : // Export an unnamed label.
    3995                 :             : 
    3996                 :             : void
    3997                 :        1641 : Unnamed_label_statement::do_export_statement(Export_function_body* efb)
    3998                 :             : {
    3999                 :        1641 :   unsigned int index = efb->unnamed_label_index(this->label_);
    4000                 :        1641 :   char buf[50];
    4001                 :             :   // We use a leading colon, not a trailing one, to simplify import.
    4002                 :        1641 :   snprintf(buf, sizeof buf, ":$l%u", index);
    4003                 :        1641 :   efb->write_c_string(buf);
    4004                 :        1641 : }
    4005                 :             : 
    4006                 :             : // Dump the AST representation for an unnamed label definition statement.
    4007                 :             : 
    4008                 :             : void
    4009                 :           0 : Unnamed_label_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    4010                 :             :     const
    4011                 :             : {
    4012                 :           0 :   ast_dump_context->print_indent();
    4013                 :           0 :   ast_dump_context->dump_label_name(this->label_);
    4014                 :           0 :   ast_dump_context->ostream() << ":" << dsuffix(location()) << std::endl;
    4015                 :           0 : }
    4016                 :             : 
    4017                 :             : // Make an unnamed label statement.
    4018                 :             : 
    4019                 :             : Statement*
    4020                 :      167230 : Statement::make_unnamed_label_statement(Unnamed_label* label)
    4021                 :             : {
    4022                 :      167230 :   return new Unnamed_label_statement(label);
    4023                 :             : }
    4024                 :             : 
    4025                 :             : // Class If_statement.
    4026                 :             : 
    4027                 :             : // Traversal.
    4028                 :             : 
    4029                 :             : int
    4030                 :     9825727 : If_statement::do_traverse(Traverse* traverse)
    4031                 :             : {
    4032                 :     9825727 :   if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT
    4033                 :     9825727 :       || this->then_block_->traverse(traverse) == TRAVERSE_EXIT)
    4034                 :      359153 :     return TRAVERSE_EXIT;
    4035                 :     9466574 :   if (this->else_block_ != NULL)
    4036                 :             :     {
    4037                 :      664452 :       if (this->else_block_->traverse(traverse) == TRAVERSE_EXIT)
    4038                 :             :         return TRAVERSE_EXIT;
    4039                 :             :     }
    4040                 :             :   return TRAVERSE_CONTINUE;
    4041                 :             : }
    4042                 :             : 
    4043                 :             : void
    4044                 :      814246 : If_statement::do_determine_types(Gogo* gogo)
    4045                 :             : {
    4046                 :      814246 :   Type_context context(Type::lookup_bool_type(), false);
    4047                 :      814246 :   this->cond_->determine_type(gogo, &context);
    4048                 :      814246 :   this->then_block_->determine_types(gogo);
    4049                 :      814246 :   if (this->else_block_ != NULL)
    4050                 :      240908 :     this->else_block_->determine_types(gogo);
    4051                 :      814246 : }
    4052                 :             : 
    4053                 :             : // Check types.
    4054                 :             : 
    4055                 :             : void
    4056                 :      254022 : If_statement::do_check_types(Gogo*)
    4057                 :             : {
    4058                 :      254022 :   Type* type = this->cond_->type();
    4059                 :      254022 :   if (type->is_error())
    4060                 :          12 :     this->set_is_error();
    4061                 :      254010 :   else if (!type->is_boolean_type())
    4062                 :           3 :     this->report_error(_("expected boolean expression"));
    4063                 :      254022 : }
    4064                 :             : 
    4065                 :             : // Whether the overall statement may fall through.
    4066                 :             : 
    4067                 :             : bool
    4068                 :         342 : If_statement::do_may_fall_through() const
    4069                 :             : {
    4070                 :         342 :   return (this->else_block_ == NULL
    4071                 :         329 :           || this->then_block_->may_fall_through()
    4072                 :         670 :           || this->else_block_->may_fall_through());
    4073                 :             : }
    4074                 :             : 
    4075                 :             : // Get the backend representation.
    4076                 :             : 
    4077                 :             : Bstatement*
    4078                 :      698736 : If_statement::do_get_backend(Translate_context* context)
    4079                 :             : {
    4080                 :      698736 :   go_assert(this->cond_->type()->is_boolean_type()
    4081                 :             :              || this->cond_->type()->is_error());
    4082                 :      698736 :   Bexpression* cond = this->cond_->get_backend(context);
    4083                 :      698736 :   Bblock* then_block = this->then_block_->get_backend(context);
    4084                 :      698736 :   Bblock* else_block = (this->else_block_ == NULL
    4085                 :      698736 :                         ? NULL
    4086                 :      235594 :                         : this->else_block_->get_backend(context));
    4087                 :      698736 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    4088                 :      698736 :   return context->backend()->if_statement(bfunction,
    4089                 :             :                                           cond, then_block, else_block,
    4090                 :      698736 :                                           this->location());
    4091                 :             : }
    4092                 :             : 
    4093                 :             : // Export an if statement.
    4094                 :             : 
    4095                 :             : void
    4096                 :        4529 : If_statement::do_export_statement(Export_function_body* efb)
    4097                 :             : {
    4098                 :        4529 :   efb->write_c_string("if ");
    4099                 :        4529 :   this->cond_->export_expression(efb);
    4100                 :        4529 :   efb->write_c_string(" ");
    4101                 :        4529 :   Block_statement::export_block(efb, this->then_block_, false);
    4102                 :        4529 :   if (this->else_block_ != NULL)
    4103                 :             :     {
    4104                 :          70 :       efb->write_c_string(" else ");
    4105                 :          70 :       Block_statement::export_block(efb, this->else_block_, false);
    4106                 :             :     }
    4107                 :        4529 : }
    4108                 :             : 
    4109                 :             : // Import an if statement.
    4110                 :             : 
    4111                 :             : Statement*
    4112                 :        5427 : If_statement::do_import(Import_function_body* ifb, Location loc)
    4113                 :             : {
    4114                 :        5427 :   ifb->require_c_string("if ");
    4115                 :             : 
    4116                 :        5427 :   Expression* cond = Expression::import_expression(ifb, loc);
    4117                 :        5427 :   ifb->require_c_string(" ");
    4118                 :             : 
    4119                 :        5427 :   if (!ifb->match_c_string("{"))
    4120                 :             :     {
    4121                 :           0 :       if (!ifb->saw_error())
    4122                 :           0 :         go_error_at(ifb->location(),
    4123                 :             :                     "import error for %qs: no block for if statement at %lu",
    4124                 :           0 :                     ifb->name().c_str(),
    4125                 :           0 :                     static_cast<unsigned long>(ifb->off()));
    4126                 :           0 :       ifb->set_saw_error();
    4127                 :           0 :       return Statement::make_error_statement(loc);
    4128                 :             :     }
    4129                 :             : 
    4130                 :        5427 :   bool is_lowered_for_statement;
    4131                 :        5427 :   Block* then_block = Block_statement::do_import(ifb, loc,
    4132                 :             :                                                  &is_lowered_for_statement);
    4133                 :        5427 :   if (then_block == NULL)
    4134                 :           0 :     return Statement::make_error_statement(loc);
    4135                 :        5427 :   if (is_lowered_for_statement)
    4136                 :             :     {
    4137                 :           0 :       if (!ifb->saw_error())
    4138                 :           0 :         go_error_at(ifb->location(),
    4139                 :             :                     ("import error for %qs: "
    4140                 :             :                      "unexpected lowered for in if statement at %lu"),
    4141                 :           0 :                     ifb->name().c_str(),
    4142                 :           0 :                     static_cast<unsigned long>(ifb->off()));
    4143                 :           0 :       ifb->set_saw_error();
    4144                 :           0 :       return Statement::make_error_statement(loc);
    4145                 :             :     }
    4146                 :             : 
    4147                 :        5427 :   Block* else_block = NULL;
    4148                 :        5427 :   if (ifb->match_c_string(" else "))
    4149                 :             :     {
    4150                 :         136 :       ifb->advance(6);
    4151                 :         136 :       if (!ifb->match_c_string("{"))
    4152                 :             :         {
    4153                 :           0 :           if (!ifb->saw_error())
    4154                 :           0 :             go_error_at(ifb->location(),
    4155                 :             :                         ("import error for %qs: no else block "
    4156                 :             :                          "for if statement at %lu"),
    4157                 :           0 :                         ifb->name().c_str(),
    4158                 :           0 :                         static_cast<unsigned long>(ifb->off()));
    4159                 :           0 :           ifb->set_saw_error();
    4160                 :           0 :           return Statement::make_error_statement(loc);
    4161                 :             :         }
    4162                 :             : 
    4163                 :         136 :       else_block = Block_statement::do_import(ifb, loc,
    4164                 :             :                                               &is_lowered_for_statement);
    4165                 :         136 :       if (else_block == NULL)
    4166                 :           0 :         return Statement::make_error_statement(loc);
    4167                 :         136 :       if (is_lowered_for_statement)
    4168                 :             :         {
    4169                 :           0 :           if (!ifb->saw_error())
    4170                 :           0 :             go_error_at(ifb->location(),
    4171                 :             :                         ("import error for %qs: "
    4172                 :             :                          "unexpected lowered for in if statement at %lu"),
    4173                 :           0 :                         ifb->name().c_str(),
    4174                 :           0 :                         static_cast<unsigned long>(ifb->off()));
    4175                 :           0 :           ifb->set_saw_error();
    4176                 :           0 :           return Statement::make_error_statement(loc);
    4177                 :             :         }
    4178                 :             :     }
    4179                 :             : 
    4180                 :        5427 :   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                 :           0 : If_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    4187                 :             : {
    4188                 :           0 :   ast_dump_context->print_indent();
    4189                 :           0 :   ast_dump_context->ostream() << "if ";
    4190                 :           0 :   ast_dump_context->dump_expression(this->cond_);
    4191                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    4192                 :           0 :   if (ast_dump_context->dump_subblocks())
    4193                 :             :     {
    4194                 :           0 :       ast_dump_context->dump_block(this->then_block_);
    4195                 :           0 :       if (this->else_block_ != NULL)
    4196                 :             :         {
    4197                 :           0 :           ast_dump_context->print_indent();
    4198                 :           0 :           ast_dump_context->ostream() << "else" << std::endl;
    4199                 :           0 :           ast_dump_context->dump_block(this->else_block_);
    4200                 :             :         }
    4201                 :             :     }
    4202                 :           0 : }
    4203                 :             : 
    4204                 :             : // Make an if statement.
    4205                 :             : 
    4206                 :             : Statement*
    4207                 :      704075 : Statement::make_if_statement(Expression* cond, Block* then_block,
    4208                 :             :                              Block* else_block, Location location)
    4209                 :             : {
    4210                 :      704075 :   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                 :       33164 : Case_clauses::Hash_integer_value::operator()(Expression* pe) const
    4224                 :             : {
    4225                 :       33164 :   Numeric_constant nc;
    4226                 :       33164 :   mpz_t ival;
    4227                 :       33164 :   if (!pe->numeric_constant_value(&nc) || !nc.to_int(&ival))
    4228                 :           0 :     go_unreachable();
    4229                 :       33164 :   size_t ret = mpz_get_ui(ival);
    4230                 :       33164 :   mpz_clear(ival);
    4231                 :       66328 :   return ret;
    4232                 :       33164 : }
    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                 :          47 : Case_clauses::Eq_integer_value::operator()(Expression* a, Expression* b) const
    4245                 :             : {
    4246                 :          47 :   Numeric_constant anc;
    4247                 :          47 :   mpz_t aval;
    4248                 :          47 :   Numeric_constant bnc;
    4249                 :          47 :   mpz_t bval;
    4250                 :          47 :   if (!a->numeric_constant_value(&anc)
    4251                 :          47 :       || !anc.to_int(&aval)
    4252                 :          47 :       || !b->numeric_constant_value(&bnc)
    4253                 :          94 :       || !bnc.to_int(&bval))
    4254                 :           0 :     go_unreachable();
    4255                 :          47 :   bool ret = mpz_cmp(aval, bval) == 0;
    4256                 :          47 :   mpz_clear(aval);
    4257                 :          47 :   mpz_clear(bval);
    4258                 :          94 :   return ret;
    4259                 :          47 : }
    4260                 :             : 
    4261                 :             : // Class Case_clauses::Case_clause.
    4262                 :             : 
    4263                 :             : // Traversal.
    4264                 :             : 
    4265                 :             : int
    4266                 :      668704 : Case_clauses::Case_clause::traverse(Traverse* traverse)
    4267                 :             : {
    4268                 :      668704 :   if (this->cases_ != NULL
    4269                 :      668704 :       && (traverse->traverse_mask()
    4270                 :      588252 :           & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
    4271                 :             :     {
    4272                 :      463414 :       if (this->cases_->traverse(traverse) == TRAVERSE_EXIT)
    4273                 :             :         return TRAVERSE_EXIT;
    4274                 :             :     }
    4275                 :      668704 :   if (this->statements_ != NULL)
    4276                 :             :     {
    4277                 :      652097 :       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                 :       23577 : Case_clauses::Case_clause::is_constant() const
    4287                 :             : {
    4288                 :       23577 :   if (this->cases_ != NULL)
    4289                 :             :     {
    4290                 :       20882 :       for (Expression_list::const_iterator p = this->cases_->begin();
    4291                 :       54158 :            p != this->cases_->end();
    4292                 :       33276 :            ++p)
    4293                 :       66617 :         if (!(*p)->is_constant() || (*p)->type()->integer_type() == NULL)
    4294                 :          65 :           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                 :       16686 : 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                 :       16686 :   Location loc = this->location_;
    4311                 :       16686 :   Unnamed_label* next_case_label;
    4312                 :       16686 :   if (this->cases_ == NULL || this->cases_->empty())
    4313                 :             :     {
    4314                 :        2671 :       go_assert(this->is_default_);
    4315                 :             :       next_case_label = NULL;
    4316                 :             :     }
    4317                 :             :   else
    4318                 :             :     {
    4319                 :             :       Expression* cond = NULL;
    4320                 :             : 
    4321                 :       17902 :       for (Expression_list::const_iterator p = this->cases_->begin();
    4322                 :       31917 :            p != this->cases_->end();
    4323                 :       17902 :            ++p)
    4324                 :             :         {
    4325                 :       17902 :           Expression* ref = Expression::make_temporary_reference(val_temp,
    4326                 :             :                                                                  loc);
    4327                 :       35804 :           Expression* this_cond = Expression::make_binary(OPERATOR_EQEQ, ref,
    4328                 :       17902 :                                                           *p, loc);
    4329                 :       17902 :           if (cond == NULL)
    4330                 :             :             cond = this_cond;
    4331                 :             :           else
    4332                 :        3887 :             cond = Expression::make_binary(OPERATOR_OROR, cond, this_cond, loc);
    4333                 :             :         }
    4334                 :             : 
    4335                 :       14015 :       Block* then_block = new Block(b, loc);
    4336                 :       14015 :       next_case_label = new Unnamed_label(Linemap::unknown_location());
    4337                 :       14015 :       Statement* s = Statement::make_goto_unnamed_statement(next_case_label,
    4338                 :             :                                                             loc);
    4339                 :       14015 :       then_block->add_statement(s);
    4340                 :             : 
    4341                 :             :       // if !COND { goto NEXT_CASE_LABEL }
    4342                 :       14015 :       cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
    4343                 :       14015 :       s = Statement::make_if_statement(cond, then_block, NULL, loc);
    4344                 :       14015 :       s->determine_types(gogo);
    4345                 :       14015 :       b->add_statement(s);
    4346                 :             :     }
    4347                 :             : 
    4348                 :       16686 :   if (start_label != NULL)
    4349                 :         115 :     b->add_statement(Statement::make_unnamed_label_statement(start_label));
    4350                 :             : 
    4351                 :       16686 :   if (this->statements_ != NULL)
    4352                 :       15974 :     b->add_statement(Statement::make_block_statement(this->statements_, loc));
    4353                 :             : 
    4354                 :       16686 :   Statement* s = Statement::make_goto_unnamed_statement(finish_label, loc);
    4355                 :       16686 :   b->add_statement(s);
    4356                 :             : 
    4357                 :       16686 :   if (next_case_label != NULL)
    4358                 :       14015 :     b->add_statement(Statement::make_unnamed_label_statement(next_case_label));
    4359                 :       16686 : }
    4360                 :             : 
    4361                 :             : // Determine types.
    4362                 :             : 
    4363                 :             : void
    4364                 :       40214 : Case_clauses::Case_clause::determine_types(Gogo* gogo, Type* type)
    4365                 :             : {
    4366                 :       40214 :   if (this->cases_ != NULL)
    4367                 :             :     {
    4368                 :       34843 :       Type_context case_context(type, false);
    4369                 :       85934 :       for (Expression_list::iterator p = this->cases_->begin();
    4370                 :       85934 :            p != this->cases_->end();
    4371                 :       51091 :            ++p)
    4372                 :       51091 :         (*p)->determine_type(gogo, &case_context);
    4373                 :             :     }
    4374                 :       40214 :   if (this->statements_ != NULL)
    4375                 :       38955 :     this->statements_->determine_types(gogo);
    4376                 :       40214 : }
    4377                 :             : 
    4378                 :             : // Check types.  Returns false if there was an error.
    4379                 :             : 
    4380                 :             : bool
    4381                 :       40210 : Case_clauses::Case_clause::check_types(Type* type)
    4382                 :             : {
    4383                 :       40210 :   if (this->cases_ != NULL)
    4384                 :             :     {
    4385                 :       34841 :       for (Expression_list::iterator p = this->cases_->begin();
    4386                 :       85922 :            p != this->cases_->end();
    4387                 :       51081 :            ++p)
    4388                 :             :         {
    4389                 :       51089 :           std::string reason;
    4390                 :       51089 :           if (!Type::are_compatible_for_comparison(true, type, (*p)->type(),
    4391                 :             :                                                    &reason))
    4392                 :             :             {
    4393                 :           8 :               go_error_at(this->location_, "%s", reason.c_str());
    4394                 :           8 :               return false;
    4395                 :             :             }
    4396                 :       51089 :         }
    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                 :        4442 : Case_clauses::Case_clause::may_fall_through() const
    4407                 :             : {
    4408                 :        4442 :   if (this->statements_ == NULL)
    4409                 :             :     return true;
    4410                 :        4433 :   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                 :       23489 : 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                 :       23489 :   if (this->cases_ != NULL)
    4428                 :             :     {
    4429                 :       20803 :       go_assert(!this->is_default_);
    4430                 :       53967 :       for (Expression_list::const_iterator p = this->cases_->begin();
    4431                 :       53967 :            p != this->cases_->end();
    4432                 :       33164 :            ++p)
    4433                 :             :         {
    4434                 :       33164 :           Expression* e = *p;
    4435                 :       33164 :           if (e->classification() != Expression::EXPRESSION_INTEGER)
    4436                 :             :             {
    4437                 :       23741 :               Numeric_constant nc;
    4438                 :       23741 :               mpz_t ival;
    4439                 :       23741 :               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                 :           0 :                   go_assert(saw_errors());
    4444                 :           0 :                   continue;
    4445                 :             :                 }
    4446                 :       23741 :               go_assert(nc.type() != NULL);
    4447                 :       23741 :               e = Expression::make_integer_z(&ival, nc.type(), e->location());
    4448                 :       23741 :               mpz_clear(ival);
    4449                 :       23741 :             }
    4450                 :             : 
    4451                 :       33164 :           std::pair<Case_constants::iterator, bool> ins =
    4452                 :       33164 :             case_constants->insert(e);
    4453                 :       33164 :           if (!ins.second)
    4454                 :             :             {
    4455                 :             :               // Value was already present.
    4456                 :           3 :               go_error_at(this->location_, "duplicate case in switch");
    4457                 :           3 :               e = Expression::make_error(this->location_);
    4458                 :             :             }
    4459                 :       33164 :           cases->push_back(e->get_backend(context));
    4460                 :             :         }
    4461                 :             :     }
    4462                 :             : 
    4463                 :       23489 :   Bstatement* statements;
    4464                 :       23489 :   if (this->statements_ == NULL)
    4465                 :             :     statements = NULL;
    4466                 :             :   else
    4467                 :             :     {
    4468                 :       22967 :       Bblock* bblock = this->statements_->get_backend(context);
    4469                 :       22967 :       statements = context->backend()->block_statement(bblock);
    4470                 :             :     }
    4471                 :             : 
    4472                 :       23489 :   Bstatement* break_stat;
    4473                 :       23489 :   if (this->is_fallthrough_)
    4474                 :             :     break_stat = NULL;
    4475                 :             :   else
    4476                 :       23128 :     break_stat = break_label->get_goto(context, this->location_);
    4477                 :             : 
    4478                 :       23489 :   if (statements == NULL)
    4479                 :             :     return break_stat;
    4480                 :       22967 :   else if (break_stat == NULL)
    4481                 :             :     return statements;
    4482                 :             :   else
    4483                 :       22625 :     return context->backend()->compound_statement(statements, break_stat);
    4484                 :             : }
    4485                 :             : 
    4486                 :             : // Dump the AST representation for a case clause
    4487                 :             : 
    4488                 :             : void
    4489                 :           0 : Case_clauses::Case_clause::dump_clause(Ast_dump_context* ast_dump_context)
    4490                 :             :     const
    4491                 :             : {
    4492                 :           0 :   ast_dump_context->print_indent();
    4493                 :           0 :   if (this->is_default_)
    4494                 :             :     {
    4495                 :           0 :       ast_dump_context->ostream() << "default:";
    4496                 :             :     }
    4497                 :             :   else
    4498                 :             :     {
    4499                 :           0 :       ast_dump_context->ostream() << "case ";
    4500                 :           0 :       ast_dump_context->dump_expression_list(this->cases_);
    4501                 :           0 :       ast_dump_context->ostream() << ":" ;
    4502                 :             :     }
    4503                 :           0 :   ast_dump_context->dump_block(this->statements_);
    4504                 :           0 :   if (this->is_fallthrough_)
    4505                 :             :     {
    4506                 :           0 :       ast_dump_context->print_indent();
    4507                 :           0 :       ast_dump_context->ostream() <<  " (fallthrough)" << dsuffix(location()) << std::endl;
    4508                 :             :     }
    4509                 :           0 : }
    4510                 :             : 
    4511                 :             : // Class Case_clauses.
    4512                 :             : 
    4513                 :             : // Traversal.
    4514                 :             : 
    4515                 :             : int
    4516                 :      172198 : Case_clauses::traverse(Traverse* traverse)
    4517                 :             : {
    4518                 :      840902 :   for (Clauses::iterator p = this->clauses_.begin();
    4519                 :      840902 :        p != this->clauses_.end();
    4520                 :      668704 :        ++p)
    4521                 :             :     {
    4522                 :      668704 :       if (p->traverse(traverse) == TRAVERSE_EXIT)
    4523                 :      172198 :         return TRAVERSE_EXIT;
    4524                 :             :     }
    4525                 :             :   return TRAVERSE_CONTINUE;
    4526                 :             : }
    4527                 :             : 
    4528                 :             : // Check whether all the case expressions are constant.
    4529                 :             : 
    4530                 :             : bool
    4531                 :        5916 : Case_clauses::is_constant() const
    4532                 :             : {
    4533                 :       29428 :   for (Clauses::const_iterator p = this->clauses_.begin();
    4534                 :       29428 :        p != this->clauses_.end();
    4535                 :       23512 :        ++p)
    4536                 :       23577 :     if (!p->is_constant())
    4537                 :        5916 :       return false;
    4538                 :             :   return true;
    4539                 :             : }
    4540                 :             : 
    4541                 :             : // Lower case clauses for a nonconstant switch.
    4542                 :             : 
    4543                 :             : void
    4544                 :        5301 : Case_clauses::lower(Gogo* gogo, Block* b, Temporary_statement* val_temp,
    4545                 :             :                     Unnamed_label* break_label) const
    4546                 :             : {
    4547                 :             :   // The default case.
    4548                 :        5301 :   const Case_clause* default_case = NULL;
    4549                 :             : 
    4550                 :             :   // The label for the fallthrough of the previous case.
    4551                 :        5301 :   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                 :        5301 :   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                 :        5301 :   Unnamed_label* default_finish_label = NULL;
    4561                 :             : 
    4562                 :       21987 :   for (Clauses::const_iterator p = this->clauses_.begin();
    4563                 :       21987 :        p != this->clauses_.end();
    4564                 :       16686 :        ++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                 :       16686 :       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                 :       16686 :       Unnamed_label* finish_label = break_label;
    4573                 :             : 
    4574                 :       16686 :       last_fallthrough_label = NULL;
    4575                 :       16686 :       if (p->is_fallthrough() && p + 1 != this->clauses_.end())
    4576                 :             :         {
    4577                 :         115 :           finish_label = new Unnamed_label(p->location());
    4578                 :         115 :           last_fallthrough_label = finish_label;
    4579                 :             :         }
    4580                 :             : 
    4581                 :       16686 :       if (!p->is_default())
    4582                 :       14015 :         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                 :        5301 :   if (default_case != NULL)
    4594                 :        2671 :     default_case->lower(gogo, b, val_temp, default_start_label,
    4595                 :             :                         default_finish_label);
    4596                 :        5301 : }
    4597                 :             : 
    4598                 :             : // Determine types.
    4599                 :             : 
    4600                 :             : void
    4601                 :       11185 : Case_clauses::determine_types(Gogo* gogo, Type* type)
    4602                 :             : {
    4603                 :       51399 :   for (Clauses::iterator p = this->clauses_.begin();
    4604                 :       51399 :        p != this->clauses_.end();
    4605                 :       40214 :        ++p)
    4606                 :       40214 :     p->determine_types(gogo, type);
    4607                 :       11185 : }
    4608                 :             : 
    4609                 :             : // Check types.  Returns false if there was an error.
    4610                 :             : 
    4611                 :             : bool
    4612                 :       11182 : Case_clauses::check_types(Type* type)
    4613                 :             : {
    4614                 :       11182 :   bool ret = true;
    4615                 :       51392 :   for (Clauses::iterator p = this->clauses_.begin();
    4616                 :       51392 :        p != this->clauses_.end();
    4617                 :       40210 :        ++p)
    4618                 :             :     {
    4619                 :       40210 :       if (!p->check_types(type))
    4620                 :           8 :         ret = false;
    4621                 :             :     }
    4622                 :       11182 :   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                 :        1011 : Case_clauses::may_fall_through() const
    4630                 :             : {
    4631                 :        1011 :   bool found_default = false;
    4632                 :        5453 :   for (Clauses::const_iterator p = this->clauses_.begin();
    4633                 :        5453 :        p != this->clauses_.end();
    4634                 :        4442 :        ++p)
    4635                 :             :     {
    4636                 :        4442 :       if (p->may_fall_through() && !p->is_fallthrough())
    4637                 :        1011 :         return true;
    4638                 :        4442 :       if (p->is_default())
    4639                 :         987 :         found_default = true;
    4640                 :             :     }
    4641                 :        1011 :   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                 :        5840 : 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                 :        5840 :   Case_constants case_constants;
    4654                 :             : 
    4655                 :        5840 :   size_t c = this->clauses_.size();
    4656                 :        5840 :   all_cases->resize(c);
    4657                 :        5840 :   all_statements->resize(c);
    4658                 :             : 
    4659                 :        5840 :   size_t i = 0;
    4660                 :        5840 :   for (Clauses::const_iterator p = this->clauses_.begin();
    4661                 :       29329 :        p != this->clauses_.end();
    4662                 :       23489 :        ++p, ++i)
    4663                 :             :     {
    4664                 :       23489 :       std::vector<Bexpression*> cases;
    4665                 :       23489 :       Bstatement* stat = p->get_backend(context, break_label, &case_constants,
    4666                 :             :                                         &cases);
    4667                 :             :       // The final clause can't fall through.
    4668                 :       23489 :       if (i == c - 1 && p->is_fallthrough())
    4669                 :             :         {
    4670                 :           2 :           go_assert(saw_errors());
    4671                 :           2 :           stat = context->backend()->error_statement();
    4672                 :             :         }
    4673                 :       23489 :       (*all_cases)[i].swap(cases);
    4674                 :       23489 :       (*all_statements)[i] = stat;
    4675                 :       23489 :     }
    4676                 :        5840 : }
    4677                 :             : 
    4678                 :             : // Dump the AST representation for case clauses (from a switch statement)
    4679                 :             : 
    4680                 :             : void
    4681                 :           0 : Case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
    4682                 :             : {
    4683                 :           0 :   for (Clauses::const_iterator p = this->clauses_.begin();
    4684                 :           0 :        p != this->clauses_.end();
    4685                 :           0 :        ++p)
    4686                 :           0 :     p->dump_clause(ast_dump_context);
    4687                 :           0 : }
    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                 :        5851 :   Constant_switch_statement(Expression* val, Case_clauses* clauses,
    4696                 :             :                             Unnamed_label* break_label,
    4697                 :             :                             Location location)
    4698                 :        5851 :     : Statement(STATEMENT_CONSTANT_SWITCH, location),
    4699                 :       11702 :       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                 :      138161 : Constant_switch_statement::do_traverse(Traverse* traverse)
    4725                 :             : {
    4726                 :      138161 :   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
    4727                 :             :     return TRAVERSE_EXIT;
    4728                 :      116283 :   return this->clauses_->traverse(traverse);
    4729                 :             : }
    4730                 :             : 
    4731                 :             : // Convert to GENERIC.
    4732                 :             : 
    4733                 :             : Bstatement*
    4734                 :        5840 : Constant_switch_statement::do_get_backend(Translate_context* context)
    4735                 :             : {
    4736                 :        5840 :   Bexpression* switch_val_expr = this->val_->get_backend(context);
    4737                 :             : 
    4738                 :        5840 :   Unnamed_label* break_label = this->break_label_;
    4739                 :        5840 :   if (break_label == NULL)
    4740                 :        5497 :     break_label = new Unnamed_label(this->location());
    4741                 :             : 
    4742                 :        5840 :   std::vector<std::vector<Bexpression*> > all_cases;
    4743                 :        5840 :   std::vector<Bstatement*> all_statements;
    4744                 :        5840 :   this->clauses_->get_backend(context, break_label, &all_cases,
    4745                 :             :                               &all_statements);
    4746                 :             : 
    4747                 :        5840 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    4748                 :        5840 :   Bstatement* switch_statement;
    4749                 :        5840 :   switch_statement = context->backend()->switch_statement(bfunction,
    4750                 :             :                                                           switch_val_expr,
    4751                 :             :                                                           all_cases,
    4752                 :             :                                                           all_statements,
    4753                 :             :                                                           this->location());
    4754                 :        5840 :   Bstatement* ldef = break_label->get_definition(context);
    4755                 :        5840 :   return context->backend()->compound_statement(switch_statement, ldef);
    4756                 :        5840 : }
    4757                 :             : 
    4758                 :             : // Dump the AST representation for a constant switch statement.
    4759                 :             : 
    4760                 :             : void
    4761                 :           0 : Constant_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    4762                 :             :     const
    4763                 :             : {
    4764                 :           0 :   ast_dump_context->print_indent();
    4765                 :           0 :   ast_dump_context->ostream() << "switch ";
    4766                 :           0 :   ast_dump_context->dump_expression(this->val_);
    4767                 :             : 
    4768                 :           0 :   if (ast_dump_context->dump_subblocks())
    4769                 :             :     {
    4770                 :           0 :       ast_dump_context->ostream() << " {" << std::endl;
    4771                 :           0 :       this->clauses_->dump_clauses(ast_dump_context);
    4772                 :           0 :       ast_dump_context->ostream() << "}";
    4773                 :             :     }
    4774                 :             : 
    4775                 :           0 :    ast_dump_context->ostream() << std::endl;
    4776                 :           0 : }
    4777                 :             : 
    4778                 :             : // Class Switch_statement.
    4779                 :             : 
    4780                 :             : // Traversal.
    4781                 :             : 
    4782                 :             : int
    4783                 :       55915 : Switch_statement::do_traverse(Traverse* traverse)
    4784                 :             : {
    4785                 :       55915 :   if (this->val_ != NULL)
    4786                 :             :     {
    4787                 :       40790 :       if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
    4788                 :             :         return TRAVERSE_EXIT;
    4789                 :             :     }
    4790                 :       55915 :   return this->clauses_->traverse(traverse);
    4791                 :             : }
    4792                 :             : 
    4793                 :             : void
    4794                 :       11185 : Switch_statement::do_determine_types(Gogo* gogo)
    4795                 :             : {
    4796                 :       11185 :   if (this->val_ != NULL)
    4797                 :        8160 :     this->val_->determine_type_no_context(gogo);
    4798                 :       11185 :   this->clauses_->determine_types(gogo,
    4799                 :       11185 :                                   (this->val_ == NULL
    4800                 :             :                                    ? NULL
    4801                 :        8160 :                                    : this->val_->type()));
    4802                 :       11185 : }
    4803                 :             : 
    4804                 :             : void
    4805                 :       11185 : Switch_statement::do_check_types(Gogo*)
    4806                 :             : {
    4807                 :       11185 :   if (this->val_ != NULL
    4808                 :       11185 :       && (this->val_->is_error_expression()
    4809                 :        8160 :           || this->val_->type()->is_error()))
    4810                 :           1 :     return;
    4811                 :             : 
    4812                 :       11184 :   if (this->val_ != NULL
    4813                 :        8159 :       && !this->val_->type()->is_comparable()
    4814                 :       11195 :       && !Type::are_compatible_for_comparison(true, this->val_->type(),
    4815                 :          11 :                                               Type::make_nil_type(), NULL))
    4816                 :             :     {
    4817                 :           2 :       go_error_at(this->val_->location(),
    4818                 :             :                   "cannot switch on value whose type may not be compared");
    4819                 :           2 :       this->set_is_error();
    4820                 :           2 :       return;
    4821                 :             :     }
    4822                 :             : 
    4823                 :       11182 :   Type* type;
    4824                 :       11182 :   if (this->val_ != NULL)
    4825                 :        8157 :     type = this->val_->type();
    4826                 :             :   else
    4827                 :        3025 :     type = Type::make_boolean_type();
    4828                 :       11182 :   if (!this->clauses_->check_types(type))
    4829                 :           8 :     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                 :       11175 : Switch_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
    4837                 :             :                            Statement_inserter*)
    4838                 :             : {
    4839                 :       11175 :   Location loc = this->location();
    4840                 :             : 
    4841                 :       11175 :   if (this->val_ != NULL
    4842                 :       11175 :       && (this->val_->is_error_expression()
    4843                 :        8150 :           || this->val_->type()->is_error()))
    4844                 :             :     {
    4845                 :           1 :       go_assert(saw_errors());
    4846                 :           1 :       return Statement::make_error_statement(loc);
    4847                 :             :     }
    4848                 :             : 
    4849                 :       11174 :   if (this->val_ != NULL
    4850                 :        8149 :       && this->val_->type()->integer_type() != NULL
    4851                 :        5917 :       && !this->clauses_->empty()
    4852                 :       17090 :       && this->clauses_->is_constant())
    4853                 :        5851 :     return new Constant_switch_statement(this->val_, this->clauses_,
    4854                 :        5851 :                                          this->break_label_, loc);
    4855                 :             : 
    4856                 :        5323 :   Block* b = new Block(enclosing, loc);
    4857                 :             : 
    4858                 :        5323 :   if (this->clauses_->empty())
    4859                 :             :     {
    4860                 :          22 :       Expression* val = this->val_;
    4861                 :          22 :       if (val == NULL)
    4862                 :          13 :         val = Expression::make_boolean(true, loc);
    4863                 :          22 :       return Statement::make_statement(val, true);
    4864                 :             :     }
    4865                 :             : 
    4866                 :             :   // var val_temp VAL_TYPE = VAL
    4867                 :        5301 :   Expression* val = this->val_;
    4868                 :        5301 :   if (val == NULL)
    4869                 :        3012 :     val = Expression::make_boolean(true, loc);
    4870                 :             : 
    4871                 :        5301 :   Type* type = val->type();
    4872                 :        5301 :   if (type->is_abstract())
    4873                 :        3012 :     type = type->make_non_abstract_type();
    4874                 :        5301 :   Temporary_statement* val_temp = Statement::make_temporary(type, val, loc);
    4875                 :        5301 :   b->add_statement(val_temp);
    4876                 :             : 
    4877                 :        5301 :   this->clauses_->lower(gogo, b, val_temp, this->break_label());
    4878                 :             : 
    4879                 :        5301 :   Statement* s = Statement::make_unnamed_label_statement(this->break_label_);
    4880                 :        5301 :   b->add_statement(s);
    4881                 :             : 
    4882                 :        5301 :   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                 :        6269 : Switch_statement::break_label()
    4890                 :             : {
    4891                 :        6269 :   if (this->break_label_ == NULL)
    4892                 :        5644 :     this->break_label_ = new Unnamed_label(this->location());
    4893                 :        6269 :   return this->break_label_;
    4894                 :             : }
    4895                 :             : 
    4896                 :             : // Dump the AST representation for a switch statement.
    4897                 :             : 
    4898                 :             : void
    4899                 :           0 : Switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    4900                 :             : {
    4901                 :           0 :   ast_dump_context->print_indent();
    4902                 :           0 :   ast_dump_context->ostream() << "switch ";
    4903                 :           0 :   if (this->val_ != NULL)
    4904                 :             :     {
    4905                 :           0 :       ast_dump_context->dump_expression(this->val_);
    4906                 :             :     }
    4907                 :           0 :   if (ast_dump_context->dump_subblocks())
    4908                 :             :     {
    4909                 :           0 :       ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
    4910                 :           0 :       this->clauses_->dump_clauses(ast_dump_context);
    4911                 :           0 :       ast_dump_context->print_indent();
    4912                 :           0 :       ast_dump_context->ostream() << "}";
    4913                 :             :     }
    4914                 :           0 :   ast_dump_context->ostream() << std::endl;
    4915                 :           0 : }
    4916                 :             : 
    4917                 :             : // Return whether this switch may fall through.
    4918                 :             : 
    4919                 :             : bool
    4920                 :        1023 : Switch_statement::do_may_fall_through() const
    4921                 :             : {
    4922                 :        1023 :   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                 :        1023 :   if (this->break_label_ != NULL)
    4928                 :             :     return true;
    4929                 :             : 
    4930                 :        1011 :   return this->clauses_->may_fall_through();
    4931                 :             : }
    4932                 :             : 
    4933                 :             : // Make a switch statement.
    4934                 :             : 
    4935                 :             : Switch_statement*
    4936                 :       11186 : Statement::make_switch_statement(Expression* val, Location location)
    4937                 :             : {
    4938                 :       11186 :   return new Switch_statement(val, location);
    4939                 :             : }
    4940                 :             : 
    4941                 :             : // Class Type_case_clauses::Type_case_clause.
    4942                 :             : 
    4943                 :             : // Traversal.
    4944                 :             : 
    4945                 :             : int
    4946                 :       63273 : Type_case_clauses::Type_case_clause::traverse(Traverse* traverse)
    4947                 :             : {
    4948                 :       63273 :   if (!this->is_default_
    4949                 :       58007 :       && ((traverse->traverse_mask()
    4950                 :       58007 :            & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
    4951                 :      121280 :       && Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
    4952                 :             :     return TRAVERSE_EXIT;
    4953                 :       63273 :   if (this->statements_ != NULL)
    4954                 :       54592 :     return this->statements_->traverse(traverse);
    4955                 :             :   return TRAVERSE_CONTINUE;
    4956                 :             : }
    4957                 :             : 
    4958                 :             : void
    4959                 :       12656 : Type_case_clauses::Type_case_clause::determine_types(Gogo* gogo)
    4960                 :             : {
    4961                 :       12656 :   if (this->statements_ != NULL)
    4962                 :       10919 :     this->statements_->determine_types(gogo);
    4963                 :       12656 : }
    4964                 :             : 
    4965                 :             : bool
    4966                 :       12656 : Type_case_clauses::Type_case_clause::check_types(Type* switch_val_type)
    4967                 :             : {
    4968                 :       12656 :   if (!this->is_default_)
    4969                 :             :     {
    4970                 :       11602 :       Type* type = this->type_;
    4971                 :       11602 :       std::string reason;
    4972                 :       11602 :       if (switch_val_type->interface_type() != NULL
    4973                 :       11600 :           && !type->is_nil_constant_as_type()
    4974                 :       22697 :           && type->interface_type() == NULL
    4975                 :       11096 :           && !switch_val_type->interface_type()->implements_interface(type,
    4976                 :             :                                                                       &reason))
    4977                 :             :         {
    4978                 :           1 :           if (reason.empty())
    4979                 :           0 :             go_error_at(this->location_, "impossible type switch case");
    4980                 :             :           else
    4981                 :           1 :             go_error_at(this->location_, "impossible type switch case (%s)",
    4982                 :             :                         reason.c_str());
    4983                 :           1 :           return false;
    4984                 :             :         }
    4985                 :       11602 :     }
    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                 :       12649 : 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                 :       12649 :   Location loc = this->location_;
    5003                 :             : 
    5004                 :       12649 :   Unnamed_label* next_case_label = NULL;
    5005                 :       12649 :   if (!this->is_default_)
    5006                 :             :     {
    5007                 :       11599 :       Type* type = this->type_;
    5008                 :             : 
    5009                 :       11599 :       Expression* ref = Expression::make_temporary_reference(descriptor_temp,
    5010                 :             :                                                              loc);
    5011                 :             : 
    5012                 :       11599 :       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                 :       11599 :       if (type->is_nil_constant_as_type())
    5017                 :         227 :         cond = Expression::make_binary(OPERATOR_EQEQ, ref,
    5018                 :             :                                        Expression::make_nil(loc),
    5019                 :             :                                        loc);
    5020                 :       11372 :       else if (type->interface_type() == NULL)
    5021                 :             :         {
    5022                 :       11095 :           if (!gogo->need_eqtype())
    5023                 :       11095 :             cond = Expression::make_binary(OPERATOR_EQEQ, ref,
    5024                 :             :                                            Expression::make_type_descriptor(type, loc),
    5025                 :             :                                            loc);
    5026                 :             :           else
    5027                 :           0 :             cond = Runtime::make_call(gogo, Runtime::EQTYPE, loc, 2,
    5028                 :             :                                       Expression::make_type_descriptor(type, loc),
    5029                 :             :                                       ref);
    5030                 :             :         }
    5031                 :             :       else
    5032                 :         277 :         cond = Runtime::make_call(gogo, Runtime::IFACET2IP, loc, 2,
    5033                 :             :                                   Expression::make_type_descriptor(type, loc),
    5034                 :             :                                   ref);
    5035                 :             : 
    5036                 :       11599 :       Unnamed_label* dest;
    5037                 :       11599 :       if (!this->is_fallthrough_)
    5038                 :             :         {
    5039                 :             :           // if !COND { goto NEXT_CASE_LABEL }
    5040                 :       10321 :           next_case_label = new Unnamed_label(Linemap::unknown_location());
    5041                 :       10321 :           dest = next_case_label;
    5042                 :       10321 :           cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
    5043                 :             :         }
    5044                 :             :       else
    5045                 :             :         {
    5046                 :             :           // if COND { goto STMTS_LABEL }
    5047                 :        1278 :           go_assert(stmts_label != NULL);
    5048                 :        1278 :           if (*stmts_label == NULL)
    5049                 :         531 :             *stmts_label = new Unnamed_label(Linemap::unknown_location());
    5050                 :        1278 :           dest = *stmts_label;
    5051                 :             :         }
    5052                 :       11599 :       Block* then_block = new Block(b, loc);
    5053                 :       11599 :       Statement* s = Statement::make_goto_unnamed_statement(dest, loc);
    5054                 :       11599 :       then_block->add_statement(s);
    5055                 :       11599 :       s = Statement::make_if_statement(cond, then_block, NULL, loc);
    5056                 :       11599 :       s->determine_types(gogo);
    5057                 :       11599 :       b->add_statement(s);
    5058                 :             :     }
    5059                 :             : 
    5060                 :       12649 :   if (this->statements_ != NULL
    5061                 :        1733 :       || (!this->is_fallthrough_
    5062                 :         455 :           && stmts_label != NULL
    5063                 :         449 :           && *stmts_label != NULL))
    5064                 :             :     {
    5065                 :       10994 :       go_assert(!this->is_fallthrough_);
    5066                 :       10994 :       if (stmts_label != NULL && *stmts_label != NULL)
    5067                 :             :         {
    5068                 :         531 :           go_assert(!this->is_default_);
    5069                 :         531 :           if (this->statements_ != NULL)
    5070                 :         453 :             (*stmts_label)->set_location(this->statements_->start_location());
    5071                 :         531 :           Statement* s = Statement::make_unnamed_label_statement(*stmts_label);
    5072                 :         531 :           b->add_statement(s);
    5073                 :         531 :           *stmts_label = NULL;
    5074                 :             :         }
    5075                 :       10994 :       if (this->statements_ != NULL)
    5076                 :       10916 :         b->add_statement(Statement::make_block_statement(this->statements_,
    5077                 :             :                                                          loc));
    5078                 :             :     }
    5079                 :             : 
    5080                 :       12649 :   if (this->is_fallthrough_)
    5081                 :        1278 :     go_assert(next_case_label == NULL);
    5082                 :             :   else
    5083                 :             :     {
    5084                 :       11371 :       Location gloc = (this->statements_ == NULL
    5085                 :       11371 :                               ? loc
    5086                 :       11371 :                               : this->statements_->end_location());
    5087                 :       11371 :       b->add_statement(Statement::make_goto_unnamed_statement(break_label,
    5088                 :             :                                                               gloc));
    5089                 :       11371 :       if (next_case_label != NULL)
    5090                 :             :         {
    5091                 :       10321 :           Statement* s =
    5092                 :       10321 :             Statement::make_unnamed_label_statement(next_case_label);
    5093                 :       10321 :           b->add_statement(s);
    5094                 :             :         }
    5095                 :             :     }
    5096                 :       12649 : }
    5097                 :             : 
    5098                 :             : // Return true if this type clause may fall through to the statements
    5099                 :             : // following the switch.
    5100                 :             : 
    5101                 :             : bool
    5102                 :         984 : Type_case_clauses::Type_case_clause::may_fall_through() const
    5103                 :             : {
    5104                 :         984 :   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                 :         901 :   if (this->statements_ == NULL)
    5115                 :             :     return true;
    5116                 :         901 :   return this->statements_->may_fall_through();
    5117                 :             : }
    5118                 :             : 
    5119                 :             : // Dump the AST representation for a type case clause
    5120                 :             : 
    5121                 :             : void
    5122                 :           0 : Type_case_clauses::Type_case_clause::dump_clause(
    5123                 :             :     Ast_dump_context* ast_dump_context) const
    5124                 :             : {
    5125                 :           0 :   ast_dump_context->print_indent();
    5126                 :           0 :   if (this->is_default_)
    5127                 :             :     {
    5128                 :           0 :       ast_dump_context->ostream() << "default:";
    5129                 :             :     }
    5130                 :             :   else
    5131                 :             :     {
    5132                 :           0 :       ast_dump_context->ostream() << "case ";
    5133                 :           0 :       ast_dump_context->dump_type(this->type_);
    5134                 :           0 :       ast_dump_context->ostream() << ":" ;
    5135                 :             :     }
    5136                 :           0 :   ast_dump_context->dump_block(this->statements_);
    5137                 :           0 :   if (this->is_fallthrough_)
    5138                 :             :     {
    5139                 :           0 :       ast_dump_context->print_indent();
    5140                 :           0 :       ast_dump_context->ostream() <<  " (fallthrough)" << std::endl;
    5141                 :             :     }
    5142                 :           0 : }
    5143                 :             : 
    5144                 :             : // Class Type_case_clauses.
    5145                 :             : 
    5146                 :             : // Traversal.
    5147                 :             : 
    5148                 :             : int
    5149                 :       11958 : Type_case_clauses::traverse(Traverse* traverse)
    5150                 :             : {
    5151                 :       75231 :   for (Type_clauses::iterator p = this->clauses_.begin();
    5152                 :       75231 :        p != this->clauses_.end();
    5153                 :       63273 :        ++p)
    5154                 :             :     {
    5155                 :       63273 :       if (p->traverse(traverse) == TRAVERSE_EXIT)
    5156                 :       11958 :         return TRAVERSE_EXIT;
    5157                 :             :     }
    5158                 :             :   return TRAVERSE_CONTINUE;
    5159                 :             : }
    5160                 :             : 
    5161                 :             : void
    5162                 :        2393 : Type_case_clauses::determine_types(Gogo* gogo)
    5163                 :             : {
    5164                 :       15049 :   for (Type_clauses::iterator p = this->clauses_.begin();
    5165                 :       15049 :        p != this->clauses_.end();
    5166                 :       12656 :        ++p)
    5167                 :       12656 :     p->determine_types(gogo);
    5168                 :        2393 : }
    5169                 :             : 
    5170                 :             : bool
    5171                 :        2393 : Type_case_clauses::check_types(Type* switch_val_type)
    5172                 :             : {
    5173                 :        2393 :   bool ret = true;
    5174                 :       15049 :   for (Type_clauses::iterator p = this->clauses_.begin();
    5175                 :       15049 :        p != this->clauses_.end();
    5176                 :       12656 :        ++p)
    5177                 :             :     {
    5178                 :       12656 :       if (!p->check_types(switch_val_type))
    5179                 :           1 :         ret = false;
    5180                 :             :     }
    5181                 :        2393 :   return ret;
    5182                 :             : }
    5183                 :             : 
    5184                 :             : // Check for duplicate types.
    5185                 :             : 
    5186                 :             : void
    5187                 :        2393 : Type_case_clauses::check_duplicates() const
    5188                 :             : {
    5189                 :        2393 :   typedef Unordered_set_hash(const Type*, Type_hash_identical,
    5190                 :             :                              Type_identical) Types_seen;
    5191                 :        2393 :   Types_seen types_seen;
    5192                 :       15049 :   for (Type_clauses::const_iterator p = this->clauses_.begin();
    5193                 :       15049 :        p != this->clauses_.end();
    5194                 :       12656 :        ++p)
    5195                 :             :     {
    5196                 :       12656 :       Type* t = p->type();
    5197                 :       12656 :       if (t == NULL)
    5198                 :        1054 :         continue;
    5199                 :       11602 :       if (t->is_nil_constant_as_type())
    5200                 :         227 :         t = Type::make_nil_type();
    5201                 :       11602 :       std::pair<Types_seen::iterator, bool> ins = types_seen.insert(t);
    5202                 :       11602 :       if (!ins.second)
    5203                 :           6 :         go_error_at(p->location(), "duplicate type in switch");
    5204                 :             :     }
    5205                 :        2393 : }
    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                 :        2386 : Type_case_clauses::lower(Gogo* gogo, Block* b,
    5213                 :             :                          Temporary_statement* descriptor_temp,
    5214                 :             :                          Unnamed_label* break_label) const
    5215                 :             : {
    5216                 :        2386 :   const Type_case_clause* default_case = NULL;
    5217                 :             : 
    5218                 :        2386 :   Unnamed_label* stmts_label = NULL;
    5219                 :       15035 :   for (Type_clauses::const_iterator p = this->clauses_.begin();
    5220                 :       15035 :        p != this->clauses_.end();
    5221                 :       12649 :        ++p)
    5222                 :             :     {
    5223                 :       12649 :       if (!p->is_default())
    5224                 :       11599 :         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                 :        2386 :   go_assert(stmts_label == NULL);
    5233                 :             : 
    5234                 :        2386 :   if (default_case != NULL)
    5235                 :        1050 :     default_case->lower(gogo, b, descriptor_temp, break_label, NULL);
    5236                 :        2386 : }
    5237                 :             : 
    5238                 :             : // Return true if these clauses may fall through to the statements
    5239                 :             : // following the switch statement.
    5240                 :             : 
    5241                 :             : bool
    5242                 :         203 : Type_case_clauses::may_fall_through() const
    5243                 :             : {
    5244                 :         203 :   bool found_default = false;
    5245                 :        1187 :   for (Type_clauses::const_iterator p = this->clauses_.begin();
    5246                 :        1187 :        p != this->clauses_.end();
    5247                 :         984 :        ++p)
    5248                 :             :     {
    5249                 :         984 :       if (p->may_fall_through())
    5250                 :         203 :         return true;
    5251                 :         984 :       if (p->is_default())
    5252                 :         191 :         found_default = true;
    5253                 :             :     }
    5254                 :         203 :   return !found_default;
    5255                 :             : }
    5256                 :             : 
    5257                 :             : // Dump the AST representation for case clauses (from a switch statement)
    5258                 :             : 
    5259                 :             : void
    5260                 :           0 : Type_case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
    5261                 :             : {
    5262                 :           0 :   for (Type_clauses::const_iterator p = this->clauses_.begin();
    5263                 :           0 :        p != this->clauses_.end();
    5264                 :           0 :        ++p)
    5265                 :           0 :     p->dump_clause(ast_dump_context);
    5266                 :           0 : }
    5267                 :             : 
    5268                 :             : // Class Type_switch_statement.
    5269                 :             : 
    5270                 :             : // Traversal.
    5271                 :             : 
    5272                 :             : int
    5273                 :       11958 : Type_switch_statement::do_traverse(Traverse* traverse)
    5274                 :             : {
    5275                 :       11958 :   if (this->traverse_expression(traverse, &this->expr_) == TRAVERSE_EXIT)
    5276                 :             :     return TRAVERSE_EXIT;
    5277                 :       11958 :   if (this->clauses_ != NULL)
    5278                 :       11958 :     return this->clauses_->traverse(traverse);
    5279                 :             :   return TRAVERSE_CONTINUE;
    5280                 :             : }
    5281                 :             : 
    5282                 :             : void
    5283                 :        2393 : Type_switch_statement::do_determine_types(Gogo* gogo)
    5284                 :             : {
    5285                 :        2393 :   this->expr_->determine_type_no_context(gogo);
    5286                 :        2393 :   this->clauses_->determine_types(gogo);
    5287                 :        2393 : }
    5288                 :             : 
    5289                 :             : void
    5290                 :        2393 : Type_switch_statement::do_check_types(Gogo*)
    5291                 :             : {
    5292                 :        2393 :   if (this->clauses_ != NULL)
    5293                 :        2393 :     this->clauses_->check_duplicates();
    5294                 :             : 
    5295                 :        2393 :   Type* expr_type = this->expr_->type();
    5296                 :        2393 :   if (expr_type->interface_type() == NULL)
    5297                 :             :     {
    5298                 :           6 :       if (!expr_type->is_error())
    5299                 :           4 :         this->report_error(_("cannot type switch on non-interface value"));
    5300                 :           6 :       this->set_is_error();
    5301                 :             :     }
    5302                 :             : 
    5303                 :        2393 :   if (!this->clauses_->check_types(expr_type))
    5304                 :           1 :     this->set_is_error();
    5305                 :        2393 : }
    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                 :        2386 : Type_switch_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
    5315                 :             :                                 Statement_inserter*)
    5316                 :             : {
    5317                 :        2386 :   const Location loc = this->location();
    5318                 :             : 
    5319                 :        2386 :   if (this->classification() == STATEMENT_ERROR)
    5320                 :           0 :     return Statement::make_error_statement(loc);
    5321                 :             : 
    5322                 :        2386 :   Block* b = new Block(enclosing, loc);
    5323                 :             : 
    5324                 :        2386 :   Temporary_statement* val_temp =
    5325                 :        2386 :     Statement::make_temporary(NULL, this->expr_, loc);
    5326                 :        2386 :   b->add_statement(val_temp);
    5327                 :             : 
    5328                 :             :   // var descriptor_temp DESCRIPTOR_TYPE
    5329                 :        2386 :   Type* descriptor_type = Type::make_type_descriptor_ptr_type();
    5330                 :        2386 :   Temporary_statement* descriptor_temp =
    5331                 :        2386 :     Statement::make_temporary(descriptor_type, NULL, loc);
    5332                 :        2386 :   b->add_statement(descriptor_temp);
    5333                 :             : 
    5334                 :             :   // descriptor_temp = ifacetype(val_temp)
    5335                 :        2386 :   Expression* ref = Expression::make_temporary_reference(val_temp, loc);
    5336                 :        2386 :   Expression* td = Expression::get_interface_type_descriptor(ref);
    5337                 :        2386 :   Temporary_reference_expression* lhs =
    5338                 :        2386 :     Expression::make_temporary_reference(descriptor_temp, loc);
    5339                 :        2386 :   lhs->set_is_lvalue();
    5340                 :        2386 :   Statement* s = Statement::make_assignment(lhs, td, loc);
    5341                 :        2386 :   s->determine_types(gogo);
    5342                 :        2386 :   b->add_statement(s);
    5343                 :             : 
    5344                 :        2386 :   if (this->clauses_ != NULL)
    5345                 :        2386 :     this->clauses_->lower(gogo, b, descriptor_temp, this->break_label());
    5346                 :             : 
    5347                 :        2386 :   s = Statement::make_unnamed_label_statement(this->break_label_);
    5348                 :        2386 :   b->add_statement(s);
    5349                 :             : 
    5350                 :        2386 :   return Statement::make_block_statement(b, loc);
    5351                 :             : }
    5352                 :             : 
    5353                 :             : // Return whether this switch may fall through.
    5354                 :             : 
    5355                 :             : bool
    5356                 :         215 : Type_switch_statement::do_may_fall_through() const
    5357                 :             : {
    5358                 :         215 :   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                 :         215 :   if (this->break_label_ != NULL)
    5364                 :             :     return true;
    5365                 :             : 
    5366                 :         203 :   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                 :        2583 : Type_switch_statement::break_label()
    5374                 :             : {
    5375                 :        2583 :   if (this->break_label_ == NULL)
    5376                 :        2386 :     this->break_label_ = new Unnamed_label(this->location());
    5377                 :        2583 :   return this->break_label_;
    5378                 :             : }
    5379                 :             : 
    5380                 :             : // Dump the AST representation for a type switch statement
    5381                 :             : 
    5382                 :             : void
    5383                 :           0 : Type_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    5384                 :             :     const
    5385                 :             : {
    5386                 :           0 :   ast_dump_context->print_indent();
    5387                 :           0 :   ast_dump_context->ostream() << "switch ";
    5388                 :           0 :   ast_dump_context->dump_expression(this->expr_);
    5389                 :           0 :   ast_dump_context->ostream() << " .(type)";
    5390                 :           0 :   if (ast_dump_context->dump_subblocks())
    5391                 :             :     {
    5392                 :           0 :       ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
    5393                 :           0 :       this->clauses_->dump_clauses(ast_dump_context);
    5394                 :           0 :       ast_dump_context->ostream() << "}";
    5395                 :             :     }
    5396                 :           0 :   ast_dump_context->ostream() << std::endl;
    5397                 :           0 : }
    5398                 :             : 
    5399                 :             : // Make a type switch statement.
    5400                 :             : 
    5401                 :             : Type_switch_statement*
    5402                 :        2393 : Statement::make_type_switch_statement(Expression* expr, Location location)
    5403                 :             : {
    5404                 :        2393 :   return new Type_switch_statement(expr, location);
    5405                 :             : }
    5406                 :             : 
    5407                 :             : // Class Send_statement.
    5408                 :             : 
    5409                 :             : // Traversal.
    5410                 :             : 
    5411                 :             : int
    5412                 :       60890 : Send_statement::do_traverse(Traverse* traverse)
    5413                 :             : {
    5414                 :       60890 :   if (this->traverse_expression(traverse, &this->channel_) == TRAVERSE_EXIT)
    5415                 :             :     return TRAVERSE_EXIT;
    5416                 :       59936 :   return this->traverse_expression(traverse, &this->val_);
    5417                 :             : }
    5418                 :             : 
    5419                 :             : // Determine types.
    5420                 :             : 
    5421                 :             : void
    5422                 :        2676 : Send_statement::do_determine_types(Gogo* gogo)
    5423                 :             : {
    5424                 :        2676 :   this->channel_->determine_type_no_context(gogo);
    5425                 :        2676 :   Type* type = this->channel_->type();
    5426                 :        2676 :   Type_context context;
    5427                 :        2676 :   if (type->channel_type() != NULL)
    5428                 :        5348 :     context.type = type->channel_type()->element_type();
    5429                 :        2676 :   this->val_->determine_type(gogo, &context);
    5430                 :        2676 : }
    5431                 :             : 
    5432                 :             : // Check types.
    5433                 :             : 
    5434                 :             : void
    5435                 :        2594 : Send_statement::do_check_types(Gogo*)
    5436                 :             : {
    5437                 :        2594 :   Type* type = this->channel_->type();
    5438                 :        2594 :   if (type->is_error())
    5439                 :             :     {
    5440                 :           1 :       this->set_is_error();
    5441                 :           1 :       return;
    5442                 :             :     }
    5443                 :        2593 :   Channel_type* channel_type = type->channel_type();
    5444                 :        2593 :   if (channel_type == NULL)
    5445                 :             :     {
    5446                 :           1 :       go_error_at(this->location(), "left operand of %<<-%> must be channel");
    5447                 :           1 :       this->set_is_error();
    5448                 :           1 :       return;
    5449                 :             :     }
    5450                 :        2592 :   Type* element_type = channel_type->element_type();
    5451                 :        2592 :   if (!Type::are_assignable(element_type, this->val_->type(), NULL))
    5452                 :             :     {
    5453                 :           0 :       this->report_error(_("incompatible types in send"));
    5454                 :           0 :       return;
    5455                 :             :     }
    5456                 :        2592 :   if (!channel_type->may_send())
    5457                 :             :     {
    5458                 :           1 :       this->report_error(_("invalid send on receive-only channel"));
    5459                 :           1 :       return;
    5460                 :             :     }
    5461                 :             : }
    5462                 :             : 
    5463                 :             : // Flatten a send statement.  We may need a temporary for interface
    5464                 :             : // conversion.
    5465                 :             : 
    5466                 :             : Statement*
    5467                 :        2608 : Send_statement::do_flatten(Gogo*, Named_object*, Block*,
    5468                 :             :                            Statement_inserter* inserter)
    5469                 :             : {
    5470                 :        2608 :   if (this->channel_->is_error_expression()
    5471                 :        2608 :       || this->channel_->type()->is_error_type())
    5472                 :             :     {
    5473                 :           0 :       go_assert(saw_errors());
    5474                 :           0 :       return Statement::make_error_statement(this->location());
    5475                 :             :     }
    5476                 :             : 
    5477                 :        5216 :   Type* element_type = this->channel_->type()->channel_type()->element_type();
    5478                 :        2608 :   if (!Type::are_identical(element_type, this->val_->type(),
    5479                 :             :                            Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
    5480                 :             :                            NULL)
    5481                 :          18 :       && this->val_->type()->interface_type() != NULL
    5482                 :        2608 :       && !this->val_->is_multi_eval_safe())
    5483                 :             :     {
    5484                 :           0 :       Temporary_statement* temp =
    5485                 :           0 :         Statement::make_temporary(NULL, this->val_, this->location());
    5486                 :           0 :       inserter->insert(temp);
    5487                 :           0 :       this->val_ = Expression::make_temporary_reference(temp,
    5488                 :             :                                                         this->location());
    5489                 :             :     }
    5490                 :        2608 :   return this;
    5491                 :             : }
    5492                 :             : 
    5493                 :             : // Add explicit type conversions.
    5494                 :             : 
    5495                 :             : void
    5496                 :        2598 : Send_statement::do_add_conversions()
    5497                 :             : {
    5498                 :        5196 :   Type* lt = this->channel_->type()->channel_type()->element_type();
    5499                 :        2598 :   Type* rt = this->val_->type();
    5500                 :        2598 :   if (!Type::are_identical(lt, rt, 0, NULL)
    5501                 :        2598 :       && lt->interface_type() != NULL)
    5502                 :          97 :     this->val_ = Expression::make_cast(lt, this->val_, this->location());
    5503                 :        2598 : }
    5504                 :             : 
    5505                 :             : // Convert a send statement to the backend representation.
    5506                 :             : 
    5507                 :             : Bstatement*
    5508                 :        2597 : Send_statement::do_get_backend(Translate_context* context)
    5509                 :             : {
    5510                 :        2597 :   Gogo* gogo = context->gogo();
    5511                 :        2597 :   Location loc = this->location();
    5512                 :             : 
    5513                 :        2597 :   Channel_type* channel_type = this->channel_->type()->channel_type();
    5514                 :        2597 :   Type* element_type = channel_type->element_type();
    5515                 :        2597 :   Expression* val = Expression::convert_for_assignment(gogo,
    5516                 :             :                                                        element_type,
    5517                 :             :                                                        this->val_, loc);
    5518                 :             : 
    5519                 :        2597 :   bool can_take_address;
    5520                 :        2597 :   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                 :          15 :     case Type::TYPE_ARRAY:
    5540                 :          15 :       can_take_address = !element_type->is_slice_type();
    5541                 :          15 :       break;
    5542                 :             : 
    5543                 :           0 :     default:
    5544                 :           0 :     case Type::TYPE_ERROR:
    5545                 :           0 :     case Type::TYPE_VOID:
    5546                 :           0 :     case Type::TYPE_SINK:
    5547                 :           0 :     case Type::TYPE_NIL:
    5548                 :           0 :     case Type::TYPE_NAMED:
    5549                 :           0 :     case Type::TYPE_FORWARD:
    5550                 :           0 :       go_assert(saw_errors());
    5551                 :           0 :       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                 :          15 :   if (can_take_address
    5558                 :         320 :       && val->var_expression() == NULL
    5559                 :        2294 :       && val->temporary_reference_expression() == NULL)
    5560                 :             :     can_take_address = false;
    5561                 :             : 
    5562                 :        4818 :   Bstatement* btemp = NULL;
    5563                 :        2279 :   if (can_take_address)
    5564                 :             :     {
    5565                 :             :       // The function doesn't change the value, so just take its
    5566                 :             :       // address directly.
    5567                 :          58 :       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                 :        2539 :       Temporary_statement* temp = Statement::make_temporary(element_type,
    5576                 :             :                                                             val, loc);
    5577                 :        2539 :       Expression* ref = Expression::make_temporary_reference(temp, loc);
    5578                 :        2539 :       val = Expression::make_unary(OPERATOR_AND, ref, loc);
    5579                 :        2539 :       btemp = temp->get_backend(context);
    5580                 :             :     }
    5581                 :             : 
    5582                 :        2597 :   Expression* call = Runtime::make_call(gogo, Runtime::CHANSEND, loc, 2,
    5583                 :        2597 :                                         this->channel_, val);
    5584                 :        2597 :   call->determine_type_no_context(gogo);
    5585                 :        2597 :   gogo->lower_expression(context->function(), NULL, &call);
    5586                 :        2597 :   Bexpression* bcall = call->get_backend(context);
    5587                 :        2597 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    5588                 :        2597 :   Bstatement* s = context->backend()->expression_statement(bfunction, bcall);
    5589                 :             : 
    5590                 :        2597 :   if (btemp == NULL)
    5591                 :             :     return s;
    5592                 :             :   else
    5593                 :        2539 :     return context->backend()->compound_statement(btemp, s);
    5594                 :             : }
    5595                 :             : 
    5596                 :             : // Dump the AST representation for a send statement
    5597                 :             : 
    5598                 :             : void
    5599                 :           0 : Send_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    5600                 :             : {
    5601                 :           0 :   ast_dump_context->print_indent();
    5602                 :           0 :   ast_dump_context->dump_expression(this->channel_);
    5603                 :           0 :   ast_dump_context->ostream() << " <- ";
    5604                 :           0 :   ast_dump_context->dump_expression(this->val_);
    5605                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    5606                 :           0 : }
    5607                 :             : 
    5608                 :             : // Make a send statement.
    5609                 :             : 
    5610                 :             : Send_statement*
    5611                 :        2601 : Statement::make_send_statement(Expression* channel, Expression* val,
    5612                 :             :                                Location location)
    5613                 :             : {
    5614                 :        2601 :   return new Send_statement(channel, val, location);
    5615                 :             : }
    5616                 :             : 
    5617                 :             : // Class Select_clauses::Select_clause.
    5618                 :             : 
    5619                 :             : // Traversal.
    5620                 :             : 
    5621                 :             : int
    5622                 :      164626 : Select_clauses::Select_clause::traverse(Traverse* traverse)
    5623                 :             : {
    5624                 :      164626 :   if (!this->is_lowered_
    5625                 :      164626 :       && (traverse->traverse_mask()
    5626                 :       39950 :           & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
    5627                 :             :     {
    5628                 :       39950 :       if (this->channel_ != NULL)
    5629                 :             :         {
    5630                 :       32630 :           if (Expression::traverse(&this->channel_, traverse) == TRAVERSE_EXIT)
    5631                 :             :             return TRAVERSE_EXIT;
    5632                 :             :         }
    5633                 :       39950 :       if (this->val_ != NULL)
    5634                 :             :         {
    5635                 :       14765 :           if (Expression::traverse(&this->val_, traverse) == TRAVERSE_EXIT)
    5636                 :             :             return TRAVERSE_EXIT;
    5637                 :             :         }
    5638                 :       39950 :       if (this->closed_ != NULL)
    5639                 :             :         {
    5640                 :          45 :           if (Expression::traverse(&this->closed_, traverse) == TRAVERSE_EXIT)
    5641                 :             :             return TRAVERSE_EXIT;
    5642                 :             :         }
    5643                 :             :     }
    5644                 :      164626 :   if (this->statements_ != NULL)
    5645                 :             :     {
    5646                 :      164626 :       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                 :        6746 : Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
    5657                 :             :                                      Block* b, Temporary_statement* scases,
    5658                 :             :                                      int index, Temporary_statement* recvok)
    5659                 :             : {
    5660                 :        6746 :   Location loc = this->location_;
    5661                 :             : 
    5662                 :        6746 :   this->set_case_index(index);
    5663                 :             : 
    5664                 :        6746 :   if (this->is_default_)
    5665                 :             :     {
    5666                 :         867 :       go_assert(this->channel_ == NULL && this->val_ == NULL);
    5667                 :         867 :       this->is_lowered_ = true;
    5668                 :         867 :       return;
    5669                 :             :     }
    5670                 :             : 
    5671                 :        5879 :   Expression* scase = Expression::make_temporary_reference(scases, loc);
    5672                 :        5879 :   Expression* index_expr = Expression::make_integer_sl(index, NULL, loc);
    5673                 :        5879 :   scase = Expression::make_array_index(scase, index_expr, NULL, NULL, loc);
    5674                 :             : 
    5675                 :             :   // Evaluate the channel before the select statement.
    5676                 :        5879 :   Temporary_statement* channel_temp = Statement::make_temporary(NULL,
    5677                 :             :                                                                 this->channel_,
    5678                 :             :                                                                 loc);
    5679                 :        5879 :   b->add_statement(channel_temp);
    5680                 :        5879 :   Expression* chanref = Expression::make_temporary_reference(channel_temp,
    5681                 :             :                                                              loc);
    5682                 :             : 
    5683                 :        5879 :   if (this->is_send_)
    5684                 :        1374 :     this->lower_send(gogo, b, scase, chanref);
    5685                 :             :   else
    5686                 :        4505 :     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                 :        5879 :   this->is_lowered_ = true;
    5691                 :        5879 :   this->val_ = NULL;
    5692                 :             : }
    5693                 :             : 
    5694                 :             : // Lower a send clause in a select statement.
    5695                 :             : 
    5696                 :             : void
    5697                 :        1374 : Select_clauses::Select_clause::lower_send(Gogo* gogo, Block* b,
    5698                 :             :                                           Expression* scase,
    5699                 :             :                                           Expression* chanref)
    5700                 :             : {
    5701                 :        1374 :   Location loc = this->location_;
    5702                 :             : 
    5703                 :        1374 :   Channel_type* ct = this->channel_->type()->channel_type();
    5704                 :        1374 :   if (ct == NULL)
    5705                 :           0 :     return;
    5706                 :             : 
    5707                 :        1374 :   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                 :        1374 :   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                 :        1374 :   val->set_value_escapes();
    5719                 :        1374 :   b->add_statement(val);
    5720                 :             : 
    5721                 :        1374 :   Expression* valref = Expression::make_temporary_reference(val, loc);
    5722                 :        1374 :   Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
    5723                 :        1374 :   Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
    5724                 :        1374 :   valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);
    5725                 :             : 
    5726                 :        1374 :   this->set_case(gogo, b, scase, chanref, valaddr);
    5727                 :             : }
    5728                 :             : 
    5729                 :             : // Lower a receive clause in a select statement.
    5730                 :             : 
    5731                 :             : void
    5732                 :        4505 : 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                 :        4505 :   Location loc = this->location_;
    5738                 :             : 
    5739                 :        4505 :   Channel_type* ct = this->channel_->type()->channel_type();
    5740                 :        4505 :   if (ct == NULL)
    5741                 :           0 :     return;
    5742                 :             : 
    5743                 :        4505 :   Type* valtype = ct->element_type();
    5744                 :        4505 :   Temporary_statement* val = Statement::make_temporary(valtype, NULL, loc);
    5745                 :        4505 :   b->add_statement(val);
    5746                 :             : 
    5747                 :        4505 :   Expression* valref = Expression::make_temporary_reference(val, loc);
    5748                 :        4505 :   Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
    5749                 :        4505 :   Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
    5750                 :        4505 :   valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);
    5751                 :             : 
    5752                 :        4505 :   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                 :        4505 :   Block* init = NULL;
    5759                 :             : 
    5760                 :        4505 :   if (this->var_ != NULL)
    5761                 :             :     {
    5762                 :         460 :       go_assert(this->val_ == NULL);
    5763                 :         460 :       valref = Expression::make_temporary_reference(val, loc);
    5764                 :         460 :       this->var_->var_value()->set_init(valref);
    5765                 :         460 :       this->var_->var_value()->clear_type_from_chan_element();
    5766                 :             :     }
    5767                 :        4045 :   else if (this->val_ != NULL && !this->val_->is_sink_expression())
    5768                 :             :     {
    5769                 :        1415 :       init = new Block(b, loc);
    5770                 :        1415 :       valref = Expression::make_temporary_reference(val, loc);
    5771                 :        1415 :       Statement* s = Statement::make_assignment(this->val_, valref, loc);
    5772                 :        1415 :       s->determine_types(gogo);
    5773                 :        1415 :       init->add_statement(s);
    5774                 :             :     }
    5775                 :             : 
    5776                 :        4505 :   if (this->closedvar_ != NULL)
    5777                 :             :     {
    5778                 :          28 :       go_assert(this->closed_ == NULL);
    5779                 :          28 :       Expression* cref = Expression::make_temporary_reference(recvok, loc);
    5780                 :          28 :       this->closedvar_->var_value()->set_init(cref);
    5781                 :             :     }
    5782                 :        4477 :   else if (this->closed_ != NULL && !this->closed_->is_sink_expression())
    5783                 :             :     {
    5784                 :           7 :       if (init == NULL)
    5785                 :           0 :         init = new Block(b, loc);
    5786                 :           7 :       Expression* cref = Expression::make_temporary_reference(recvok, loc);
    5787                 :           7 :       Statement* s = Statement::make_assignment(this->closed_, cref, loc);
    5788                 :           7 :       s->determine_types(gogo);
    5789                 :           7 :       init->add_statement(s);
    5790                 :             :     }
    5791                 :             : 
    5792                 :        4505 :   if (init != NULL)
    5793                 :             :     {
    5794                 :        1415 :       gogo->lower_block(function, init);
    5795                 :             : 
    5796                 :        1415 :       if (this->statements_ != NULL)
    5797                 :        1415 :         init->add_statement(Statement::make_block_statement(this->statements_,
    5798                 :             :                                                             loc));
    5799                 :        1415 :       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                 :        5879 : Select_clauses::Select_clause::set_case(Gogo* gogo,
    5808                 :             :                                         Block* b,
    5809                 :             :                                         Expression* scase,
    5810                 :             :                                         Expression* chanref,
    5811                 :             :                                         Expression* elem)
    5812                 :             : {
    5813                 :        5879 :   Location loc = this->location_;
    5814                 :        5879 :   Struct_type* scase_type = scase->type()->struct_type();
    5815                 :             : 
    5816                 :        5879 :   int field_index = 0;
    5817                 :       11758 :   go_assert(scase_type->field(field_index)->is_field_name("c"));
    5818                 :        5879 :   Expression* ref = Expression::make_field_reference(scase, field_index, loc);
    5819                 :        5879 :   Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
    5820                 :        5879 :   chanref = Expression::make_unsafe_cast(unsafe_pointer_type, chanref, loc);
    5821                 :        5879 :   Statement* s = Statement::make_assignment(ref, chanref, loc);
    5822                 :        5879 :   s->determine_types(gogo);
    5823                 :        5879 :   b->add_statement(s);
    5824                 :             : 
    5825                 :        5879 :   if (elem != NULL)
    5826                 :             :     {
    5827                 :        5879 :       field_index = 1;
    5828                 :       11758 :       go_assert(scase_type->field(field_index)->is_field_name("elem"));
    5829                 :        5879 :       ref = Expression::make_field_reference(scase->copy(), field_index, loc);
    5830                 :        5879 :       s = Statement::make_assignment(ref, elem, loc);
    5831                 :        5879 :       s->determine_types(gogo);
    5832                 :        5879 :       b->add_statement(s);
    5833                 :             :     }
    5834                 :        5879 : }
    5835                 :             : 
    5836                 :             : // Determine types.
    5837                 :             : 
    5838                 :             : void
    5839                 :        8070 : Select_clauses::Select_clause::determine_types(Gogo* gogo)
    5840                 :             : {
    5841                 :        8070 :   if (this->channel_ != NULL)
    5842                 :        6604 :     this->channel_->determine_type_no_context(gogo);
    5843                 :        8070 :   if (this->val_ != NULL)
    5844                 :        2953 :     this->val_->determine_type_no_context(gogo);
    5845                 :        8070 :   if (this->closed_ != NULL)
    5846                 :           9 :     this->closed_->determine_type_no_context(gogo);
    5847                 :        8070 :   if (this->var_ != NULL && this->var_->is_variable())
    5848                 :         538 :     this->var_->var_value()->determine_type(gogo);
    5849                 :        8070 :   if (this->closedvar_ != NULL && this->closedvar_->is_variable())
    5850                 :          41 :     this->closedvar_->var_value()->determine_type(gogo);
    5851                 :        8070 :   if (this->statements_ != NULL)
    5852                 :        8070 :     this->statements_->determine_types(gogo);
    5853                 :        8070 : }
    5854                 :             : 
    5855                 :             : // Check types.
    5856                 :             : 
    5857                 :             : void
    5858                 :        7990 : Select_clauses::Select_clause::check_types()
    5859                 :             : {
    5860                 :        7990 :   if (this->is_default_)
    5861                 :             :     return;
    5862                 :             : 
    5863                 :        6526 :   Channel_type* ct = this->channel_->type()->channel_type();
    5864                 :        6526 :   if (ct == NULL)
    5865                 :             :     {
    5866                 :           0 :       go_error_at(this->channel_->location(), "expected channel");
    5867                 :           0 :       return;
    5868                 :             :     }
    5869                 :             : 
    5870                 :        6526 :   if (this->is_send_ && !ct->may_send())
    5871                 :           1 :     go_error_at(this->location(), "invalid send on receive-only channel");
    5872                 :        6525 :   else if (!this->is_send_ && !ct->may_receive())
    5873                 :           1 :     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                 :         406 : Select_clauses::Select_clause::may_fall_through() const
    5881                 :             : {
    5882                 :         406 :   if (this->statements_ == NULL)
    5883                 :             :     return true;
    5884                 :         406 :   return this->statements_->may_fall_through();
    5885                 :             : }
    5886                 :             : 
    5887                 :             : // Return the backend representation for the statements to execute.
    5888                 :             : 
    5889                 :             : Bstatement*
    5890                 :        6734 : Select_clauses::Select_clause::get_statements_backend(
    5891                 :             :     Translate_context* context)
    5892                 :             : {
    5893                 :        6734 :   if (this->statements_ == NULL)
    5894                 :             :     return NULL;
    5895                 :        6734 :   Bblock* bblock = this->statements_->get_backend(context);
    5896                 :        6734 :   return context->backend()->block_statement(bblock);
    5897                 :             : }
    5898                 :             : 
    5899                 :             : // Dump the AST representation for a select case clause
    5900                 :             : 
    5901                 :             : void
    5902                 :           0 : Select_clauses::Select_clause::dump_clause(
    5903                 :             :     Ast_dump_context* ast_dump_context) const
    5904                 :             : {
    5905                 :           0 :   ast_dump_context->print_indent();
    5906                 :           0 :   if (this->is_default_)
    5907                 :             :     {
    5908                 :           0 :       ast_dump_context->ostream() << "default:";
    5909                 :             :     }
    5910                 :             :   else
    5911                 :             :     {
    5912                 :           0 :       ast_dump_context->ostream() << "case "  ;
    5913                 :           0 :       if (this->is_send_)
    5914                 :             :         {
    5915                 :           0 :           ast_dump_context->dump_expression(this->channel_);
    5916                 :           0 :           ast_dump_context->ostream() << " <- " ;
    5917                 :           0 :           if (this->val_ != NULL)
    5918                 :           0 :             ast_dump_context->dump_expression(this->val_);
    5919                 :             :         }
    5920                 :             :       else
    5921                 :             :         {
    5922                 :           0 :           if (this->val_ != NULL)
    5923                 :           0 :             ast_dump_context->dump_expression(this->val_);
    5924                 :           0 :           if (this->closed_ != NULL)
    5925                 :             :             {
    5926                 :             :               // FIXME: can val_ == NULL and closed_ ! = NULL?
    5927                 :           0 :               ast_dump_context->ostream() << " , " ;
    5928                 :           0 :               ast_dump_context->dump_expression(this->closed_);
    5929                 :             :             }
    5930                 :           0 :           if (this->closedvar_ != NULL || this->var_ != NULL)
    5931                 :           0 :             ast_dump_context->ostream() << " := " ;
    5932                 :             : 
    5933                 :           0 :           ast_dump_context->ostream() << " <- " ;
    5934                 :           0 :           ast_dump_context->dump_expression(this->channel_);
    5935                 :             :         }
    5936                 :           0 :       ast_dump_context->ostream() << ":" ;
    5937                 :             :     }
    5938                 :           0 :   ast_dump_context->dump_block(this->statements_);
    5939                 :           0 : }
    5940                 :             : 
    5941                 :             : // Class Select_clauses.
    5942                 :             : 
    5943                 :             : // Whether there is a default case.
    5944                 :             : 
    5945                 :             : bool
    5946                 :        2656 : Select_clauses::has_default() const
    5947                 :             : {
    5948                 :        7202 :   for (Clauses::const_iterator p = this->clauses_.begin();
    5949                 :        7202 :        p != this->clauses_.end();
    5950                 :        4546 :        ++p)
    5951                 :        6010 :     if (p->is_default())
    5952                 :        2656 :       return true;
    5953                 :             :   return false;
    5954                 :             : }
    5955                 :             : 
    5956                 :             : // Traversal.
    5957                 :             : 
    5958                 :             : int
    5959                 :       49708 : Select_clauses::traverse(Traverse* traverse)
    5960                 :             : {
    5961                 :      214334 :   for (Clauses::iterator p = this->clauses_.begin();
    5962                 :      214334 :        p != this->clauses_.end();
    5963                 :      164626 :        ++p)
    5964                 :             :     {
    5965                 :      164626 :       if (p->traverse(traverse) == TRAVERSE_EXIT)
    5966                 :       49708 :         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                 :        1951 : 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                 :        1951 :   int send_count = 0;
    5983                 :        1951 :   int recv_count = 0;
    5984                 :        1951 :   bool has_default = false;
    5985                 :        8697 :   for (Clauses::iterator p = this->clauses_.begin();
    5986                 :        8697 :        p != this->clauses_.end();
    5987                 :        6746 :        ++p)
    5988                 :             :     {
    5989                 :        6746 :       if (p->is_default())
    5990                 :             :         has_default = true;
    5991                 :        5879 :       else if (p->is_send())
    5992                 :        1374 :         ++send_count;
    5993                 :             :       else
    5994                 :        4505 :         ++recv_count;
    5995                 :             :     }
    5996                 :             : 
    5997                 :        1951 :   *p_send_count = send_count;
    5998                 :        1951 :   *p_recv_count = recv_count;
    5999                 :             : 
    6000                 :        1951 :   int send_index = 0;
    6001                 :        1951 :   int recv_index = send_count;
    6002                 :        8697 :   for (Clauses::iterator p = this->clauses_.begin();
    6003                 :        8697 :        p != this->clauses_.end();
    6004                 :        6746 :        ++p)
    6005                 :             :     {
    6006                 :        6746 :       int index;
    6007                 :        6746 :       if (p->is_default())
    6008                 :             :         index = -1;
    6009                 :        5879 :       else if (p->is_send())
    6010                 :             :         {
    6011                 :        1374 :           index = send_index;
    6012                 :        1374 :           ++send_index;
    6013                 :             :         }
    6014                 :             :       else
    6015                 :             :         {
    6016                 :        4505 :           index = recv_index;
    6017                 :        4505 :           ++recv_index;
    6018                 :             :         }
    6019                 :             : 
    6020                 :        6746 :       p->lower(gogo, function, b, scases, index, recvok);
    6021                 :             :     }
    6022                 :             : 
    6023                 :        1951 :   go_assert(send_index == send_count);
    6024                 :        1951 :   go_assert(recv_index == send_count + recv_count);
    6025                 :        3035 :   go_assert(static_cast<size_t>(recv_index + (has_default ? 1 : 0))
    6026                 :             :             == this->size());
    6027                 :        1951 : }
    6028                 :             : 
    6029                 :             : // Determine types.
    6030                 :             : 
    6031                 :             : void
    6032                 :        2695 : Select_clauses::determine_types(Gogo* gogo)
    6033                 :             : {
    6034                 :       10765 :   for (Clauses::iterator p = this->clauses_.begin();
    6035                 :       10765 :        p != this->clauses_.end();
    6036                 :        8070 :        ++p)
    6037                 :        8070 :     p->determine_types(gogo);
    6038                 :        2695 : }
    6039                 :             : 
    6040                 :             : // Check types.
    6041                 :             : 
    6042                 :             : void
    6043                 :        2656 : Select_clauses::check_types()
    6044                 :             : {
    6045                 :       10646 :   for (Clauses::iterator p = this->clauses_.begin();
    6046                 :       10646 :        p != this->clauses_.end();
    6047                 :        7990 :        ++p)
    6048                 :        7990 :     p->check_types();
    6049                 :        2656 : }
    6050                 :             : 
    6051                 :             : // Return whether these select clauses fall through to the statement
    6052                 :             : // following the overall select statement.
    6053                 :             : 
    6054                 :             : bool
    6055                 :         194 : Select_clauses::may_fall_through() const
    6056                 :             : {
    6057                 :         588 :   for (Clauses::const_iterator p = this->clauses_.begin();
    6058                 :         588 :        p != this->clauses_.end();
    6059                 :         394 :        ++p)
    6060                 :         406 :     if (p->may_fall_through())
    6061                 :         194 :       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                 :        1945 : Select_clauses::get_backend(Translate_context* context,
    6071                 :             :                             Temporary_statement* index,
    6072                 :             :                             Unnamed_label *break_label,
    6073                 :             :                             Location location)
    6074                 :             : {
    6075                 :        1945 :   size_t count = this->clauses_.size();
    6076                 :        1945 :   std::vector<std::vector<Bexpression*> > cases(count + 1);
    6077                 :        1945 :   std::vector<Bstatement*> clauses(count + 1);
    6078                 :             : 
    6079                 :        1945 :   Type* int_type = Type::lookup_integer_type("int");
    6080                 :             : 
    6081                 :        1945 :   int i = 0;
    6082                 :        1945 :   for (Clauses::iterator p = this->clauses_.begin();
    6083                 :        8679 :        p != this->clauses_.end();
    6084                 :        6734 :        ++p, ++i)
    6085                 :             :     {
    6086                 :        6734 :       Expression* index_expr = Expression::make_integer_sl(p->case_index(),
    6087                 :             :                                                            int_type,
    6088                 :             :                                                            location);
    6089                 :        6734 :       cases[i].push_back(index_expr->get_backend(context));
    6090                 :             : 
    6091                 :        6734 :       Bstatement* s = p->get_statements_backend(context);
    6092                 :        6734 :       Location gloc = (p->statements() == NULL
    6093                 :        6734 :                        ? p->location()
    6094                 :        6734 :                        : p->statements()->end_location());
    6095                 :        6734 :       Bstatement* g = break_label->get_goto(context, gloc);
    6096                 :             : 
    6097                 :        6734 :       if (s == NULL)
    6098                 :           0 :         clauses[i] = g;
    6099                 :             :       else
    6100                 :        6734 :         clauses[i] = context->backend()->compound_statement(s, g);
    6101                 :             :     }
    6102                 :             : 
    6103                 :        1945 :   Expression* ref = Expression::make_temporary_reference(index, location);
    6104                 :        1945 :   Bexpression* bindex = ref->get_backend(context);
    6105                 :             : 
    6106                 :        1945 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    6107                 :             : 
    6108                 :        1945 :   if (count == 0)
    6109                 :           0 :     return context->backend()->expression_statement(bfunction, bindex);
    6110                 :             : 
    6111                 :        1945 :   Gogo* gogo = context->gogo();
    6112                 :        1945 :   Expression* crash = Runtime::make_call(gogo, Runtime::UNREACHABLE,
    6113                 :             :                                          location, 0);
    6114                 :        1945 :   crash->determine_type_no_context(gogo);
    6115                 :        1945 :   Bexpression* bcrash = crash->get_backend(context);
    6116                 :        1945 :   clauses[count] = context->backend()->expression_statement(bfunction, bcrash);
    6117                 :             : 
    6118                 :        1945 :   std::vector<Bstatement*> statements;
    6119                 :        1945 :   statements.reserve(2);
    6120                 :             : 
    6121                 :        1945 :   Bstatement* switch_stmt = context->backend()->switch_statement(bfunction,
    6122                 :             :                                                                  bindex,
    6123                 :             :                                                                  cases,
    6124                 :             :                                                                  clauses,
    6125                 :        1945 :                                                                  location);
    6126                 :        1945 :   statements.push_back(switch_stmt);
    6127                 :             : 
    6128                 :        1945 :   Bstatement* ldef = break_label->get_definition(context);
    6129                 :        1945 :   statements.push_back(ldef);
    6130                 :             : 
    6131                 :        1945 :   return context->backend()->statement_list(statements);
    6132                 :        1945 : }
    6133                 :             : 
    6134                 :             : // Dump the AST representation for select clauses.
    6135                 :             : 
    6136                 :             : void
    6137                 :           0 : Select_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
    6138                 :             : {
    6139                 :           0 :   for (Clauses::const_iterator p = this->clauses_.begin();
    6140                 :           0 :        p != this->clauses_.end();
    6141                 :           0 :        ++p)
    6142                 :           0 :     p->dump_clause(ast_dump_context);
    6143                 :           0 : }
    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                 :        2671 : Select_statement::break_label()
    6152                 :             : {
    6153                 :        2671 :   if (this->break_label_ == NULL)
    6154                 :        2607 :     this->break_label_ = new Unnamed_label(this->location());
    6155                 :        2671 :   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                 :        5033 : Select_statement::do_lower(Gogo* gogo, Named_object* function,
    6165                 :             :                            Block* enclosing, Statement_inserter*)
    6166                 :             : {
    6167                 :        5033 :   if (this->is_lowered_)
    6168                 :        2377 :     return this;
    6169                 :             : 
    6170                 :        2656 :   Location loc = this->location();
    6171                 :             : 
    6172                 :        2656 :   Block* b = new Block(enclosing, loc);
    6173                 :             : 
    6174                 :        2656 :   int ncases = this->clauses_->size();
    6175                 :        2656 :   bool has_default = this->clauses_->has_default();
    6176                 :             : 
    6177                 :             :   // Zero-case select.  Just block the execution.
    6178                 :        2656 :   if (ncases == 0)
    6179                 :             :     {
    6180                 :          45 :       Expression* call = Runtime::make_call(gogo, Runtime::BLOCK, loc, 0);
    6181                 :          45 :       Statement *s = Statement::make_statement(call, false);
    6182                 :          45 :       s->determine_types(gogo);
    6183                 :          45 :       b->add_statement(s);
    6184                 :          45 :       this->is_lowered_ = true;
    6185                 :          45 :       return Statement::make_block_statement(b, loc);
    6186                 :             :     }
    6187                 :             : 
    6188                 :             :   // One-case select.  It is mostly just to run the case.
    6189                 :        2611 :   if (ncases == 1)
    6190                 :          76 :     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                 :        2535 :   if (ncases == 2 && has_default)
    6195                 :         584 :     return this->lower_two_case(gogo, b);
    6196                 :             : 
    6197                 :             :   // We don't allocate an entry in scases for the default case.
    6198                 :        1951 :   if (has_default)
    6199                 :         867 :     --ncases;
    6200                 :             : 
    6201                 :        1951 :   Type* scase_type = Channel_type::select_case_type();
    6202                 :        1951 :   Expression* ncases_expr =
    6203                 :        1951 :     Expression::make_integer_ul(ncases, NULL,
    6204                 :             :                                 Linemap::predeclared_location());
    6205                 :        1951 :   Array_type* scases_type = Type::make_array_type(scase_type, ncases_expr);
    6206                 :        1951 :   scases_type->set_is_array_incomparable();
    6207                 :             : 
    6208                 :        1951 :   Temporary_statement* scases = Statement::make_temporary(scases_type, NULL,
    6209                 :             :                                                           loc);
    6210                 :        1951 :   b->add_statement(scases);
    6211                 :             : 
    6212                 :        1951 :   Expression* ncases2_expr =
    6213                 :        1951 :     Expression::make_integer_ul(ncases * 2, NULL,
    6214                 :             :                                 Linemap::predeclared_location());
    6215                 :        1951 :   Type* uint16_type = Type::lookup_integer_type("uint16");
    6216                 :        1951 :   Array_type* order_type = Type::make_array_type(uint16_type, ncases2_expr);
    6217                 :        1951 :   order_type->set_is_array_incomparable();
    6218                 :             : 
    6219                 :        1951 :   Temporary_statement* order = Statement::make_temporary(order_type, NULL,
    6220                 :             :                                                          loc);
    6221                 :        1951 :   b->add_statement(order);
    6222                 :             : 
    6223                 :        1951 :   Type* int_type = Type::lookup_integer_type("int");
    6224                 :        1951 :   this->index_ = Statement::make_temporary(int_type, NULL, loc);
    6225                 :        1951 :   b->add_statement(this->index_);
    6226                 :             : 
    6227                 :        1951 :   Type* bool_type = Type::lookup_bool_type();
    6228                 :        1951 :   Temporary_statement* recvok = Statement::make_temporary(bool_type, NULL,
    6229                 :             :                                                           loc);
    6230                 :        1951 :   b->add_statement(recvok);
    6231                 :             : 
    6232                 :             :   // Initialize the scases array.
    6233                 :        1951 :   int send_count;
    6234                 :        1951 :   int recv_count;
    6235                 :        1951 :   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                 :        1951 :   Expression* scases_ref = Expression::make_temporary_reference(scases, loc);
    6242                 :        1951 :   scases_ref = Expression::make_unary(OPERATOR_AND, scases_ref, loc);
    6243                 :        1951 :   Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
    6244                 :        1951 :   scases_ref = Expression::make_cast(unsafe_pointer_type, scases_ref, loc);
    6245                 :             : 
    6246                 :        1951 :   Expression* order_ref = Expression::make_temporary_reference(order, loc);
    6247                 :        1951 :   order_ref = Expression::make_unary(OPERATOR_AND, order_ref, loc);
    6248                 :        1951 :   order_ref = Expression::make_cast(unsafe_pointer_type, order_ref, loc);
    6249                 :             : 
    6250                 :        1951 :   Expression* send_count_expr = Expression::make_integer_sl(send_count,
    6251                 :             :                                                             int_type,
    6252                 :             :                                                             loc);
    6253                 :        1951 :   Expression* recv_count_expr = Expression::make_integer_sl(recv_count,
    6254                 :             :                                                             int_type,
    6255                 :             :                                                             loc);
    6256                 :        1951 :   Expression* block_expr = Expression::make_boolean(!has_default, loc);
    6257                 :             : 
    6258                 :        1951 :   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                 :        1951 :   Expression* result = Expression::make_call_result(call, 0);
    6264                 :        1951 :   Expression* ref = Expression::make_temporary_reference(this->index_, loc);
    6265                 :        1951 :   Statement* s = Statement::make_assignment(ref, result, loc);
    6266                 :        1951 :   s->determine_types(gogo);
    6267                 :        1951 :   b->add_statement(s);
    6268                 :             : 
    6269                 :        1951 :   result = Expression::make_call_result(call, 1);
    6270                 :        1951 :   ref = Expression::make_temporary_reference(recvok, loc);
    6271                 :        1951 :   s = Statement::make_assignment(ref, result, loc);
    6272                 :        1951 :   s->determine_types(gogo);
    6273                 :        1951 :   b->add_statement(s);
    6274                 :             : 
    6275                 :        1951 :   this->is_lowered_ = true;
    6276                 :        1951 :   b->add_statement(this);
    6277                 :             : 
    6278                 :        1951 :   return Statement::make_block_statement(b, loc);
    6279                 :             : }
    6280                 :             : 
    6281                 :             : // Lower a one-case select statement.
    6282                 :             : 
    6283                 :             : Statement*
    6284                 :          76 : Select_statement::lower_one_case(Gogo* gogo, Block* b)
    6285                 :             : {
    6286                 :          76 :   Select_clauses::Select_clause& scase = this->clauses_->at(0);
    6287                 :          76 :   Location loc = this->location();
    6288                 :          76 :   Expression* chan = scase.channel();
    6289                 :          76 :   if (chan != NULL)
    6290                 :             :     {
    6291                 :             :       // Lower this to
    6292                 :             :       //   if chan == nil { block() }; send/recv; body
    6293                 :          63 :       Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc);
    6294                 :          63 :       b->add_statement(chantmp);
    6295                 :          63 :       Expression* chanref = Expression::make_temporary_reference(chantmp, loc);
    6296                 :             : 
    6297                 :          63 :       Expression* nil = Expression::make_nil(loc);
    6298                 :          63 :       Expression* cond = Expression::make_binary(OPERATOR_EQEQ, chanref, nil, loc);
    6299                 :          63 :       Block* bnil = new Block(b, loc);
    6300                 :          63 :       Expression* call = Runtime::make_call(gogo, Runtime::BLOCK, loc, 0);
    6301                 :          63 :       Statement* s = Statement::make_statement(call, false);
    6302                 :          63 :       s->determine_types(gogo);
    6303                 :          63 :       bnil->add_statement(s);
    6304                 :          63 :       Statement* ifs = Statement::make_if_statement(cond, bnil, NULL, loc);
    6305                 :          63 :       ifs->determine_types(gogo);
    6306                 :          63 :       b->add_statement(ifs);
    6307                 :             : 
    6308                 :          63 :       chanref = chanref->copy();
    6309                 :          63 :       Location cloc = scase.location();
    6310                 :          63 :       if (scase.is_send())
    6311                 :             :         {
    6312                 :           7 :           s = Statement::make_send_statement(chanref, scase.val(), cloc);
    6313                 :           7 :           s->determine_types(gogo);
    6314                 :           7 :           b->add_statement(s);
    6315                 :             :         }
    6316                 :             :       else
    6317                 :             :         {
    6318                 :          56 :           if (scase.closed() == NULL && scase.closedvar() == NULL)
    6319                 :             :             {
    6320                 :             :               // Simple receive.
    6321                 :          51 :               Expression* recv = Expression::make_receive(chanref, cloc);
    6322                 :          51 :               if (scase.val() != NULL)
    6323                 :           9 :                 s = Statement::make_assignment(scase.val(), recv, cloc);
    6324                 :          42 :               else if (scase.var() != NULL)
    6325                 :             :                 {
    6326                 :           7 :                   Temporary_statement *ts =
    6327                 :           7 :                     Statement::make_temporary(NULL, recv, cloc);
    6328                 :           7 :                   Expression* ref =
    6329                 :           7 :                     Expression::make_temporary_reference(ts, cloc);
    6330                 :           7 :                   s = ts;
    6331                 :           7 :                   scase.var()->var_value()->set_init(ref);
    6332                 :           7 :                   scase.var()->var_value()->clear_type_from_chan_element();
    6333                 :             :                 }
    6334                 :             :               else
    6335                 :          35 :                 s = Statement::make_statement(recv, false);
    6336                 :          51 :               s->determine_types(gogo);
    6337                 :          51 :               b->add_statement(s);
    6338                 :             :             }
    6339                 :             :           else
    6340                 :             :             {
    6341                 :             :               // Tuple receive.
    6342                 :           5 :               Expression* lhs;
    6343                 :           5 :               if (scase.val() != NULL)
    6344                 :             :                 lhs = scase.val();
    6345                 :             :               else
    6346                 :             :                 {
    6347                 :           8 :                   Type* valtype = chan->type()->channel_type()->element_type();
    6348                 :           4 :                   Temporary_statement *ts =
    6349                 :           4 :                     Statement::make_temporary(valtype, NULL, cloc);
    6350                 :           4 :                   lhs = Expression::make_temporary_reference(ts, cloc);
    6351                 :           4 :                   b->add_statement(ts);
    6352                 :             :                 }
    6353                 :             : 
    6354                 :           5 :               Expression* lhs2;
    6355                 :           5 :               if (scase.closed() != NULL)
    6356                 :             :                 lhs2 = scase.closed();
    6357                 :             :               else
    6358                 :             :                 {
    6359                 :           4 :                   Type* booltype = Type::make_boolean_type();
    6360                 :           4 :                   Temporary_statement *ts =
    6361                 :           4 :                     Statement::make_temporary(booltype, NULL, cloc);
    6362                 :           4 :                   lhs2 = Expression::make_temporary_reference(ts, cloc);
    6363                 :           4 :                   b->add_statement(ts);
    6364                 :             :                 }
    6365                 :             : 
    6366                 :           5 :               s = Statement::make_tuple_receive_assignment(lhs, lhs2, chanref, cloc);
    6367                 :           5 :               s->determine_types(gogo);
    6368                 :           5 :               b->add_statement(s);
    6369                 :             : 
    6370                 :           5 :               if (scase.var() != NULL)
    6371                 :             :                 {
    6372                 :           3 :                   scase.var()->var_value()->set_init(lhs->copy());
    6373                 :           3 :                   scase.var()->var_value()->clear_type_from_chan_element();
    6374                 :             :                 }
    6375                 :             : 
    6376                 :           5 :               if (scase.closedvar() != NULL)
    6377                 :           4 :                 scase.closedvar()->var_value()->set_init(lhs2->copy());
    6378                 :             :             }
    6379                 :             :         }
    6380                 :             :     }
    6381                 :             : 
    6382                 :          76 :   Statement* bs =
    6383                 :          76 :     Statement::make_block_statement(scase.statements(), scase.location());
    6384                 :          76 :   b->add_statement(bs);
    6385                 :             : 
    6386                 :          76 :   Statement* label =
    6387                 :          76 :     Statement::make_unnamed_label_statement(this->break_label());
    6388                 :          76 :   b->add_statement(label);
    6389                 :             : 
    6390                 :          76 :   this->is_lowered_ = true;
    6391                 :          76 :   return Statement::make_block_statement(b, loc);
    6392                 :             : }
    6393                 :             : 
    6394                 :             : // Lower a two-case select statement with one default case.
    6395                 :             : 
    6396                 :             : Statement*
    6397                 :         584 : Select_statement::lower_two_case(Gogo* gogo, Block* b)
    6398                 :             : {
    6399                 :         584 :   Select_clauses::Select_clause& chancase =
    6400                 :         584 :     (this->clauses_->at(0).is_default()
    6401                 :         584 :      ? this->clauses_->at(1)
    6402                 :         495 :      : this->clauses_->at(0));
    6403                 :         584 :   Select_clauses::Select_clause& defcase =
    6404                 :         584 :     (this->clauses_->at(0).is_default()
    6405                 :         584 :      ? this->clauses_->at(0)
    6406                 :         495 :      : this->clauses_->at(1));
    6407                 :         584 :   Location loc = this->location();
    6408                 :         584 :   Expression* chan = chancase.channel();
    6409                 :        1168 :   Type* valtype = chan->type()->channel_type()->element_type();
    6410                 :             : 
    6411                 :         584 :   Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc);
    6412                 :         584 :   b->add_statement(chantmp);
    6413                 :         584 :   Expression* chanref = Expression::make_temporary_reference(chantmp, loc);
    6414                 :             : 
    6415                 :         584 :   Block* bchan;
    6416                 :         584 :   Expression* cond;
    6417                 :         584 :   if (chancase.is_send())
    6418                 :             :     {
    6419                 :             :       // if selectnbsend(chan, &val) { body } else { default body }
    6420                 :             : 
    6421                 :          99 :       Temporary_statement* ts =
    6422                 :          99 :         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                 :          99 :       ts->set_value_escapes();
    6426                 :          99 :       b->add_statement(ts);
    6427                 :             : 
    6428                 :          99 :       Expression* ref = Expression::make_temporary_reference(ts, loc);
    6429                 :          99 :       Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
    6430                 :          99 :       cond = Runtime::make_call(gogo, Runtime::SELECTNBSEND, loc, 2,
    6431                 :             :                                 chanref, addr);
    6432                 :          99 :       bchan = chancase.statements();
    6433                 :             :     }
    6434                 :             :   else
    6435                 :             :     {
    6436                 :         485 :       Temporary_statement* ts = Statement::make_temporary(valtype, NULL, loc);
    6437                 :         485 :       b->add_statement(ts);
    6438                 :             : 
    6439                 :         485 :       Expression* ref = Expression::make_temporary_reference(ts, loc);
    6440                 :         485 :       Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
    6441                 :             : 
    6442                 :             :       // selected, ok = selectnbrecv(&lhs, chan)
    6443                 :         485 :       Call_expression* call = Runtime::make_call(gogo, Runtime::SELECTNBRECV,
    6444                 :             :                                                  loc, 2, addr, chanref);
    6445                 :             : 
    6446                 :         485 :       Temporary_statement* selected_temp =
    6447                 :         485 :         Statement::make_temporary(Type::make_boolean_type(),
    6448                 :             :                                   Expression::make_call_result(call, 0),
    6449                 :             :                                   loc);
    6450                 :         485 :       selected_temp->determine_types(gogo);
    6451                 :         485 :       b->add_statement(selected_temp);
    6452                 :             : 
    6453                 :         485 :       Temporary_statement* ok_temp =
    6454                 :         485 :         Statement::make_temporary(Type::make_boolean_type(),
    6455                 :             :                                   Expression::make_call_result(call, 1),
    6456                 :             :                                   loc);
    6457                 :         485 :       ok_temp->determine_types(gogo);
    6458                 :         485 :       b->add_statement(ok_temp);
    6459                 :             : 
    6460                 :         485 :       cond = Expression::make_temporary_reference(selected_temp, loc);
    6461                 :             : 
    6462                 :         485 :       Location cloc = chancase.location();
    6463                 :         485 :       bchan = new Block(b, loc);
    6464                 :         485 :       if (chancase.val() != NULL && !chancase.val()->is_sink_expression())
    6465                 :             :         {
    6466                 :          43 :           Statement* as = Statement::make_assignment(chancase.val(),
    6467                 :             :                                                      ref->copy(),
    6468                 :             :                                                      cloc);
    6469                 :          43 :           as->determine_types(gogo);
    6470                 :          43 :           bchan->add_statement(as);
    6471                 :             :         }
    6472                 :         442 :       else if (chancase.var() != NULL)
    6473                 :             :         {
    6474                 :          54 :           chancase.var()->var_value()->set_init(ref->copy());
    6475                 :          54 :           chancase.var()->var_value()->clear_type_from_chan_element();
    6476                 :             :         }
    6477                 :             : 
    6478                 :         485 :       if (chancase.closed() != NULL && !chancase.closed()->is_sink_expression())
    6479                 :             :         {
    6480                 :           1 :           Expression* okref = Expression::make_temporary_reference(ok_temp,
    6481                 :             :                                                                    cloc);
    6482                 :           1 :           Statement* as = Statement::make_assignment(chancase.closed(),
    6483                 :             :                                                      okref, cloc);
    6484                 :           1 :           as->determine_types(gogo);
    6485                 :           1 :           bchan->add_statement(as);
    6486                 :             :         }
    6487                 :         484 :       else if (chancase.closedvar() != NULL)
    6488                 :             :         {
    6489                 :           9 :           Expression* okref = Expression::make_temporary_reference(ok_temp,
    6490                 :             :                                                                    cloc);
    6491                 :           9 :           chancase.closedvar()->var_value()->set_init(okref);
    6492                 :             :         }
    6493                 :             : 
    6494                 :         485 :       Statement* bs = Statement::make_block_statement(chancase.statements(),
    6495                 :             :                                                       cloc);
    6496                 :         485 :       bchan->add_statement(bs);
    6497                 :             :     }
    6498                 :             : 
    6499                 :         584 :   Statement* ifs =
    6500                 :         584 :     Statement::make_if_statement(cond, bchan, defcase.statements(), loc);
    6501                 :         584 :   ifs->determine_types(gogo);
    6502                 :         584 :   b->add_statement(ifs);
    6503                 :             : 
    6504                 :         584 :   Statement* label =
    6505                 :         584 :     Statement::make_unnamed_label_statement(this->break_label());
    6506                 :         584 :   b->add_statement(label);
    6507                 :             : 
    6508                 :         584 :   this->is_lowered_ = true;
    6509                 :         584 :   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                 :         214 : 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                 :         214 :   if (this->break_label_ != NULL)
    6521                 :             :     return true;
    6522                 :         194 :   return this->clauses_->may_fall_through();
    6523                 :             : }
    6524                 :             : 
    6525                 :             : // Return the backend representation for a select statement.
    6526                 :             : 
    6527                 :             : Bstatement*
    6528                 :        1945 : Select_statement::do_get_backend(Translate_context* context)
    6529                 :             : {
    6530                 :        1945 :   return this->clauses_->get_backend(context, this->index_,
    6531                 :        1945 :                                      this->break_label(), this->location());
    6532                 :             : }
    6533                 :             : 
    6534                 :             : // Dump the AST representation for a select statement.
    6535                 :             : 
    6536                 :             : void
    6537                 :           0 : Select_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    6538                 :             : {
    6539                 :           0 :   ast_dump_context->print_indent();
    6540                 :           0 :   ast_dump_context->ostream() << "select";
    6541                 :           0 :   if (ast_dump_context->dump_subblocks())
    6542                 :             :     {
    6543                 :           0 :       ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
    6544                 :           0 :       this->clauses_->dump_clauses(ast_dump_context);
    6545                 :           0 :       ast_dump_context->print_indent();
    6546                 :           0 :       ast_dump_context->ostream() << "}";
    6547                 :             :     }
    6548                 :           0 :   ast_dump_context->ostream() << std::endl;
    6549                 :           0 : }
    6550                 :             : 
    6551                 :             : // Make a select statement.
    6552                 :             : 
    6553                 :             : Select_statement*
    6554                 :        2656 : Statement::make_select_statement(Location location)
    6555                 :             : {
    6556                 :        2656 :   return new Select_statement(location);
    6557                 :             : }
    6558                 :             : 
    6559                 :             : // Class For_statement.
    6560                 :             : 
    6561                 :             : // Traversal.
    6562                 :             : 
    6563                 :             : int
    6564                 :      174482 : For_statement::do_traverse(Traverse* traverse)
    6565                 :             : {
    6566                 :      174482 :   if (this->init_ != NULL)
    6567                 :             :     {
    6568                 :       34013 :       if (this->init_->traverse(traverse) == TRAVERSE_EXIT)
    6569                 :             :         return TRAVERSE_EXIT;
    6570                 :             :     }
    6571                 :      174482 :   if (this->cond_ != NULL)
    6572                 :             :     {
    6573                 :      155516 :       if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT)
    6574                 :             :         return TRAVERSE_EXIT;
    6575                 :             :     }
    6576                 :      174482 :   if (this->post_ != NULL)
    6577                 :             :     {
    6578                 :      123247 :       if (this->post_->traverse(traverse) == TRAVERSE_EXIT)
    6579                 :             :         return TRAVERSE_EXIT;
    6580                 :             :     }
    6581                 :      174482 :   return this->statements_->traverse(traverse);
    6582                 :             : }
    6583                 :             : 
    6584                 :             : void
    6585                 :       62188 : For_statement::do_determine_types(Gogo* gogo)
    6586                 :             : {
    6587                 :       62188 :   if (this->init_ != NULL)
    6588                 :       34013 :     this->init_->determine_types(gogo);
    6589                 :       62188 :   if (this->cond_ != NULL)
    6590                 :       58314 :     this->cond_->determine_type_no_context(gogo);
    6591                 :       62188 :   if (this->post_ != NULL)
    6592                 :       51860 :     this->post_->determine_types(gogo);
    6593                 :       62188 :   this->statements_->determine_types(gogo);
    6594                 :       62188 : }
    6595                 :             : 
    6596                 :             : void
    6597                 :       28074 : For_statement::do_check_types(Gogo*)
    6598                 :             : {
    6599                 :       28074 :   if (this->cond_ != NULL)
    6600                 :             :     {
    6601                 :       24301 :       Type* type = this->cond_->type();
    6602                 :       24301 :       if (type->is_error())
    6603                 :           1 :         this->set_is_error();
    6604                 :       24300 :       else if (!type->is_boolean_type())
    6605                 :             :         {
    6606                 :           1 :           go_error_at(this->cond_->location(), "expected boolean expression");
    6607                 :           1 :           this->set_is_error();
    6608                 :             :         }
    6609                 :             :     }
    6610                 :       28074 : }
    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                 :       62186 : For_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
    6617                 :             :                         Statement_inserter*)
    6618                 :             : {
    6619                 :       62186 :   Location loc = this->location();
    6620                 :             : 
    6621                 :       62186 :   if (this->classification() == STATEMENT_ERROR)
    6622                 :           0 :     return Statement::make_error_statement(loc);
    6623                 :             : 
    6624                 :       62186 :   Statement* s;
    6625                 :       62186 :   Block* b = new Block(enclosing, this->location());
    6626                 :       62186 :   if (this->init_ != NULL)
    6627                 :             :     {
    6628                 :       68026 :       s = Statement::make_block_statement(this->init_,
    6629                 :       34013 :                                           this->init_->start_location());
    6630                 :       34013 :       b->add_statement(s);
    6631                 :             :     }
    6632                 :             : 
    6633                 :       62186 :   Unnamed_label* entry = NULL;
    6634                 :       62186 :   if (this->cond_ != NULL)
    6635                 :             :     {
    6636                 :       58312 :       entry = new Unnamed_label(this->location());
    6637                 :       58312 :       b->add_statement(Statement::make_goto_unnamed_statement(entry, loc));
    6638                 :             :     }
    6639                 :             : 
    6640                 :       62186 :   Unnamed_label* top = new Unnamed_label(this->location());
    6641                 :       62186 :   top->set_derived_from(this);
    6642                 :       62186 :   b->add_statement(Statement::make_unnamed_label_statement(top));
    6643                 :             : 
    6644                 :      124372 :   s = Statement::make_block_statement(this->statements_,
    6645                 :       62186 :                                       this->statements_->start_location());
    6646                 :       62186 :   b->add_statement(s);
    6647                 :             : 
    6648                 :       62186 :   Location end_loc = this->statements_->end_location();
    6649                 :             : 
    6650                 :       62186 :   Unnamed_label* cont = this->continue_label_;
    6651                 :       62186 :   if (cont != NULL)
    6652                 :        6370 :     b->add_statement(Statement::make_unnamed_label_statement(cont));
    6653                 :             : 
    6654                 :       62186 :   if (this->post_ != NULL)
    6655                 :             :     {
    6656                 :      103718 :       s = Statement::make_block_statement(this->post_,
    6657                 :       51859 :                                           this->post_->start_location());
    6658                 :       51859 :       b->add_statement(s);
    6659                 :       51859 :       end_loc = this->post_->end_location();
    6660                 :             :     }
    6661                 :             : 
    6662                 :       62186 :   if (this->cond_ == NULL)
    6663                 :        3874 :     b->add_statement(Statement::make_goto_unnamed_statement(top, end_loc));
    6664                 :             :   else
    6665                 :             :     {
    6666                 :       58312 :       b->add_statement(Statement::make_unnamed_label_statement(entry));
    6667                 :             : 
    6668                 :       58312 :       Location cond_loc = this->cond_->location();
    6669                 :       58312 :       Block* then_block = new Block(b, cond_loc);
    6670                 :       58312 :       s = Statement::make_goto_unnamed_statement(top, cond_loc);
    6671                 :       58312 :       then_block->add_statement(s);
    6672                 :             : 
    6673                 :       58312 :       s = Statement::make_if_statement(this->cond_, then_block, NULL, cond_loc);
    6674                 :       58312 :       s->determine_types(gogo);
    6675                 :       58312 :       b->add_statement(s);
    6676                 :             :     }
    6677                 :             : 
    6678                 :       62186 :   Unnamed_label* brk = this->break_label_;
    6679                 :       62186 :   if (brk != NULL)
    6680                 :        5600 :     b->add_statement(Statement::make_unnamed_label_statement(brk));
    6681                 :             : 
    6682                 :       62186 :   b->set_end_location(end_loc);
    6683                 :             : 
    6684                 :       62186 :   Statement* bs = Statement::make_block_statement(b, loc);
    6685                 :       62186 :   bs->block_statement()->set_is_lowered_for_statement();
    6686                 :       62186 :   return bs;
    6687                 :             : }
    6688                 :             : 
    6689                 :             : // Return the break label, creating it if necessary.
    6690                 :             : 
    6691                 :             : Unnamed_label*
    6692                 :        5391 : For_statement::break_label()
    6693                 :             : {
    6694                 :        5391 :   if (this->break_label_ == NULL)
    6695                 :        4186 :     this->break_label_ = new Unnamed_label(this->location());
    6696                 :        5391 :   return this->break_label_;
    6697                 :             : }
    6698                 :             : 
    6699                 :             : // Return the continue LABEL_EXPR.
    6700                 :             : 
    6701                 :             : Unnamed_label*
    6702                 :        4887 : For_statement::continue_label()
    6703                 :             : {
    6704                 :        4887 :   if (this->continue_label_ == NULL)
    6705                 :        2807 :     this->continue_label_ = new Unnamed_label(this->location());
    6706                 :        4887 :   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                 :       34114 : For_statement::set_break_continue_labels(Unnamed_label* break_label,
    6714                 :             :                                          Unnamed_label* continue_label)
    6715                 :             : {
    6716                 :       34114 :   go_assert(this->break_label_ == NULL && this->continue_label_ == NULL);
    6717                 :       34114 :   this->break_label_ = break_label;
    6718                 :       34114 :   this->continue_label_ = continue_label;
    6719                 :       34114 : }
    6720                 :             : 
    6721                 :             : // Whether the overall statement may fall through.
    6722                 :             : 
    6723                 :             : bool
    6724                 :        1095 : 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                 :        1095 :   if(this->cond_ != NULL)
    6729                 :             :     return true;
    6730                 :        1071 :   if(this->break_label_ != NULL)
    6731                 :          12 :     return true;
    6732                 :             :   return false;
    6733                 :             : }
    6734                 :             : 
    6735                 :             : // Dump the AST representation for a for statement.
    6736                 :             : 
    6737                 :             : void
    6738                 :           0 : For_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    6739                 :             : {
    6740                 :           0 :   if (this->init_ != NULL && ast_dump_context->dump_subblocks())
    6741                 :             :     {
    6742                 :           0 :       ast_dump_context->print_indent();
    6743                 :           0 :       ast_dump_context->indent();
    6744                 :           0 :       ast_dump_context->ostream() << "// INIT  " << std::endl;
    6745                 :           0 :       ast_dump_context->dump_block(this->init_);
    6746                 :           0 :       ast_dump_context->unindent();
    6747                 :             :     }
    6748                 :           0 :   ast_dump_context->print_indent();
    6749                 :           0 :   ast_dump_context->ostream() << "for ";
    6750                 :           0 :   if (this->cond_ != NULL)
    6751                 :           0 :     ast_dump_context->dump_expression(this->cond_);
    6752                 :             : 
    6753                 :           0 :   if (ast_dump_context->dump_subblocks())
    6754                 :             :     {
    6755                 :           0 :       ast_dump_context->ostream() << " {" << std::endl;
    6756                 :           0 :       ast_dump_context->dump_block(this->statements_);
    6757                 :           0 :       if (this->init_ != NULL)
    6758                 :             :         {
    6759                 :           0 :           ast_dump_context->print_indent();
    6760                 :           0 :           ast_dump_context->ostream() << "// POST " << std::endl;
    6761                 :           0 :           ast_dump_context->dump_block(this->post_);
    6762                 :             :         }
    6763                 :           0 :       ast_dump_context->unindent();
    6764                 :             : 
    6765                 :           0 :       ast_dump_context->print_indent();
    6766                 :           0 :       ast_dump_context->ostream() << "}";
    6767                 :             :     }
    6768                 :             : 
    6769                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    6770                 :           0 : }
    6771                 :             : 
    6772                 :             : // Make a for statement.
    6773                 :             : 
    6774                 :             : For_statement*
    6775                 :       62188 : Statement::make_for_statement(Block* init, Expression* cond, Block* post,
    6776                 :             :                               Location location)
    6777                 :             : {
    6778                 :       62188 :   return new For_statement(init, cond, post, location);
    6779                 :             : }
    6780                 :             : 
    6781                 :             : // Class For_range_statement.
    6782                 :             : 
    6783                 :             : // Traversal.
    6784                 :             : 
    6785                 :             : int
    6786                 :      137404 : For_range_statement::do_traverse(Traverse* traverse)
    6787                 :             : {
    6788                 :      137404 :   if (this->index_var_ != NULL)
    6789                 :             :     {
    6790                 :      136950 :       if (this->traverse_expression(traverse, &this->index_var_)
    6791                 :             :           == TRAVERSE_EXIT)
    6792                 :             :         return TRAVERSE_EXIT;
    6793                 :             :     }
    6794                 :      137404 :   if (this->value_var_ != NULL)
    6795                 :             :     {
    6796                 :      111400 :       if (this->traverse_expression(traverse, &this->value_var_)
    6797                 :             :           == TRAVERSE_EXIT)
    6798                 :             :         return TRAVERSE_EXIT;
    6799                 :             :     }
    6800                 :      137404 :   if (this->traverse_expression(traverse, &this->range_) == TRAVERSE_EXIT)
    6801                 :             :     return TRAVERSE_EXIT;
    6802                 :      137404 :   return this->statements_->traverse(traverse);
    6803                 :             : }
    6804                 :             : 
    6805                 :             : void
    6806                 :       43116 : For_range_statement::do_determine_types(Gogo* gogo)
    6807                 :             : {
    6808                 :       43116 :   if (this->index_var_ != NULL)
    6809                 :       43025 :     this->index_var_->determine_type_no_context(gogo);
    6810                 :       43116 :   if (this->value_var_ != NULL)
    6811                 :       22280 :     this->value_var_->determine_type_no_context(gogo);
    6812                 :       43116 :   this->range_->determine_type_no_context(gogo);
    6813                 :       43116 :   this->statements_->determine_types(gogo);
    6814                 :       43116 : }
    6815                 :             : 
    6816                 :             : void
    6817                 :       25744 : For_range_statement::do_check_types(Gogo*)
    6818                 :             : {
    6819                 :       25744 :   Type* range_type = this->range_->type();
    6820                 :             : 
    6821                 :       25744 :   Type* index_type;
    6822                 :       25744 :   Type* value_type = NULL;
    6823                 :             : 
    6824                 :       25744 :   if (range_type->points_to() != NULL
    6825                 :         207 :       && range_type->points_to()->array_type() != NULL
    6826                 :       25951 :       && !range_type->points_to()->is_slice_type())
    6827                 :         207 :     range_type = range_type->points_to();
    6828                 :             : 
    6829                 :       25744 :   if (range_type->array_type() != NULL)
    6830                 :             :     {
    6831                 :       22962 :       index_type = Type::lookup_integer_type("int");
    6832                 :       45924 :       value_type = range_type->array_type()->element_type();
    6833                 :             :     }
    6834                 :        2782 :   else if (range_type->is_string_type())
    6835                 :             :     {
    6836                 :         612 :       index_type = Type::lookup_integer_type("int");
    6837                 :         612 :       value_type = Type::lookup_integer_type("rune");
    6838                 :             :     }
    6839                 :        2170 :   else if (range_type->map_type() != NULL)
    6840                 :             :     {
    6841                 :        4134 :       index_type = range_type->map_type()->key_type();
    6842                 :        4134 :       value_type = range_type->map_type()->val_type();
    6843                 :             :     }
    6844                 :         103 :   else if (range_type->channel_type() != NULL)
    6845                 :             :     {
    6846                 :         206 :       if (!range_type->channel_type()->may_receive())
    6847                 :           2 :         this->report_error(_("invalid receive on send-only channel"));
    6848                 :         206 :       index_type = range_type->channel_type()->element_type();
    6849                 :         103 :       if (this->value_var_ != NULL)
    6850                 :             :         {
    6851                 :           0 :           if (!this->value_var_->type()->is_error())
    6852                 :           0 :             this->report_error(_("too many variables for range clause "
    6853                 :             :                                  "with channel"));
    6854                 :           0 :           this->set_is_error();
    6855                 :           0 :           return;
    6856                 :             :         }
    6857                 :             :     }
    6858                 :             :   else
    6859                 :             :     {
    6860                 :           0 :       this->report_error(_("range clause must have "
    6861                 :             :                            "array, slice, string, map, or channel type"));
    6862                 :           0 :       return;
    6863                 :             :     }
    6864                 :             : 
    6865                 :       25744 :   if (this->index_var_ != NULL
    6866                 :       25744 :       && !Assignment_statement::check_assignment_types(this->index_var_,
    6867                 :             :                                                        index_type,
    6868                 :             :                                                        this->location()))
    6869                 :           0 :     this->set_is_error();
    6870                 :       25744 :   if (this->value_var_ != NULL
    6871                 :       25744 :       && !Assignment_statement::check_assignment_types(this->value_var_,
    6872                 :             :                                                        value_type,
    6873                 :             :                                                        this->location()))
    6874                 :           0 :     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                 :       34428 : For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
    6883                 :             :                               Statement_inserter*)
    6884                 :             : {
    6885                 :       34428 :   if (this->classification() == STATEMENT_ERROR)
    6886                 :           0 :     return Statement::make_error_statement(this->location());
    6887                 :             : 
    6888                 :       34428 :   Type* range_type = this->range_->type();
    6889                 :       34428 :   if (range_type->points_to() != NULL
    6890                 :        8893 :       && range_type->points_to()->array_type() != NULL
    6891                 :       43321 :       && !range_type->points_to()->is_slice_type())
    6892                 :        8893 :     range_type = range_type->points_to();
    6893                 :             : 
    6894                 :       34428 :   Type* index_type;
    6895                 :       34428 :   Type* value_type = NULL;
    6896                 :       34428 :   if (range_type->array_type() != NULL)
    6897                 :             :     {
    6898                 :       31648 :       index_type = Type::lookup_integer_type("int");
    6899                 :       63296 :       value_type = range_type->array_type()->element_type();
    6900                 :             :     }
    6901                 :        2780 :   else if (range_type->is_string_type())
    6902                 :             :     {
    6903                 :         612 :       index_type = Type::lookup_integer_type("int");
    6904                 :         612 :       value_type = Type::lookup_integer_type("rune");
    6905                 :             :     }
    6906                 :        2168 :   else if (range_type->map_type() != NULL)
    6907                 :             :     {
    6908                 :        4134 :       index_type = range_type->map_type()->key_type();
    6909                 :        4134 :       value_type = range_type->map_type()->val_type();
    6910                 :             :     }
    6911                 :         101 :   else if (range_type->channel_type() != NULL)
    6912                 :             :     {
    6913                 :         202 :       index_type = range_type->channel_type()->element_type();
    6914                 :         101 :       go_assert(this->value_var_ == NULL);
    6915                 :             :     }
    6916                 :             :   else
    6917                 :           0 :     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                 :       34428 :   bool eval = true;
    6925                 :       22280 :   if ((this->value_var_ == NULL || this->value_var_->is_sink_expression())
    6926                 :       45786 :       && range_type->array_type() != NULL
    6927                 :       11358 :       && !range_type->is_slice_type()
    6928                 :       43732 :       && Builtin_call_expression::array_len_is_constant(this->range_))
    6929                 :             :     eval = false;
    6930                 :             : 
    6931                 :       34428 :   Location loc = this->location();
    6932                 :       34428 :   Block* temp_block = new Block(enclosing, loc);
    6933                 :             : 
    6934                 :       34428 :   Expression* orig_range_expr = this->range_;
    6935                 :       34428 :   Named_object* range_object = NULL;
    6936                 :       34428 :   Temporary_statement* range_temp = NULL;
    6937                 :       34428 :   if (eval)
    6938                 :             :     {
    6939                 :       25128 :       Var_expression* ve = this->range_->var_expression();
    6940                 :       25128 :       if (ve != NULL)
    6941                 :       14959 :         range_object = ve->named_object();
    6942                 :             :       else
    6943                 :             :         {
    6944                 :       10169 :           range_temp = Statement::make_temporary(NULL, this->range_, loc);
    6945                 :       10169 :           temp_block->add_statement(range_temp);
    6946                 :       10169 :           this->range_ = NULL;
    6947                 :             :         }
    6948                 :             :     }
    6949                 :             : 
    6950                 :             :   // Try to match "range clear" patterns and rewrite to simple runtime
    6951                 :             :   // calls.
    6952                 :       34428 :   if (range_type->map_type() != NULL)
    6953                 :             :     {
    6954                 :        2067 :       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                 :        2067 :       if (clear != NULL)
    6961                 :             :         {
    6962                 :          33 :           if (gogo->debug_optimization())
    6963                 :           1 :             go_debug(loc, "map range clear");
    6964                 :          33 :           clear->determine_types(gogo);
    6965                 :          33 :           temp_block->add_statement(clear);
    6966                 :          33 :           return Statement::make_block_statement(temp_block, loc);
    6967                 :             :         }
    6968                 :             :     }
    6969                 :       32361 :   else if (range_type->array_type() != NULL)
    6970                 :             :     {
    6971                 :             :       // Slice or array.
    6972                 :       31648 :       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                 :       31648 :       if (clear != NULL)
    6979                 :             :         {
    6980                 :         281 :           if (gogo->debug_optimization())
    6981                 :           2 :             go_debug(loc, "array range clear");
    6982                 :         281 :           clear->determine_types(gogo);
    6983                 :         281 :           temp_block->add_statement(clear);
    6984                 :         281 :           return Statement::make_block_statement(temp_block, loc);
    6985                 :             :         }
    6986                 :             :     }
    6987                 :             : 
    6988                 :       34114 :   Temporary_statement* index_temp = Statement::make_temporary(index_type,
    6989                 :             :                                                               NULL, loc);
    6990                 :       34114 :   temp_block->add_statement(index_temp);
    6991                 :             : 
    6992                 :       34114 :   Temporary_statement* value_temp = NULL;
    6993                 :       34114 :   if (this->value_var_ != NULL && !this->value_var_->is_sink_expression())
    6994                 :             :     {
    6995                 :       22252 :       value_temp = Statement::make_temporary(value_type, NULL, loc);
    6996                 :       22252 :       temp_block->add_statement(value_temp);
    6997                 :             :     }
    6998                 :             : 
    6999                 :       34114 :   Block* body = new Block(temp_block, loc);
    7000                 :             : 
    7001                 :       34114 :   Block* init;
    7002                 :       34114 :   Expression* cond;
    7003                 :       34114 :   Block* iter_init;
    7004                 :       34114 :   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                 :       34114 :   if (range_type->is_slice_type())
    7015                 :       21657 :     this->lower_range_slice(gogo, temp_block, body, range_object, range_temp,
    7016                 :             :                             index_temp, value_temp, &init, &cond, &iter_init,
    7017                 :             :                             &post);
    7018                 :       12457 :   else if (range_type->array_type() != NULL)
    7019                 :        9710 :     this->lower_range_array(gogo, temp_block, body, range_object, range_temp,
    7020                 :             :                             index_temp, value_temp, &init, &cond, &iter_init,
    7021                 :             :                             &post);
    7022                 :        2747 :   else if (range_type->is_string_type())
    7023                 :         612 :     this->lower_range_string(gogo, temp_block, body, range_object, range_temp,
    7024                 :             :                              index_temp, value_temp, &init, &cond, &iter_init,
    7025                 :             :                              &post);
    7026                 :        2135 :   else if (range_type->map_type() != NULL)
    7027                 :        4068 :     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                 :         101 :   else if (range_type->channel_type() != NULL)
    7031                 :         101 :     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                 :           0 :     go_unreachable();
    7036                 :             : 
    7037                 :       34114 :   if (iter_init != NULL)
    7038                 :       23037 :     body->add_statement(Statement::make_block_statement(iter_init, loc));
    7039                 :             : 
    7040                 :       34114 :   if (this->index_var_ != NULL)
    7041                 :             :     {
    7042                 :       34024 :       Statement* assign;
    7043                 :       34024 :       Expression* index_ref =
    7044                 :       34024 :         Expression::make_temporary_reference(index_temp, loc);
    7045                 :       34024 :       if (this->value_var_ == NULL || this->value_var_->is_sink_expression())
    7046                 :       11772 :         assign = Statement::make_assignment(this->index_var_, index_ref, loc);
    7047                 :             :       else
    7048                 :             :         {
    7049                 :       22252 :           Expression_list* lhs = new Expression_list();
    7050                 :       22252 :           lhs->push_back(this->index_var_);
    7051                 :       22252 :           lhs->push_back(this->value_var_);
    7052                 :             : 
    7053                 :       22252 :           Expression_list* rhs = new Expression_list();
    7054                 :       22252 :           rhs->push_back(index_ref);
    7055                 :       22252 :           rhs->push_back(Expression::make_temporary_reference(value_temp, loc));
    7056                 :             : 
    7057                 :       22252 :           assign = Statement::make_tuple_assignment(lhs, rhs, loc);
    7058                 :             :         }
    7059                 :       34024 :       assign->determine_types(gogo);
    7060                 :       34024 :       body->add_statement(assign);
    7061                 :             :     }
    7062                 :             : 
    7063                 :       34114 :   body->add_statement(Statement::make_block_statement(this->statements_, loc));
    7064                 :             : 
    7065                 :       34114 :   body->set_end_location(this->statements_->end_location());
    7066                 :             : 
    7067                 :       34114 :   For_statement* loop = Statement::make_for_statement(init, cond, post,
    7068                 :             :                                                       this->location());
    7069                 :       34114 :   loop->add_statements(body);
    7070                 :       34114 :   loop->determine_types(gogo);
    7071                 :       34114 :   loop->set_break_continue_labels(this->break_label_, this->continue_label_);
    7072                 :             : 
    7073                 :       34114 :   temp_block->add_statement(loop);
    7074                 :             : 
    7075                 :       34114 :   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                 :       26352 : For_range_statement::make_range_ref(Named_object* range_object,
    7083                 :             :                                     Temporary_statement* range_temp,
    7084                 :             :                                     Location loc)
    7085                 :             : {
    7086                 :       26352 :   if (range_object != NULL)
    7087                 :       16021 :     return Expression::make_var_reference(range_object, loc);
    7088                 :             :   else
    7089                 :       10331 :     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                 :       32260 : For_range_statement::call_builtin(Gogo* gogo, const char* funcname,
    7097                 :             :                                   Expression* arg,
    7098                 :             :                                   Location loc)
    7099                 :             : {
    7100                 :       32260 :   Named_object* no = gogo->lookup_global(funcname);
    7101                 :       32260 :   go_assert(no != NULL && no->is_function_declaration());
    7102                 :       32260 :   Expression* func = Expression::make_func_reference(no, NULL, loc);
    7103                 :       32260 :   Expression_list* params = new Expression_list();
    7104                 :       32260 :   params->push_back(arg);
    7105                 :       32260 :   return Expression::make_call(func, params, false, loc);
    7106                 :             : }
    7107                 :             : 
    7108                 :             : // Lower a for range over an array.
    7109                 :             : 
    7110                 :             : void
    7111                 :        9710 : 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                 :        9710 :   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                 :        9710 :   Block* init = new Block(enclosing, loc);
    7141                 :             : 
    7142                 :        9710 :   Expression* len_arg;
    7143                 :        9710 :   if (range_object == NULL && range_temp == NULL)
    7144                 :             :     {
    7145                 :             :       // Don't evaluate this->range_, just get its length.
    7146                 :        9209 :       len_arg = this->range_;
    7147                 :             :     }
    7148                 :             :   else
    7149                 :             :     {
    7150                 :         501 :       Expression* ref = this->make_range_ref(range_object, range_temp, loc);
    7151                 :         501 :       range_temp = Statement::make_temporary(NULL, ref, loc);
    7152                 :         501 :       range_temp->determine_types(gogo);
    7153                 :         501 :       init->add_statement(range_temp);
    7154                 :         501 :       len_arg = ref;
    7155                 :             :     }
    7156                 :        9710 :   Expression* len_call = this->call_builtin(gogo, "len", len_arg, loc);
    7157                 :        9710 :   Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
    7158                 :             :                                                             len_call, loc);
    7159                 :        9710 :   len_temp->determine_types(gogo);
    7160                 :        9710 :   init->add_statement(len_temp);
    7161                 :             : 
    7162                 :        9710 :   Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);
    7163                 :             : 
    7164                 :        9710 :   Temporary_reference_expression* tref =
    7165                 :        9710 :     Expression::make_temporary_reference(index_temp, loc);
    7166                 :        9710 :   tref->set_is_lvalue();
    7167                 :        9710 :   Statement* s = Statement::make_assignment(tref, zexpr, loc);
    7168                 :        9710 :   s->determine_types(gogo);
    7169                 :        9710 :   init->add_statement(s);
    7170                 :             : 
    7171                 :        9710 :   *pinit = init;
    7172                 :             : 
    7173                 :             :   // Set *PCOND to
    7174                 :             :   //   index_temp < len_temp
    7175                 :             : 
    7176                 :        9710 :   Expression* ref = Expression::make_temporary_reference(index_temp, loc);
    7177                 :        9710 :   Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
    7178                 :        9710 :   Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);
    7179                 :             : 
    7180                 :        9710 :   *pcond = lt;
    7181                 :             : 
    7182                 :             :   // Set *PITER_INIT to
    7183                 :             :   //   value_temp = range[index_temp]
    7184                 :             : 
    7185                 :        9710 :   Block* iter_init = NULL;
    7186                 :        9710 :   if (value_temp != NULL)
    7187                 :             :     {
    7188                 :         497 :       iter_init = new Block(body_block, loc);
    7189                 :             : 
    7190                 :         497 :       ref = Expression::make_temporary_reference(range_temp, loc);
    7191                 :         497 :       ref2 = Expression::make_temporary_reference(index_temp, loc);
    7192                 :         497 :       Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
    7193                 :             : 
    7194                 :         497 :       tref = Expression::make_temporary_reference(value_temp, loc);
    7195                 :         497 :       tref->set_is_lvalue();
    7196                 :         497 :       s = Statement::make_assignment(tref, index, loc);
    7197                 :         497 :       s->determine_types(gogo);
    7198                 :             : 
    7199                 :         497 :       iter_init->add_statement(s);
    7200                 :             :     }
    7201                 :        9710 :   *piter_init = iter_init;
    7202                 :             : 
    7203                 :             :   // Set *PPOST to
    7204                 :             :   //   index_temp++
    7205                 :             : 
    7206                 :        9710 :   Block* post = new Block(enclosing, loc);
    7207                 :        9710 :   tref = Expression::make_temporary_reference(index_temp, loc);
    7208                 :        9710 :   tref->set_is_lvalue();
    7209                 :        9710 :   s = Statement::make_inc_statement(tref);
    7210                 :        9710 :   s->determine_types(gogo);
    7211                 :        9710 :   post->add_statement(s);
    7212                 :        9710 :   *ppost = post;
    7213                 :        9710 : }
    7214                 :             : 
    7215                 :             : // Lower a for range over a slice.
    7216                 :             : 
    7217                 :             : void
    7218                 :       21657 : 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                 :       21657 :   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                 :       21657 :   Block* init = new Block(enclosing, loc);
    7252                 :             : 
    7253                 :       21657 :   Expression* ref = this->make_range_ref(range_object, range_temp, loc);
    7254                 :       21657 :   Temporary_statement* for_temp = Statement::make_temporary(NULL, ref, loc);
    7255                 :       21657 :   for_temp->determine_types(gogo);
    7256                 :       21657 :   init->add_statement(for_temp);
    7257                 :             : 
    7258                 :       21657 :   ref = Expression::make_temporary_reference(for_temp, loc);
    7259                 :       21657 :   Expression* len_call = this->call_builtin(gogo, "len", ref, loc);
    7260                 :       21657 :   Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
    7261                 :             :                                                             len_call, loc);
    7262                 :       21657 :   len_temp->determine_types(gogo);
    7263                 :       21657 :   init->add_statement(len_temp);
    7264                 :             : 
    7265                 :       21657 :   Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);
    7266                 :             : 
    7267                 :       21657 :   Temporary_reference_expression* tref =
    7268                 :       21657 :     Expression::make_temporary_reference(index_temp, loc);
    7269                 :       21657 :   tref->set_is_lvalue();
    7270                 :       21657 :   Statement* s = Statement::make_assignment(tref, zexpr, loc);
    7271                 :       21657 :   s->determine_types(gogo);
    7272                 :       21657 :   init->add_statement(s);
    7273                 :             : 
    7274                 :       21657 :   *pinit = init;
    7275                 :             : 
    7276                 :             :   // Set *PCOND to
    7277                 :             :   //   index_temp < len_temp
    7278                 :             : 
    7279                 :       21657 :   ref = Expression::make_temporary_reference(index_temp, loc);
    7280                 :       21657 :   Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
    7281                 :       21657 :   Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);
    7282                 :             : 
    7283                 :       21657 :   *pcond = lt;
    7284                 :             : 
    7285                 :             :   // Set *PITER_INIT to
    7286                 :             :   //   value_temp = range[index_temp]
    7287                 :             : 
    7288                 :       21657 :   Block* iter_init = NULL;
    7289                 :       21657 :   if (value_temp != NULL)
    7290                 :             :     {
    7291                 :       19793 :       iter_init = new Block(body_block, loc);
    7292                 :             : 
    7293                 :       19793 :       ref = Expression::make_temporary_reference(for_temp, loc);
    7294                 :       19793 :       ref2 = Expression::make_temporary_reference(index_temp, loc);
    7295                 :       19793 :       Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
    7296                 :             : 
    7297                 :       19793 :       tref = Expression::make_temporary_reference(value_temp, loc);
    7298                 :       19793 :       tref->set_is_lvalue();
    7299                 :       19793 :       s = Statement::make_assignment(tref, index, loc);
    7300                 :       19793 :       s->determine_types(gogo);
    7301                 :             : 
    7302                 :       19793 :       iter_init->add_statement(s);
    7303                 :             :     }
    7304                 :       21657 :   *piter_init = iter_init;
    7305                 :             : 
    7306                 :             :   // Set *PPOST to
    7307                 :             :   //   index_temp++
    7308                 :             : 
    7309                 :       21657 :   Block* post = new Block(enclosing, loc);
    7310                 :       21657 :   tref = Expression::make_temporary_reference(index_temp, loc);
    7311                 :       21657 :   tref->set_is_lvalue();
    7312                 :       21657 :   s = Statement::make_inc_statement(tref);
    7313                 :       21657 :   s->determine_types(gogo);
    7314                 :       21657 :   post->add_statement(s);
    7315                 :       21657 :   *ppost = post;
    7316                 :       21657 : }
    7317                 :             : 
    7318                 :             : // Lower a for range over a string.
    7319                 :             : 
    7320                 :             : void
    7321                 :         612 : 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                 :         612 :   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                 :         612 :   Block* init = new Block(enclosing, loc);
    7357                 :             : 
    7358                 :         612 :   Expression* ref = this->make_range_ref(range_object, range_temp, loc);
    7359                 :         612 :   Call_expression* call = this->call_builtin(gogo, "len", ref, loc);
    7360                 :         612 :   Temporary_statement* len_temp =
    7361                 :         612 :     Statement::make_temporary(index_temp->type(), call, loc);
    7362                 :         612 :   len_temp->determine_types(gogo);
    7363                 :         612 :   init->add_statement(len_temp);
    7364                 :             : 
    7365                 :         612 :   Temporary_statement* next_index_temp =
    7366                 :         612 :     Statement::make_temporary(index_temp->type(), NULL, loc);
    7367                 :         612 :   init->add_statement(next_index_temp);
    7368                 :             : 
    7369                 :         612 :   Temporary_reference_expression* index_ref =
    7370                 :         612 :     Expression::make_temporary_reference(index_temp, loc);
    7371                 :         612 :   index_ref->set_is_lvalue();
    7372                 :         612 :   Expression* zexpr = Expression::make_integer_ul(0, index_temp->type(), loc);
    7373                 :         612 :   Statement* s = Statement::make_assignment(index_ref, zexpr, loc);
    7374                 :         612 :   s->determine_types(gogo);
    7375                 :         612 :   init->add_statement(s);
    7376                 :             : 
    7377                 :         612 :   Type* rune_type;
    7378                 :         612 :   if (value_temp != NULL)
    7379                 :         561 :     rune_type = value_temp->type();
    7380                 :             :   else
    7381                 :             :     {
    7382                 :          51 :       rune_type = Type::lookup_integer_type("rune");
    7383                 :          51 :       value_temp = Statement::make_temporary(rune_type, NULL, loc);
    7384                 :          51 :       init->add_statement(value_temp);
    7385                 :             :     }
    7386                 :             : 
    7387                 :         612 :   *pinit = init;
    7388                 :             : 
    7389                 :             :   // Set *PCOND to
    7390                 :             :   //   index_temp < len_temp
    7391                 :             : 
    7392                 :         612 :   index_ref = Expression::make_temporary_reference(index_temp, loc);
    7393                 :         612 :   Expression* len_ref =
    7394                 :         612 :     Expression::make_temporary_reference(len_temp, loc);
    7395                 :         612 :   *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                 :         612 :   Block* iter_init = new Block(body_block, loc);
    7406                 :             : 
    7407                 :         612 :   ref = this->make_range_ref(range_object, range_temp, loc);
    7408                 :         612 :   index_ref = Expression::make_temporary_reference(index_temp, loc);
    7409                 :         612 :   ref = Expression::make_string_index(ref, index_ref, NULL, loc);
    7410                 :         612 :   ref = Expression::make_cast(rune_type, ref, loc);
    7411                 :         612 :   Temporary_reference_expression* value_ref =
    7412                 :         612 :     Expression::make_temporary_reference(value_temp, loc);
    7413                 :         612 :   value_ref->set_is_lvalue();
    7414                 :         612 :   s = Statement::make_assignment(value_ref, ref, loc);
    7415                 :         612 :   s->determine_types(gogo);
    7416                 :         612 :   iter_init->add_statement(s);
    7417                 :             : 
    7418                 :         612 :   value_ref = Expression::make_temporary_reference(value_temp, loc);
    7419                 :         612 :   Expression* rune_self = Expression::make_integer_ul(0x80, rune_type, loc);
    7420                 :         612 :   Expression* cond = Expression::make_binary(OPERATOR_LT, value_ref, rune_self,
    7421                 :             :                                              loc);
    7422                 :             : 
    7423                 :         612 :   Block* then_block = new Block(iter_init, loc);
    7424                 :             : 
    7425                 :         612 :   Temporary_reference_expression* lhs =
    7426                 :         612 :     Expression::make_temporary_reference(next_index_temp, loc);
    7427                 :         612 :   lhs->set_is_lvalue();
    7428                 :         612 :   index_ref = Expression::make_temporary_reference(index_temp, loc);
    7429                 :         612 :   Expression* one = Expression::make_integer_ul(1, index_temp->type(), loc);
    7430                 :         612 :   Expression* sum = Expression::make_binary(OPERATOR_PLUS, index_ref, one,
    7431                 :             :                                             loc);
    7432                 :         612 :   s = Statement::make_assignment(lhs, sum, loc);
    7433                 :         612 :   s->determine_types(gogo);
    7434                 :         612 :   then_block->add_statement(s);
    7435                 :             : 
    7436                 :         612 :   Block* else_block = new Block(iter_init, loc);
    7437                 :             : 
    7438                 :         612 :   ref = this->make_range_ref(range_object, range_temp, loc);
    7439                 :         612 :   index_ref = Expression::make_temporary_reference(index_temp, loc);
    7440                 :         612 :   call = Runtime::make_call(gogo, Runtime::DECODERUNE, loc, 2, ref, index_ref);
    7441                 :             : 
    7442                 :         612 :   value_ref = Expression::make_temporary_reference(value_temp, loc);
    7443                 :         612 :   value_ref->set_is_lvalue();
    7444                 :         612 :   Expression* res = Expression::make_call_result(call, 0);
    7445                 :         612 :   s = Statement::make_assignment(value_ref, res, loc);
    7446                 :         612 :   s->determine_types(gogo);
    7447                 :         612 :   else_block->add_statement(s);
    7448                 :             : 
    7449                 :         612 :   lhs = Expression::make_temporary_reference(next_index_temp, loc);
    7450                 :         612 :   lhs->set_is_lvalue();
    7451                 :         612 :   res = Expression::make_call_result(call, 1);
    7452                 :         612 :   s = Statement::make_assignment(lhs, res, loc);
    7453                 :         612 :   s->determine_types(gogo);
    7454                 :         612 :   else_block->add_statement(s);
    7455                 :             : 
    7456                 :         612 :   s = Statement::make_if_statement(cond, then_block, else_block, loc);
    7457                 :         612 :   s->determine_types(gogo);
    7458                 :         612 :   iter_init->add_statement(s);
    7459                 :             : 
    7460                 :         612 :   *piter_init = iter_init;
    7461                 :             : 
    7462                 :             :   // Set *PPOST to
    7463                 :             :   //   index_temp = next_index_temp
    7464                 :             : 
    7465                 :         612 :   Block* post = new Block(enclosing, loc);
    7466                 :             : 
    7467                 :         612 :   index_ref = Expression::make_temporary_reference(index_temp, loc);
    7468                 :         612 :   index_ref->set_is_lvalue();
    7469                 :         612 :   ref = Expression::make_temporary_reference(next_index_temp, loc);
    7470                 :         612 :   s = Statement::make_assignment(index_ref, ref, loc);
    7471                 :         612 :   s->determine_types(gogo);
    7472                 :             : 
    7473                 :         612 :   post->add_statement(s);
    7474                 :         612 :   *ppost = post;
    7475                 :         612 : }
    7476                 :             : 
    7477                 :             : // Lower a for range over a map.
    7478                 :             : 
    7479                 :             : void
    7480                 :        2034 : 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                 :        2034 :   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                 :        2034 :   Block* init = new Block(enclosing, loc);
    7513                 :             : 
    7514                 :        2034 :   Type* map_iteration_type = map_type->hiter_type(gogo);
    7515                 :        2034 :   Temporary_statement* hiter = Statement::make_temporary(map_iteration_type,
    7516                 :             :                                                          NULL, loc);
    7517                 :        2034 :   init->add_statement(hiter);
    7518                 :             : 
    7519                 :        2034 :   Expression* p1 = Expression::make_type_descriptor(map_type, loc);
    7520                 :        2034 :   Expression* p2 = this->make_range_ref(range_object, range_temp, loc);
    7521                 :        2034 :   Expression* ref = Expression::make_temporary_reference(hiter, loc);
    7522                 :        2034 :   Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
    7523                 :        2034 :   Expression* call = Runtime::make_call(gogo, Runtime::MAPITERINIT, loc, 3,
    7524                 :             :                                         p1, p2, p3);
    7525                 :        2034 :   Statement* s = Statement::make_statement(call, true);
    7526                 :        2034 :   s->determine_types(gogo);
    7527                 :        2034 :   init->add_statement(s);
    7528                 :             : 
    7529                 :        2034 :   *pinit = init;
    7530                 :             : 
    7531                 :             :   // Set *PCOND to
    7532                 :             :   //   hiter.key != nil
    7533                 :             : 
    7534                 :        2034 :   ref = Expression::make_temporary_reference(hiter, loc);
    7535                 :        2034 :   ref = Expression::make_field_reference(ref, 0, loc);
    7536                 :        2034 :   Expression* ne = Expression::make_binary(OPERATOR_NOTEQ, ref,
    7537                 :             :                                            Expression::make_nil(loc),
    7538                 :             :                                            loc);
    7539                 :        2034 :   *pcond = ne;
    7540                 :             : 
    7541                 :             :   // Set *PITER_INIT to
    7542                 :             :   //   index_temp = *hiter.key
    7543                 :             :   //   value_temp = *hiter.val
    7544                 :             : 
    7545                 :        2034 :   Block* iter_init = new Block(body_block, loc);
    7546                 :             : 
    7547                 :        2034 :   Expression* lhs = Expression::make_temporary_reference(index_temp, loc);
    7548                 :        2034 :   Expression* rhs = Expression::make_temporary_reference(hiter, loc);
    7549                 :        2034 :   rhs = Expression::make_field_reference(ref, 0, loc);
    7550                 :        2034 :   rhs = Expression::make_dereference(ref, Expression::NIL_CHECK_NOT_NEEDED,
    7551                 :             :                                      loc);
    7552                 :        2034 :   Statement* set = Statement::make_assignment(lhs, rhs, loc);
    7553                 :        2034 :   set->determine_types(gogo);
    7554                 :        2034 :   iter_init->add_statement(set);
    7555                 :             : 
    7556                 :        2034 :   if (value_temp != NULL)
    7557                 :             :     {
    7558                 :        1401 :       lhs = Expression::make_temporary_reference(value_temp, loc);
    7559                 :        1401 :       rhs = Expression::make_temporary_reference(hiter, loc);
    7560                 :        1401 :       rhs = Expression::make_field_reference(rhs, 1, loc);
    7561                 :        1401 :       rhs = Expression::make_dereference(rhs, Expression::NIL_CHECK_NOT_NEEDED,
    7562                 :             :                                          loc);
    7563                 :        1401 :       set = Statement::make_assignment(lhs, rhs, loc);
    7564                 :        1401 :       set->determine_types(gogo);
    7565                 :        1401 :       iter_init->add_statement(set);
    7566                 :             :     }
    7567                 :             : 
    7568                 :        2034 :   *piter_init = iter_init;
    7569                 :             : 
    7570                 :             :   // Set *PPOST to
    7571                 :             :   //   mapiternext(&hiter)
    7572                 :             : 
    7573                 :        2034 :   Block* post = new Block(enclosing, loc);
    7574                 :             : 
    7575                 :        2034 :   ref = Expression::make_temporary_reference(hiter, loc);
    7576                 :        2034 :   p1 = Expression::make_unary(OPERATOR_AND, ref, loc);
    7577                 :        2034 :   call = Runtime::make_call(gogo, Runtime::MAPITERNEXT, loc, 1, p1);
    7578                 :        2034 :   s = Statement::make_statement(call, true);
    7579                 :        2034 :   s->determine_types(gogo);
    7580                 :        2034 :   post->add_statement(s);
    7581                 :             : 
    7582                 :        2034 :   *ppost = post;
    7583                 :        2034 : }
    7584                 :             : 
    7585                 :             : // Lower a for range over a channel.
    7586                 :             : 
    7587                 :             : void
    7588                 :         101 : 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                 :         101 :   go_assert(value_temp == NULL);
    7601                 :             : 
    7602                 :         101 :   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                 :         101 :   *pinit = NULL;
    7617                 :         101 :   *pcond = NULL;
    7618                 :         101 :   *ppost = NULL;
    7619                 :             : 
    7620                 :             :   // Set *PITER_INIT to
    7621                 :             :   //   index_temp, ok_temp = <-range
    7622                 :             :   //   if !ok_temp {
    7623                 :             :   //           break
    7624                 :             :   //   }
    7625                 :             : 
    7626                 :         101 :   Block* iter_init = new Block(body_block, loc);
    7627                 :             : 
    7628                 :         101 :   Temporary_statement* ok_temp =
    7629                 :         101 :     Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
    7630                 :         101 :   iter_init->add_statement(ok_temp);
    7631                 :             : 
    7632                 :         101 :   Expression* cref = this->make_range_ref(range_object, range_temp, loc);
    7633                 :         101 :   Temporary_reference_expression* iref =
    7634                 :         101 :     Expression::make_temporary_reference(index_temp, loc);
    7635                 :         101 :   iref->set_is_lvalue();
    7636                 :         101 :   Temporary_reference_expression* oref =
    7637                 :         101 :     Expression::make_temporary_reference(ok_temp, loc);
    7638                 :         101 :   oref->set_is_lvalue();
    7639                 :         101 :   Statement* s = Statement::make_tuple_receive_assignment(iref, oref, cref,
    7640                 :             :                                                           loc);
    7641                 :         101 :   s->determine_types(gogo);
    7642                 :         101 :   iter_init->add_statement(s);
    7643                 :             : 
    7644                 :         101 :   Block* then_block = new Block(iter_init, loc);
    7645                 :         101 :   s = Statement::make_break_statement(this->break_label(), loc);
    7646                 :         101 :   then_block->add_statement(s);
    7647                 :             : 
    7648                 :         101 :   oref = Expression::make_temporary_reference(ok_temp, loc);
    7649                 :         101 :   Expression* cond = Expression::make_unary(OPERATOR_NOT, oref, loc);
    7650                 :         101 :   s = Statement::make_if_statement(cond, then_block, NULL, loc);
    7651                 :         101 :   s->determine_types(gogo);
    7652                 :         101 :   iter_init->add_statement(s);
    7653                 :             : 
    7654                 :         101 :   *piter_init = iter_init;
    7655                 :         101 : }
    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                 :        2067 : 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                 :        2067 :   if (this->value_var_ != NULL)
    7674                 :             :     return NULL;
    7675                 :         645 :   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                 :        2664 :   Var_expression* index_ve = this->index_var_->var_expression();
    7681                 :         630 :   if (index_ve == NULL)
    7682                 :             :     return NULL;
    7683                 :         630 :   Named_object* index_no = index_ve->named_object();
    7684                 :         630 :   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                 :         629 :   const std::vector<Statement*>* statements = this->statements_->statements();
    7689                 :         629 :   if (statements->size() != 1)
    7690                 :             :     return NULL;
    7691                 :        2123 :   Expression_statement* es = statements->at(0)->expression_statement();
    7692                 :          89 :   if (es == NULL)
    7693                 :             :     return NULL;
    7694                 :          89 :   Call_expression* call = es->expr()->call_expression();
    7695                 :          89 :   if (call == NULL || !call->is_builtin()
    7696                 :          40 :       || call->builtin_call_expression()->code()
    7697                 :             :          != Builtin_call_expression::BUILTIN_DELETE)
    7698                 :          49 :     return NULL;
    7699                 :          40 :   if (!Expression::is_same_variable(call->args()->at(0), orig_range_expr)
    7700                 :          40 :       || !Expression::is_same_variable(call->args()->at(1), this->index_var_))
    7701                 :           7 :     return NULL;
    7702                 :             : 
    7703                 :             :   // Everything matches. Rewrite to mapclear(TYPE, MAP).
    7704                 :          33 :   Expression* e1 = Expression::make_type_descriptor(map_type, loc);
    7705                 :          33 :   Expression* e2 = this->make_range_ref(range_object, range_temp, loc);
    7706                 :          33 :   call = Runtime::make_call(gogo, Runtime::MAPCLEAR, loc, 2, e1, e2);
    7707                 :          33 :   Statement* s = Statement::make_statement(call, true);
    7708                 :          33 :   s->determine_types(gogo);
    7709                 :          33 :   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                 :       31648 : 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                 :       31648 :   if (this->value_var_ != NULL)
    7729                 :             :     return NULL;
    7730                 :       11354 :   if (this->index_var_ == NULL)
    7731                 :             :     return NULL;
    7732                 :             : 
    7733                 :             :   // Match the body, a single assignment statement a[i] = zero.
    7734                 :       11330 :   const std::vector<Statement*>* statements = this->statements_->statements();
    7735                 :       11330 :   if (statements->size() != 1)
    7736                 :             :     return NULL;
    7737                 :        7844 :   Assignment_statement* as = statements->at(0)->assignment_statement();
    7738                 :        1190 :   if (as == NULL || !as->rhs()->is_zero_value())
    7739                 :        7461 :     return NULL;
    7740                 :         385 :   if (as->lhs()->type()->interface_type() != NULL
    7741                 :           4 :       && as->rhs()->type()->interface_type() == NULL
    7742                 :           2 :       && !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                 :         381 :   Array_index_expression* aie = as->lhs()->array_index_expression();
    7747                 :         373 :   if (aie == NULL || aie->end() != NULL
    7748                 :         373 :       || !Expression::is_same_variable(orig_range_expr, aie->array())
    7749                 :         282 :       || !Expression::is_same_variable(this->index_var_, aie->start()))
    7750                 :         100 :     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                 :         562 :   Type* elem_type = array_type->array_type()->element_type();
    7762                 :         281 :   int64_t elme_sz;
    7763                 :         281 :   bool ok = elem_type->backend_type_size(gogo, &elme_sz);
    7764                 :         281 :   if (!ok)
    7765                 :             :     return NULL;
    7766                 :             : 
    7767                 :         281 :   Block* b = new Block(temp_block, loc);
    7768                 :             : 
    7769                 :         281 :   Expression* ref;
    7770                 :         281 :   if (range_object == NULL && range_temp == NULL)
    7771                 :             :     // is_same_variable implies no side effect, so it is ok to copy.
    7772                 :          91 :     ref = orig_range_expr->copy();
    7773                 :             :   else
    7774                 :         190 :     ref = this->make_range_ref(range_object, range_temp, loc);
    7775                 :         281 :   Expression* len = this->call_builtin(gogo, "len", ref, loc);
    7776                 :         281 :   Temporary_statement* tslen = Statement::make_temporary(NULL, len, loc);
    7777                 :         281 :   tslen->determine_types(gogo);
    7778                 :         281 :   temp_block->add_statement(tslen);
    7779                 :             : 
    7780                 :         281 :   Expression* zero = Expression::make_integer_ul(0, this->index_var_->type(), loc);
    7781                 :         281 :   ref = ref->copy();
    7782                 :         281 :   Expression* elem = Expression::make_array_index(ref, zero, NULL, NULL, loc);
    7783                 :         281 :   elem->array_index_expression()->set_needs_bounds_check(false);
    7784                 :         281 :   Expression* e1 = Expression::make_unary(OPERATOR_AND, elem, loc);
    7785                 :         281 :   Temporary_statement* ts1 = Statement::make_temporary(NULL, e1, loc);
    7786                 :         281 :   ts1->determine_types(gogo);
    7787                 :         281 :   b->add_statement(ts1);
    7788                 :             : 
    7789                 :         281 :   len = Expression::make_temporary_reference(tslen, loc);
    7790                 :         281 :   Expression* sz = Expression::make_integer_int64(elme_sz, len->type(), loc);
    7791                 :         281 :   Expression* e2 = Expression::make_binary(OPERATOR_MULT, len, sz, loc);
    7792                 :         281 :   Temporary_statement* ts2 = Statement::make_temporary(NULL, e2, loc);
    7793                 :         281 :   ts2->determine_types(gogo);
    7794                 :         281 :   b->add_statement(ts2);
    7795                 :             : 
    7796                 :         281 :   Expression* ptr_arg = Expression::make_temporary_reference(ts1, loc);
    7797                 :         281 :   Expression* sz_arg = Expression::make_temporary_reference(ts2, loc);
    7798                 :         281 :   Expression* call;
    7799                 :         281 :   if (elem_type->has_pointer())
    7800                 :          30 :     call = Runtime::make_call(gogo, Runtime::MEMCLRHASPTR, loc, 2,
    7801                 :             :                               ptr_arg, sz_arg);
    7802                 :             :   else
    7803                 :             :     {
    7804                 :         251 :       Type* int32_type = Type::lookup_integer_type("int32");
    7805                 :         251 :       Expression* zero32 = Expression::make_integer_ul(0, int32_type, loc);
    7806                 :         251 :       call = Runtime::make_call(gogo, Runtime::BUILTIN_MEMSET, loc, 3, ptr_arg,
    7807                 :             :                                 zero32, sz_arg);
    7808                 :             :     }
    7809                 :         281 :   Statement* cs3 = Statement::make_statement(call, true);
    7810                 :         281 :   cs3->determine_types(gogo);
    7811                 :         281 :   b->add_statement(cs3);
    7812                 :             : 
    7813                 :         281 :   len = Expression::make_temporary_reference(tslen, loc);
    7814                 :         281 :   Expression* one = Expression::make_integer_ul(1, len->type(), loc);
    7815                 :         281 :   Expression* rhs = Expression::make_binary(OPERATOR_MINUS, len, one, loc);
    7816                 :         281 :   Expression* lhs = this->index_var_->copy();
    7817                 :         281 :   Statement* as4 = Statement::make_assignment(lhs, rhs, loc);
    7818                 :         281 :   as4->determine_types(gogo);
    7819                 :         281 :   b->add_statement(as4);
    7820                 :             : 
    7821                 :         281 :   len = Expression::make_temporary_reference(tslen, loc);
    7822                 :         281 :   zero = zero->copy();
    7823                 :         281 :   Expression* cond = Expression::make_binary(OPERATOR_NOTEQ, len, zero, loc);
    7824                 :         281 :   Statement* ret = Statement::make_if_statement(cond, b, NULL, loc);
    7825                 :         281 :   ret->determine_types(gogo);
    7826                 :         281 :   return ret;
    7827                 :             : }
    7828                 :             : 
    7829                 :             : // Return the break LABEL_EXPR.
    7830                 :             : 
    7831                 :             : Unnamed_label*
    7832                 :        1527 : For_range_statement::break_label()
    7833                 :             : {
    7834                 :        1527 :   if (this->break_label_ == NULL)
    7835                 :        1414 :     this->break_label_ = new Unnamed_label(this->location());
    7836                 :        1527 :   return this->break_label_;
    7837                 :             : }
    7838                 :             : 
    7839                 :             : // Return the continue LABEL_EXPR.
    7840                 :             : 
    7841                 :             : Unnamed_label*
    7842                 :        5908 : For_range_statement::continue_label()
    7843                 :             : {
    7844                 :        5908 :   if (this->continue_label_ == NULL)
    7845                 :        3563 :     this->continue_label_ = new Unnamed_label(this->location());
    7846                 :        5908 :   return this->continue_label_;
    7847                 :             : }
    7848                 :             : 
    7849                 :             : // Dump the AST representation for a for range statement.
    7850                 :             : 
    7851                 :             : void
    7852                 :           0 : For_range_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    7853                 :             : {
    7854                 :             : 
    7855                 :           0 :   ast_dump_context->print_indent();
    7856                 :           0 :   ast_dump_context->ostream() << "for ";
    7857                 :           0 :   ast_dump_context->dump_expression(this->index_var_);
    7858                 :           0 :   if (this->value_var_ != NULL)
    7859                 :             :     {
    7860                 :           0 :       ast_dump_context->ostream() << ", ";
    7861                 :           0 :       ast_dump_context->dump_expression(this->value_var_);
    7862                 :             :     }
    7863                 :             : 
    7864                 :           0 :   ast_dump_context->ostream() << " = range ";
    7865                 :           0 :   ast_dump_context->dump_expression(this->range_);
    7866                 :           0 :   if (ast_dump_context->dump_subblocks())
    7867                 :             :     {
    7868                 :           0 :       ast_dump_context->ostream() << " {" << std::endl;
    7869                 :             : 
    7870                 :           0 :       ast_dump_context->indent();
    7871                 :             : 
    7872                 :           0 :       ast_dump_context->dump_block(this->statements_);
    7873                 :             : 
    7874                 :           0 :       ast_dump_context->unindent();
    7875                 :           0 :       ast_dump_context->print_indent();
    7876                 :           0 :       ast_dump_context->ostream() << "}";
    7877                 :             :     }
    7878                 :           0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    7879                 :           0 : }
    7880                 :             : 
    7881                 :             : // Make a for statement with a range clause.
    7882                 :             : 
    7883                 :             : For_range_statement*
    7884                 :       34430 : Statement::make_for_range_statement(Expression* index_var,
    7885                 :             :                                     Expression* value_var,
    7886                 :             :                                     Expression* range,
    7887                 :             :                                     Location location)
    7888                 :             : {
    7889                 :       34430 :   return new For_range_statement(index_var, value_var, range, location);
    7890                 :             : }
        

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.