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