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 "types.h"
11 #include "expressions.h"
12 #include "gogo.h"
13 #include "runtime.h"
14 #include "backend.h"
15 #include "statements.h"
16 #include "ast-dump.h"
17 #include "dataflow.h"
18 
19 // Class Statement.
20 
Statement(Statement_classification classification,Location location)21 Statement::Statement(Statement_classification classification,
22 		     Location location)
23   : classification_(classification), location_(location)
24 {
25 }
26 
~Statement()27 Statement::~Statement()
28 {
29 }
30 
31 // Traverse the tree.  The work of walking the components is handled
32 // by the subclasses.
33 
34 int
traverse(Block * block,size_t * pindex,Traverse * traverse)35 Statement::traverse(Block* block, size_t* pindex, Traverse* traverse)
36 {
37   if (this->classification_ == STATEMENT_ERROR)
38     return TRAVERSE_CONTINUE;
39 
40   unsigned int traverse_mask = traverse->traverse_mask();
41 
42   if ((traverse_mask & Traverse::traverse_statements) != 0)
43     {
44       int t = traverse->statement(block, pindex, this);
45       if (t == TRAVERSE_EXIT)
46 	return TRAVERSE_EXIT;
47       else if (t == TRAVERSE_SKIP_COMPONENTS)
48 	return TRAVERSE_CONTINUE;
49     }
50 
51   // No point in checking traverse_mask here--a statement may contain
52   // other blocks or statements, and if we got here we always want to
53   // walk them.
54   return this->do_traverse(traverse);
55 }
56 
57 // Traverse the contents of a statement.
58 
59 int
traverse_contents(Traverse * traverse)60 Statement::traverse_contents(Traverse* traverse)
61 {
62   return this->do_traverse(traverse);
63 }
64 
65 // Traverse assignments.
66 
67 bool
traverse_assignments(Traverse_assignments * tassign)68 Statement::traverse_assignments(Traverse_assignments* tassign)
69 {
70   if (this->classification_ == STATEMENT_ERROR)
71     return false;
72   return this->do_traverse_assignments(tassign);
73 }
74 
75 // Traverse an expression in a statement.  This is a helper function
76 // for child classes.
77 
78 int
traverse_expression(Traverse * traverse,Expression ** expr)79 Statement::traverse_expression(Traverse* traverse, Expression** expr)
80 {
81   if ((traverse->traverse_mask()
82        & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
83     return TRAVERSE_CONTINUE;
84   return Expression::traverse(expr, traverse);
85 }
86 
87 // Traverse an expression list in a statement.  This is a helper
88 // function for child classes.
89 
90 int
traverse_expression_list(Traverse * traverse,Expression_list * expr_list)91 Statement::traverse_expression_list(Traverse* traverse,
92 				    Expression_list* expr_list)
93 {
94   if (expr_list == NULL)
95     return TRAVERSE_CONTINUE;
96   if ((traverse->traverse_mask()
97        & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
98     return TRAVERSE_CONTINUE;
99   return expr_list->traverse(traverse);
100 }
101 
102 // Traverse a type in a statement.  This is a helper function for
103 // child classes.
104 
105 int
traverse_type(Traverse * traverse,Type * type)106 Statement::traverse_type(Traverse* traverse, Type* type)
107 {
108   if ((traverse->traverse_mask()
109        & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
110     return TRAVERSE_CONTINUE;
111   return Type::traverse(type, traverse);
112 }
113 
114 // Set type information for unnamed constants.  This is really done by
115 // the child class.
116 
117 void
determine_types()118 Statement::determine_types()
119 {
120   this->do_determine_types();
121 }
122 
123 // If this is a thunk statement, return it.
124 
125 Thunk_statement*
thunk_statement()126 Statement::thunk_statement()
127 {
128   Thunk_statement* ret = this->convert<Thunk_statement, STATEMENT_GO>();
129   if (ret == NULL)
130     ret = this->convert<Thunk_statement, STATEMENT_DEFER>();
131   return ret;
132 }
133 
134 // Convert a Statement to the backend representation.  This is really
135 // done by the child class.
136 
137 Bstatement*
get_backend(Translate_context * context)138 Statement::get_backend(Translate_context* context)
139 {
140   if (this->classification_ == STATEMENT_ERROR)
141     return context->backend()->error_statement();
142   return this->do_get_backend(context);
143 }
144 
145 // Dump AST representation for a statement to a dump context.
146 
147 void
dump_statement(Ast_dump_context * ast_dump_context) const148 Statement::dump_statement(Ast_dump_context* ast_dump_context) const
149 {
150   this->do_dump_statement(ast_dump_context);
151 }
152 
153 // Note that this statement is erroneous.  This is called by children
154 // when they discover an error.
155 
156 void
set_is_error()157 Statement::set_is_error()
158 {
159   this->classification_ = STATEMENT_ERROR;
160 }
161 
162 // For children to call to report an error conveniently.
163 
164 void
report_error(const char * msg)165 Statement::report_error(const char* msg)
166 {
167   error_at(this->location_, "%s", msg);
168   this->set_is_error();
169 }
170 
171 // An error statement, used to avoid crashing after we report an
172 // error.
173 
174 class Error_statement : public Statement
175 {
176  public:
Error_statement(Location location)177   Error_statement(Location location)
178     : Statement(STATEMENT_ERROR, location)
179   { }
180 
181  protected:
182   int
do_traverse(Traverse *)183   do_traverse(Traverse*)
184   { return TRAVERSE_CONTINUE; }
185 
186   Bstatement*
do_get_backend(Translate_context *)187   do_get_backend(Translate_context*)
188   { go_unreachable(); }
189 
190   void
191   do_dump_statement(Ast_dump_context*) const;
192 };
193 
194 // Dump the AST representation for an error statement.
195 
196 void
do_dump_statement(Ast_dump_context * ast_dump_context) const197 Error_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
198 {
199   ast_dump_context->print_indent();
200   ast_dump_context->ostream() << "Error statement" << std::endl;
201 }
202 
203 // Make an error statement.
204 
205 Statement*
make_error_statement(Location location)206 Statement::make_error_statement(Location location)
207 {
208   return new Error_statement(location);
209 }
210 
211 // Class Variable_declaration_statement.
212 
Variable_declaration_statement(Named_object * var)213 Variable_declaration_statement::Variable_declaration_statement(
214     Named_object* var)
215   : Statement(STATEMENT_VARIABLE_DECLARATION, var->var_value()->location()),
216     var_(var)
217 {
218 }
219 
220 // We don't actually traverse the variable here; it was traversed
221 // while traversing the Block.
222 
223 int
do_traverse(Traverse *)224 Variable_declaration_statement::do_traverse(Traverse*)
225 {
226   return TRAVERSE_CONTINUE;
227 }
228 
229 // Traverse the assignments in a variable declaration.  Note that this
230 // traversal is different from the usual traversal.
231 
232 bool
do_traverse_assignments(Traverse_assignments * tassign)233 Variable_declaration_statement::do_traverse_assignments(
234     Traverse_assignments* tassign)
235 {
236   tassign->initialize_variable(this->var_);
237   return true;
238 }
239 
240 // Lower the variable's initialization expression.
241 
242 Statement*
do_lower(Gogo * gogo,Named_object * function,Block *,Statement_inserter * inserter)243 Variable_declaration_statement::do_lower(Gogo* gogo, Named_object* function,
244 					 Block*, Statement_inserter* inserter)
245 {
246   this->var_->var_value()->lower_init_expression(gogo, function, inserter);
247   return this;
248 }
249 
250 // Flatten the variable's initialization expression.
251 
252 Statement*
do_flatten(Gogo * gogo,Named_object * function,Block *,Statement_inserter * inserter)253 Variable_declaration_statement::do_flatten(Gogo* gogo, Named_object* function,
254                                            Block*, Statement_inserter* inserter)
255 {
256   Variable* var = this->var_->var_value();
257   if (var->type()->is_error_type()
258       || (var->init() != NULL
259           && var->init()->is_error_expression()))
260     {
261       go_assert(saw_errors());
262       return Statement::make_error_statement(this->location());
263     }
264   this->var_->var_value()->flatten_init_expression(gogo, function, inserter);
265   return this;
266 }
267 
268 // Convert a variable declaration to the backend representation.
269 
270 Bstatement*
do_get_backend(Translate_context * context)271 Variable_declaration_statement::do_get_backend(Translate_context* context)
272 {
273   Variable* var = this->var_->var_value();
274   Bvariable* bvar = this->var_->get_backend_variable(context->gogo(),
275 						     context->function());
276   Bexpression* binit = var->get_init(context->gogo(), context->function());
277 
278   if (!var->is_in_heap())
279     {
280       go_assert(binit != NULL);
281       return context->backend()->init_statement(bvar, binit);
282     }
283 
284   // Something takes the address of this variable, so the value is
285   // stored in the heap.  Initialize it to newly allocated memory
286   // space, and assign the initial value to the new space.
287   Location loc = this->location();
288   Named_object* newfn = context->gogo()->lookup_global("new");
289   go_assert(newfn != NULL && newfn->is_function_declaration());
290   Expression* func = Expression::make_func_reference(newfn, NULL, loc);
291   Expression_list* params = new Expression_list();
292   params->push_back(Expression::make_type(var->type(), loc));
293   Expression* call = Expression::make_call(func, params, false, loc);
294   context->gogo()->lower_expression(context->function(), NULL, &call);
295   Temporary_statement* temp = Statement::make_temporary(NULL, call, loc);
296   Bstatement* btemp = temp->get_backend(context);
297 
298   Bstatement* set = NULL;
299   if (binit != NULL)
300     {
301       Expression* e = Expression::make_temporary_reference(temp, loc);
302       e = Expression::make_unary(OPERATOR_MULT, e, loc);
303       Bexpression* be = e->get_backend(context);
304       set = context->backend()->assignment_statement(be, binit, loc);
305     }
306 
307   Expression* ref = Expression::make_temporary_reference(temp, loc);
308   Bexpression* bref = ref->get_backend(context);
309   Bstatement* sinit = context->backend()->init_statement(bvar, bref);
310 
311   std::vector<Bstatement*> stats;
312   stats.reserve(3);
313   stats.push_back(btemp);
314   if (set != NULL)
315     stats.push_back(set);
316   stats.push_back(sinit);
317   return context->backend()->statement_list(stats);
318 }
319 
320 // Dump the AST representation for a variable declaration.
321 
322 void
do_dump_statement(Ast_dump_context * ast_dump_context) const323 Variable_declaration_statement::do_dump_statement(
324     Ast_dump_context* ast_dump_context) const
325 {
326   ast_dump_context->print_indent();
327 
328   go_assert(var_->is_variable());
329   ast_dump_context->ostream() << "var " << this->var_->name() <<  " ";
330   Variable* var = this->var_->var_value();
331   if (var->has_type())
332     {
333       ast_dump_context->dump_type(var->type());
334       ast_dump_context->ostream() << " ";
335     }
336   if (var->init() != NULL)
337     {
338       ast_dump_context->ostream() <<  "= ";
339       ast_dump_context->dump_expression(var->init());
340     }
341   ast_dump_context->ostream() << std::endl;
342 }
343 
344 // Make a variable declaration.
345 
346 Statement*
make_variable_declaration(Named_object * var)347 Statement::make_variable_declaration(Named_object* var)
348 {
349   return new Variable_declaration_statement(var);
350 }
351 
352 // Class Temporary_statement.
353 
354 // Return the type of the temporary variable.
355 
356 Type*
type() const357 Temporary_statement::type() const
358 {
359   Type* type = this->type_ != NULL ? this->type_ : this->init_->type();
360 
361   // Temporary variables cannot have a void type.
362   if (type->is_void_type())
363     {
364       go_assert(saw_errors());
365       return Type::make_error_type();
366     }
367   return type;
368 }
369 
370 // Traversal.
371 
372 int
do_traverse(Traverse * traverse)373 Temporary_statement::do_traverse(Traverse* traverse)
374 {
375   if (this->type_ != NULL
376       && this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
377     return TRAVERSE_EXIT;
378   if (this->init_ == NULL)
379     return TRAVERSE_CONTINUE;
380   else
381     return this->traverse_expression(traverse, &this->init_);
382 }
383 
384 // Traverse assignments.
385 
386 bool
do_traverse_assignments(Traverse_assignments * tassign)387 Temporary_statement::do_traverse_assignments(Traverse_assignments* tassign)
388 {
389   if (this->init_ == NULL)
390     return false;
391   tassign->value(&this->init_, true, true);
392   return true;
393 }
394 
395 // Determine types.
396 
397 void
do_determine_types()398 Temporary_statement::do_determine_types()
399 {
400   if (this->type_ != NULL && this->type_->is_abstract())
401     this->type_ = this->type_->make_non_abstract_type();
402 
403   if (this->init_ != NULL)
404     {
405       if (this->type_ == NULL)
406 	this->init_->determine_type_no_context();
407       else
408 	{
409 	  Type_context context(this->type_, false);
410 	  this->init_->determine_type(&context);
411 	}
412     }
413 
414   if (this->type_ == NULL)
415     {
416       this->type_ = this->init_->type();
417       go_assert(!this->type_->is_abstract());
418     }
419 }
420 
421 // Check types.
422 
423 void
do_check_types(Gogo *)424 Temporary_statement::do_check_types(Gogo*)
425 {
426   if (this->type_ != NULL && this->init_ != NULL)
427     {
428       std::string reason;
429       if (!Type::are_assignable(this->type_, this->init_->type(), &reason))
430 	{
431 	  if (reason.empty())
432 	    error_at(this->location(), "incompatible types in assignment");
433 	  else
434 	    error_at(this->location(), "incompatible types in assignment (%s)",
435 		     reason.c_str());
436 	  this->set_is_error();
437 	}
438     }
439 }
440 
441 // Flatten a temporary statement: add another temporary when it might
442 // be needed for interface conversion.
443 
444 Statement*
do_flatten(Gogo *,Named_object *,Block *,Statement_inserter * inserter)445 Temporary_statement::do_flatten(Gogo*, Named_object*, Block*,
446 				Statement_inserter* inserter)
447 {
448   if (this->type()->is_error_type()
449       || (this->init_ != NULL
450           && this->init_->is_error_expression()))
451     {
452       go_assert(saw_errors());
453       return Statement::make_error_statement(this->location());
454     }
455 
456   if (this->type_ != NULL
457       && this->init_ != NULL
458       && !Type::are_identical(this->type_, this->init_->type(), false, NULL)
459       && this->init_->type()->interface_type() != NULL
460       && !this->init_->is_variable())
461     {
462       Temporary_statement *temp =
463 	Statement::make_temporary(NULL, this->init_, this->location());
464       inserter->insert(temp);
465       this->init_ = Expression::make_temporary_reference(temp,
466 							 this->location());
467     }
468   return this;
469 }
470 
471 // Convert to backend representation.
472 
473 Bstatement*
do_get_backend(Translate_context * context)474 Temporary_statement::do_get_backend(Translate_context* context)
475 {
476   go_assert(this->bvariable_ == NULL);
477 
478   Named_object* function = context->function();
479   go_assert(function != NULL);
480   Bfunction* bfunction = function->func_value()->get_decl();
481   Btype* btype = this->type()->get_backend(context->gogo());
482 
483   Bexpression* binit;
484   if (this->init_ == NULL)
485     binit = NULL;
486   else if (this->type_ == NULL)
487     binit = this->init_->get_backend(context);
488   else
489     {
490       Expression* init = Expression::convert_for_assignment(context->gogo(),
491 							    this->type_,
492 							    this->init_,
493 							    this->location());
494       binit = init->get_backend(context);
495     }
496 
497   Bstatement* statement;
498   this->bvariable_ =
499     context->backend()->temporary_variable(bfunction, context->bblock(),
500 					   btype, binit,
501 					   this->is_address_taken_,
502 					   this->location(), &statement);
503   return statement;
504 }
505 
506 // Return the backend variable.
507 
508 Bvariable*
get_backend_variable(Translate_context * context) const509 Temporary_statement::get_backend_variable(Translate_context* context) const
510 {
511   if (this->bvariable_ == NULL)
512     {
513       go_assert(saw_errors());
514       return context->backend()->error_variable();
515     }
516   return this->bvariable_;
517 }
518 
519 // Dump the AST represemtation for a temporary statement
520 
521 void
do_dump_statement(Ast_dump_context * ast_dump_context) const522 Temporary_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
523 {
524   ast_dump_context->print_indent();
525   ast_dump_context->dump_temp_variable_name(this);
526   if (this->type_ != NULL)
527     {
528       ast_dump_context->ostream() << " ";
529       ast_dump_context->dump_type(this->type_);
530     }
531   if (this->init_ != NULL)
532     {
533       ast_dump_context->ostream() << " = ";
534       ast_dump_context->dump_expression(this->init_);
535     }
536   ast_dump_context->ostream() << std::endl;
537 }
538 
539 // Make and initialize a temporary variable in BLOCK.
540 
541 Temporary_statement*
make_temporary(Type * type,Expression * init,Location location)542 Statement::make_temporary(Type* type, Expression* init,
543 			  Location location)
544 {
545   return new Temporary_statement(type, init, location);
546 }
547 
548 // Class Assignment_statement.
549 
550 // Traversal.
551 
552 int
do_traverse(Traverse * traverse)553 Assignment_statement::do_traverse(Traverse* traverse)
554 {
555   if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
556     return TRAVERSE_EXIT;
557   return this->traverse_expression(traverse, &this->rhs_);
558 }
559 
560 bool
do_traverse_assignments(Traverse_assignments * tassign)561 Assignment_statement::do_traverse_assignments(Traverse_assignments* tassign)
562 {
563   tassign->assignment(&this->lhs_, &this->rhs_);
564   return true;
565 }
566 
567 // Set types for the assignment.
568 
569 void
do_determine_types()570 Assignment_statement::do_determine_types()
571 {
572   this->lhs_->determine_type_no_context();
573   Type* rhs_context_type = this->lhs_->type();
574   if (rhs_context_type->is_sink_type())
575     rhs_context_type = NULL;
576   Type_context context(rhs_context_type, false);
577   this->rhs_->determine_type(&context);
578 }
579 
580 // Check types for an assignment.
581 
582 void
do_check_types(Gogo *)583 Assignment_statement::do_check_types(Gogo*)
584 {
585   // The left hand side must be either addressable, a map index
586   // expression, or the blank identifier.
587   if (!this->lhs_->is_addressable()
588       && this->lhs_->map_index_expression() == NULL
589       && !this->lhs_->is_sink_expression())
590     {
591       if (!this->lhs_->type()->is_error())
592 	this->report_error(_("invalid left hand side of assignment"));
593       return;
594     }
595 
596   Type* lhs_type = this->lhs_->type();
597   Type* rhs_type = this->rhs_->type();
598 
599   // Invalid assignment of nil to the blank identifier.
600   if (lhs_type->is_sink_type()
601       && rhs_type->is_nil_type())
602     {
603       this->report_error(_("use of untyped nil"));
604       return;
605     }
606 
607   std::string reason;
608   if (!Type::are_assignable(lhs_type, rhs_type, &reason))
609     {
610       if (reason.empty())
611 	error_at(this->location(), "incompatible types in assignment");
612       else
613 	error_at(this->location(), "incompatible types in assignment (%s)",
614 		 reason.c_str());
615       this->set_is_error();
616     }
617 
618   if (lhs_type->is_error() || rhs_type->is_error())
619     this->set_is_error();
620 }
621 
622 // Flatten an assignment statement.  We may need a temporary for
623 // interface conversion.
624 
625 Statement*
do_flatten(Gogo *,Named_object *,Block *,Statement_inserter * inserter)626 Assignment_statement::do_flatten(Gogo*, Named_object*, Block*,
627 				 Statement_inserter* inserter)
628 {
629   if (this->lhs_->is_error_expression()
630       || this->lhs_->type()->is_error_type()
631       || this->rhs_->is_error_expression()
632       || this->rhs_->type()->is_error_type())
633     {
634       go_assert(saw_errors());
635       return Statement::make_error_statement(this->location());
636     }
637 
638   if (!this->lhs_->is_sink_expression()
639       && !Type::are_identical(this->lhs_->type(), this->rhs_->type(),
640 			      false, NULL)
641       && this->rhs_->type()->interface_type() != NULL
642       && !this->rhs_->is_variable())
643     {
644       Temporary_statement* temp =
645 	Statement::make_temporary(NULL, this->rhs_, this->location());
646       inserter->insert(temp);
647       this->rhs_ = Expression::make_temporary_reference(temp,
648 							this->location());
649     }
650   return this;
651 }
652 
653 // Convert an assignment statement to the backend representation.
654 
655 Bstatement*
do_get_backend(Translate_context * context)656 Assignment_statement::do_get_backend(Translate_context* context)
657 {
658   if (this->lhs_->is_sink_expression())
659     {
660       Bexpression* rhs = this->rhs_->get_backend(context);
661       return context->backend()->expression_statement(rhs);
662     }
663 
664   Bexpression* lhs = this->lhs_->get_backend(context);
665   Expression* conv =
666       Expression::convert_for_assignment(context->gogo(), this->lhs_->type(),
667                                          this->rhs_, this->location());
668   Bexpression* rhs = conv->get_backend(context);
669   return context->backend()->assignment_statement(lhs, rhs, this->location());
670 }
671 
672 // Dump the AST representation for an assignment statement.
673 
674 void
do_dump_statement(Ast_dump_context * ast_dump_context) const675 Assignment_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
676     const
677 {
678   ast_dump_context->print_indent();
679   ast_dump_context->dump_expression(this->lhs_);
680   ast_dump_context->ostream() << " = " ;
681   ast_dump_context->dump_expression(this->rhs_);
682   ast_dump_context->ostream() << std::endl;
683 }
684 
685 // Make an assignment statement.
686 
687 Statement*
make_assignment(Expression * lhs,Expression * rhs,Location location)688 Statement::make_assignment(Expression* lhs, Expression* rhs,
689 			   Location location)
690 {
691   return new Assignment_statement(lhs, rhs, location);
692 }
693 
694 // The Move_subexpressions class is used to move all top-level
695 // subexpressions of an expression.  This is used for things like
696 // index expressions in which we must evaluate the index value before
697 // it can be changed by a multiple assignment.
698 
699 class Move_subexpressions : public Traverse
700 {
701  public:
Move_subexpressions(int skip,Block * block)702   Move_subexpressions(int skip, Block* block)
703     : Traverse(traverse_expressions),
704       skip_(skip), block_(block)
705   { }
706 
707  protected:
708   int
709   expression(Expression**);
710 
711  private:
712   // The number of subexpressions to skip moving.  This is used to
713   // avoid moving the array itself, as we only need to move the index.
714   int skip_;
715   // The block where new temporary variables should be added.
716   Block* block_;
717 };
718 
719 int
expression(Expression ** pexpr)720 Move_subexpressions::expression(Expression** pexpr)
721 {
722   if (this->skip_ > 0)
723     --this->skip_;
724   else if ((*pexpr)->temporary_reference_expression() == NULL
725 	   && !(*pexpr)->is_nil_expression()
726            && !(*pexpr)->is_constant())
727     {
728       Location loc = (*pexpr)->location();
729       Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
730       this->block_->add_statement(temp);
731       *pexpr = Expression::make_temporary_reference(temp, loc);
732     }
733   // We only need to move top-level subexpressions.
734   return TRAVERSE_SKIP_COMPONENTS;
735 }
736 
737 // The Move_ordered_evals class is used to find any subexpressions of
738 // an expression that have an evaluation order dependency.  It creates
739 // temporary variables to hold them.
740 
741 class Move_ordered_evals : public Traverse
742 {
743  public:
Move_ordered_evals(Block * block)744   Move_ordered_evals(Block* block)
745     : Traverse(traverse_expressions),
746       block_(block)
747   { }
748 
749  protected:
750   int
751   expression(Expression**);
752 
753  private:
754   // The block where new temporary variables should be added.
755   Block* block_;
756 };
757 
758 int
expression(Expression ** pexpr)759 Move_ordered_evals::expression(Expression** pexpr)
760 {
761   // We have to look at subexpressions first.
762   if ((*pexpr)->traverse_subexpressions(this) == TRAVERSE_EXIT)
763     return TRAVERSE_EXIT;
764 
765   int i;
766   if ((*pexpr)->must_eval_subexpressions_in_order(&i))
767     {
768       Move_subexpressions ms(i, this->block_);
769       if ((*pexpr)->traverse_subexpressions(&ms) == TRAVERSE_EXIT)
770 	return TRAVERSE_EXIT;
771     }
772 
773   if ((*pexpr)->must_eval_in_order())
774     {
775       Call_expression* call = (*pexpr)->call_expression();
776       if (call != NULL && call->is_multi_value_arg())
777 	{
778 	  // A call expression which returns multiple results as an argument
779 	  // to another call must be handled specially.  We can't create a
780 	  // temporary because there is no type to give it.  Instead, group
781 	  // the caller and this multi-valued call argument and use a temporary
782 	  // variable to hold them.
783 	  return TRAVERSE_SKIP_COMPONENTS;
784 	}
785 
786       Location loc = (*pexpr)->location();
787       Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
788       this->block_->add_statement(temp);
789       *pexpr = Expression::make_temporary_reference(temp, loc);
790     }
791   return TRAVERSE_SKIP_COMPONENTS;
792 }
793 
794 // An assignment operation statement.
795 
796 class Assignment_operation_statement : public Statement
797 {
798  public:
Assignment_operation_statement(Operator op,Expression * lhs,Expression * rhs,Location location)799   Assignment_operation_statement(Operator op, Expression* lhs, Expression* rhs,
800 				 Location location)
801     : Statement(STATEMENT_ASSIGNMENT_OPERATION, location),
802       op_(op), lhs_(lhs), rhs_(rhs)
803   { }
804 
805  protected:
806   int
807   do_traverse(Traverse*);
808 
809   bool
do_traverse_assignments(Traverse_assignments *)810   do_traverse_assignments(Traverse_assignments*)
811   { go_unreachable(); }
812 
813   Statement*
814   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
815 
816   Bstatement*
do_get_backend(Translate_context *)817   do_get_backend(Translate_context*)
818   { go_unreachable(); }
819 
820   void
821   do_dump_statement(Ast_dump_context*) const;
822 
823  private:
824   // The operator (OPERATOR_PLUSEQ, etc.).
825   Operator op_;
826   // Left hand side.
827   Expression* lhs_;
828   // Right hand side.
829   Expression* rhs_;
830 };
831 
832 // Traversal.
833 
834 int
do_traverse(Traverse * traverse)835 Assignment_operation_statement::do_traverse(Traverse* traverse)
836 {
837   if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
838     return TRAVERSE_EXIT;
839   return this->traverse_expression(traverse, &this->rhs_);
840 }
841 
842 // Lower an assignment operation statement to a regular assignment
843 // statement.
844 
845 Statement*
do_lower(Gogo *,Named_object *,Block * enclosing,Statement_inserter *)846 Assignment_operation_statement::do_lower(Gogo*, Named_object*,
847 					 Block* enclosing, Statement_inserter*)
848 {
849   Location loc = this->location();
850 
851   // We have to evaluate the left hand side expression only once.  We
852   // do this by moving out any expression with side effects.
853   Block* b = new Block(enclosing, loc);
854   Move_ordered_evals moe(b);
855   this->lhs_->traverse_subexpressions(&moe);
856 
857   Expression* lval = this->lhs_->copy();
858 
859   Operator op;
860   switch (this->op_)
861     {
862     case OPERATOR_PLUSEQ:
863       op = OPERATOR_PLUS;
864       break;
865     case OPERATOR_MINUSEQ:
866       op = OPERATOR_MINUS;
867       break;
868     case OPERATOR_OREQ:
869       op = OPERATOR_OR;
870       break;
871     case OPERATOR_XOREQ:
872       op = OPERATOR_XOR;
873       break;
874     case OPERATOR_MULTEQ:
875       op = OPERATOR_MULT;
876       break;
877     case OPERATOR_DIVEQ:
878       op = OPERATOR_DIV;
879       break;
880     case OPERATOR_MODEQ:
881       op = OPERATOR_MOD;
882       break;
883     case OPERATOR_LSHIFTEQ:
884       op = OPERATOR_LSHIFT;
885       break;
886     case OPERATOR_RSHIFTEQ:
887       op = OPERATOR_RSHIFT;
888       break;
889     case OPERATOR_ANDEQ:
890       op = OPERATOR_AND;
891       break;
892     case OPERATOR_BITCLEAREQ:
893       op = OPERATOR_BITCLEAR;
894       break;
895     default:
896       go_unreachable();
897     }
898 
899   Expression* binop = Expression::make_binary(op, lval, this->rhs_, loc);
900   Statement* s = Statement::make_assignment(this->lhs_, binop, loc);
901   if (b->statements()->empty())
902     {
903       delete b;
904       return s;
905     }
906   else
907     {
908       b->add_statement(s);
909       return Statement::make_block_statement(b, loc);
910     }
911 }
912 
913 // Dump the AST representation for an assignment operation statement
914 
915 void
do_dump_statement(Ast_dump_context * ast_dump_context) const916 Assignment_operation_statement::do_dump_statement(
917     Ast_dump_context* ast_dump_context) const
918 {
919   ast_dump_context->print_indent();
920   ast_dump_context->dump_expression(this->lhs_);
921   ast_dump_context->dump_operator(this->op_);
922   ast_dump_context->dump_expression(this->rhs_);
923   ast_dump_context->ostream() << std::endl;
924 }
925 
926 // Make an assignment operation statement.
927 
928 Statement*
make_assignment_operation(Operator op,Expression * lhs,Expression * rhs,Location location)929 Statement::make_assignment_operation(Operator op, Expression* lhs,
930 				     Expression* rhs, Location location)
931 {
932   return new Assignment_operation_statement(op, lhs, rhs, location);
933 }
934 
935 // A tuple assignment statement.  This differs from an assignment
936 // statement in that the right-hand-side expressions are evaluated in
937 // parallel.
938 
939 class Tuple_assignment_statement : public Statement
940 {
941  public:
Tuple_assignment_statement(Expression_list * lhs,Expression_list * rhs,Location location)942   Tuple_assignment_statement(Expression_list* lhs, Expression_list* rhs,
943 			     Location location)
944     : Statement(STATEMENT_TUPLE_ASSIGNMENT, location),
945       lhs_(lhs), rhs_(rhs)
946   { }
947 
948  protected:
949   int
950   do_traverse(Traverse* traverse);
951 
952   bool
do_traverse_assignments(Traverse_assignments *)953   do_traverse_assignments(Traverse_assignments*)
954   { go_unreachable(); }
955 
956   Statement*
957   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
958 
959   Bstatement*
do_get_backend(Translate_context *)960   do_get_backend(Translate_context*)
961   { go_unreachable(); }
962 
963   void
964   do_dump_statement(Ast_dump_context*) const;
965 
966  private:
967   // Left hand side--a list of lvalues.
968   Expression_list* lhs_;
969   // Right hand side--a list of rvalues.
970   Expression_list* rhs_;
971 };
972 
973 // Traversal.
974 
975 int
do_traverse(Traverse * traverse)976 Tuple_assignment_statement::do_traverse(Traverse* traverse)
977 {
978   if (this->traverse_expression_list(traverse, this->lhs_) == TRAVERSE_EXIT)
979     return TRAVERSE_EXIT;
980   return this->traverse_expression_list(traverse, this->rhs_);
981 }
982 
983 // Lower a tuple assignment.  We use temporary variables to split it
984 // up into a set of single assignments.
985 
986 Statement*
do_lower(Gogo *,Named_object *,Block * enclosing,Statement_inserter *)987 Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
988 				     Statement_inserter*)
989 {
990   Location loc = this->location();
991 
992   Block* b = new Block(enclosing, loc);
993 
994   // First move out any subexpressions on the left hand side.  The
995   // right hand side will be evaluated in the required order anyhow.
996   Move_ordered_evals moe(b);
997   for (Expression_list::iterator plhs = this->lhs_->begin();
998        plhs != this->lhs_->end();
999        ++plhs)
1000     Expression::traverse(&*plhs, &moe);
1001 
1002   std::vector<Temporary_statement*> temps;
1003   temps.reserve(this->lhs_->size());
1004 
1005   Expression_list::const_iterator prhs = this->rhs_->begin();
1006   for (Expression_list::const_iterator plhs = this->lhs_->begin();
1007        plhs != this->lhs_->end();
1008        ++plhs, ++prhs)
1009     {
1010       go_assert(prhs != this->rhs_->end());
1011 
1012       if ((*plhs)->is_error_expression()
1013 	  || (*plhs)->type()->is_error()
1014 	  || (*prhs)->is_error_expression()
1015 	  || (*prhs)->type()->is_error())
1016 	continue;
1017 
1018       if ((*plhs)->is_sink_expression())
1019 	{
1020           if ((*prhs)->type()->is_nil_type())
1021             this->report_error(_("use of untyped nil"));
1022           else
1023             b->add_statement(Statement::make_statement(*prhs, true));
1024 	  continue;
1025 	}
1026 
1027       Temporary_statement* temp = Statement::make_temporary((*plhs)->type(),
1028 							    *prhs, loc);
1029       b->add_statement(temp);
1030       temps.push_back(temp);
1031 
1032     }
1033   go_assert(prhs == this->rhs_->end());
1034 
1035   prhs = this->rhs_->begin();
1036   std::vector<Temporary_statement*>::const_iterator ptemp = temps.begin();
1037   for (Expression_list::const_iterator plhs = this->lhs_->begin();
1038        plhs != this->lhs_->end();
1039        ++plhs, ++prhs)
1040     {
1041       if ((*plhs)->is_error_expression()
1042 	  || (*plhs)->type()->is_error()
1043 	  || (*prhs)->is_error_expression()
1044 	  || (*prhs)->type()->is_error())
1045 	continue;
1046 
1047       if ((*plhs)->is_sink_expression())
1048 	continue;
1049 
1050       Expression* ref = Expression::make_temporary_reference(*ptemp, loc);
1051       b->add_statement(Statement::make_assignment(*plhs, ref, loc));
1052       ++ptemp;
1053     }
1054   go_assert(ptemp == temps.end() || saw_errors());
1055 
1056   return Statement::make_block_statement(b, loc);
1057 }
1058 
1059 // Dump the AST representation for a tuple assignment statement.
1060 
1061 void
do_dump_statement(Ast_dump_context * ast_dump_context) const1062 Tuple_assignment_statement::do_dump_statement(
1063     Ast_dump_context* ast_dump_context) const
1064 {
1065   ast_dump_context->print_indent();
1066   ast_dump_context->dump_expression_list(this->lhs_);
1067   ast_dump_context->ostream() << " = ";
1068   ast_dump_context->dump_expression_list(this->rhs_);
1069   ast_dump_context->ostream()  << std::endl;
1070 }
1071 
1072 // Make a tuple assignment statement.
1073 
1074 Statement*
make_tuple_assignment(Expression_list * lhs,Expression_list * rhs,Location location)1075 Statement::make_tuple_assignment(Expression_list* lhs, Expression_list* rhs,
1076 				 Location location)
1077 {
1078   return new Tuple_assignment_statement(lhs, rhs, location);
1079 }
1080 
1081 // A tuple assignment from a map index expression.
1082 //   v, ok = m[k]
1083 
1084 class Tuple_map_assignment_statement : public Statement
1085 {
1086 public:
Tuple_map_assignment_statement(Expression * val,Expression * present,Expression * map_index,Location location)1087   Tuple_map_assignment_statement(Expression* val, Expression* present,
1088 				 Expression* map_index,
1089 				 Location location)
1090     : Statement(STATEMENT_TUPLE_MAP_ASSIGNMENT, location),
1091       val_(val), present_(present), map_index_(map_index)
1092   { }
1093 
1094  protected:
1095   int
1096   do_traverse(Traverse* traverse);
1097 
1098   bool
do_traverse_assignments(Traverse_assignments *)1099   do_traverse_assignments(Traverse_assignments*)
1100   { go_unreachable(); }
1101 
1102   Statement*
1103   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1104 
1105   Bstatement*
do_get_backend(Translate_context *)1106   do_get_backend(Translate_context*)
1107   { go_unreachable(); }
1108 
1109   void
1110   do_dump_statement(Ast_dump_context*) const;
1111 
1112  private:
1113   // Lvalue which receives the value from the map.
1114   Expression* val_;
1115   // Lvalue which receives whether the key value was present.
1116   Expression* present_;
1117   // The map index expression.
1118   Expression* map_index_;
1119 };
1120 
1121 // Traversal.
1122 
1123 int
do_traverse(Traverse * traverse)1124 Tuple_map_assignment_statement::do_traverse(Traverse* traverse)
1125 {
1126   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
1127       || this->traverse_expression(traverse, &this->present_) == TRAVERSE_EXIT)
1128     return TRAVERSE_EXIT;
1129   return this->traverse_expression(traverse, &this->map_index_);
1130 }
1131 
1132 // Lower a tuple map assignment.
1133 
1134 Statement*
do_lower(Gogo *,Named_object *,Block * enclosing,Statement_inserter *)1135 Tuple_map_assignment_statement::do_lower(Gogo*, Named_object*,
1136 					 Block* enclosing, Statement_inserter*)
1137 {
1138   Location loc = this->location();
1139 
1140   Map_index_expression* map_index = this->map_index_->map_index_expression();
1141   if (map_index == NULL)
1142     {
1143       this->report_error(_("expected map index on right hand side"));
1144       return Statement::make_error_statement(loc);
1145     }
1146   Map_type* map_type = map_index->get_map_type();
1147   if (map_type == NULL)
1148     return Statement::make_error_statement(loc);
1149 
1150   Block* b = new Block(enclosing, loc);
1151 
1152   // Move out any subexpressions to make sure that functions are
1153   // called in the required order.
1154   Move_ordered_evals moe(b);
1155   this->val_->traverse_subexpressions(&moe);
1156   this->present_->traverse_subexpressions(&moe);
1157 
1158   // Copy the key value into a temporary so that we can take its
1159   // address without pushing the value onto the heap.
1160 
1161   // var key_temp KEY_TYPE = MAP_INDEX
1162   Temporary_statement* key_temp =
1163     Statement::make_temporary(map_type->key_type(), map_index->index(), loc);
1164   b->add_statement(key_temp);
1165 
1166   // var val_temp VAL_TYPE
1167   Temporary_statement* val_temp =
1168     Statement::make_temporary(map_type->val_type(), NULL, loc);
1169   b->add_statement(val_temp);
1170 
1171   // var present_temp bool
1172   Temporary_statement* present_temp =
1173     Statement::make_temporary((this->present_->type()->is_sink_type())
1174 			      ? Type::make_boolean_type()
1175 			      : this->present_->type(),
1176 			      NULL, loc);
1177   b->add_statement(present_temp);
1178 
1179   // present_temp = mapaccess2(DESCRIPTOR, MAP, &key_temp, &val_temp)
1180   Expression* a1 = Expression::make_type_descriptor(map_type, loc);
1181   Expression* a2 = map_index->map();
1182   Temporary_reference_expression* ref =
1183     Expression::make_temporary_reference(key_temp, loc);
1184   Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc);
1185   ref = Expression::make_temporary_reference(val_temp, loc);
1186   Expression* a4 = Expression::make_unary(OPERATOR_AND, ref, loc);
1187   Expression* call = Runtime::make_call(Runtime::MAPACCESS2, loc, 4,
1188 					a1, a2, a3, a4);
1189   ref = Expression::make_temporary_reference(present_temp, loc);
1190   ref->set_is_lvalue();
1191   Statement* s = Statement::make_assignment(ref, call, loc);
1192   b->add_statement(s);
1193 
1194   // val = val_temp
1195   ref = Expression::make_temporary_reference(val_temp, loc);
1196   s = Statement::make_assignment(this->val_, ref, loc);
1197   b->add_statement(s);
1198 
1199   // present = present_temp
1200   ref = Expression::make_temporary_reference(present_temp, loc);
1201   s = Statement::make_assignment(this->present_, ref, loc);
1202   b->add_statement(s);
1203 
1204   return Statement::make_block_statement(b, loc);
1205 }
1206 
1207 // Dump the AST representation for a tuple map assignment statement.
1208 
1209 void
do_dump_statement(Ast_dump_context * ast_dump_context) const1210 Tuple_map_assignment_statement::do_dump_statement(
1211     Ast_dump_context* ast_dump_context) const
1212 {
1213   ast_dump_context->print_indent();
1214   ast_dump_context->dump_expression(this->val_);
1215   ast_dump_context->ostream() << ", ";
1216   ast_dump_context->dump_expression(this->present_);
1217   ast_dump_context->ostream() << " = ";
1218   ast_dump_context->dump_expression(this->map_index_);
1219   ast_dump_context->ostream() << std::endl;
1220 }
1221 
1222 // Make a map assignment statement which returns a pair of values.
1223 
1224 Statement*
make_tuple_map_assignment(Expression * val,Expression * present,Expression * map_index,Location location)1225 Statement::make_tuple_map_assignment(Expression* val, Expression* present,
1226 				     Expression* map_index,
1227 				     Location location)
1228 {
1229   return new Tuple_map_assignment_statement(val, present, map_index, location);
1230 }
1231 
1232 // Assign a pair of entries to a map.
1233 //   m[k] = v, p
1234 
1235 class Map_assignment_statement : public Statement
1236 {
1237  public:
Map_assignment_statement(Expression * map_index,Expression * val,Expression * should_set,Location location)1238   Map_assignment_statement(Expression* map_index,
1239 			   Expression* val, Expression* should_set,
1240 			   Location location)
1241     : Statement(STATEMENT_MAP_ASSIGNMENT, location),
1242       map_index_(map_index), val_(val), should_set_(should_set)
1243   { }
1244 
1245  protected:
1246   int
1247   do_traverse(Traverse* traverse);
1248 
1249   bool
do_traverse_assignments(Traverse_assignments *)1250   do_traverse_assignments(Traverse_assignments*)
1251   { go_unreachable(); }
1252 
1253   Statement*
1254   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1255 
1256   Bstatement*
do_get_backend(Translate_context *)1257   do_get_backend(Translate_context*)
1258   { go_unreachable(); }
1259 
1260   void
1261   do_dump_statement(Ast_dump_context*) const;
1262 
1263  private:
1264   // A reference to the map index which should be set or deleted.
1265   Expression* map_index_;
1266   // The value to add to the map.
1267   Expression* val_;
1268   // Whether or not to add the value.
1269   Expression* should_set_;
1270 };
1271 
1272 // Traverse a map assignment.
1273 
1274 int
do_traverse(Traverse * traverse)1275 Map_assignment_statement::do_traverse(Traverse* traverse)
1276 {
1277   if (this->traverse_expression(traverse, &this->map_index_) == TRAVERSE_EXIT
1278       || this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
1279     return TRAVERSE_EXIT;
1280   return this->traverse_expression(traverse, &this->should_set_);
1281 }
1282 
1283 // Lower a map assignment to a function call.
1284 
1285 Statement*
do_lower(Gogo *,Named_object *,Block * enclosing,Statement_inserter *)1286 Map_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
1287 				   Statement_inserter*)
1288 {
1289   Location loc = this->location();
1290 
1291   Map_index_expression* map_index = this->map_index_->map_index_expression();
1292   if (map_index == NULL)
1293     {
1294       this->report_error(_("expected map index on left hand side"));
1295       return Statement::make_error_statement(loc);
1296     }
1297   Map_type* map_type = map_index->get_map_type();
1298   if (map_type == NULL)
1299     return Statement::make_error_statement(loc);
1300 
1301   Block* b = new Block(enclosing, loc);
1302 
1303   // Evaluate the map first to get order of evaluation right.
1304   // map_temp := m // we are evaluating m[k] = v, p
1305   Temporary_statement* map_temp = Statement::make_temporary(map_type,
1306 							    map_index->map(),
1307 							    loc);
1308   b->add_statement(map_temp);
1309 
1310   // var key_temp MAP_KEY_TYPE = k
1311   Temporary_statement* key_temp =
1312     Statement::make_temporary(map_type->key_type(), map_index->index(), loc);
1313   b->add_statement(key_temp);
1314 
1315   // var val_temp MAP_VAL_TYPE = v
1316   Temporary_statement* val_temp =
1317     Statement::make_temporary(map_type->val_type(), this->val_, loc);
1318   b->add_statement(val_temp);
1319 
1320   // var insert_temp bool = p
1321   Temporary_statement* insert_temp =
1322     Statement::make_temporary(Type::lookup_bool_type(), this->should_set_,
1323 			      loc);
1324   b->add_statement(insert_temp);
1325 
1326   // mapassign2(map_temp, &key_temp, &val_temp, p)
1327   Expression* p1 = Expression::make_temporary_reference(map_temp, loc);
1328   Expression* ref = Expression::make_temporary_reference(key_temp, loc);
1329   Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
1330   ref = Expression::make_temporary_reference(val_temp, loc);
1331   Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
1332   Expression* p4 = Expression::make_temporary_reference(insert_temp, loc);
1333   Expression* call = Runtime::make_call(Runtime::MAPASSIGN2, loc, 4,
1334 					p1, p2, p3, p4);
1335   Statement* s = Statement::make_statement(call, true);
1336   b->add_statement(s);
1337 
1338   return Statement::make_block_statement(b, loc);
1339 }
1340 
1341 // Dump the AST representation for a map assignment statement.
1342 
1343 void
do_dump_statement(Ast_dump_context * ast_dump_context) const1344 Map_assignment_statement::do_dump_statement(
1345     Ast_dump_context* ast_dump_context) const
1346 {
1347   ast_dump_context->print_indent();
1348   ast_dump_context->dump_expression(this->map_index_);
1349   ast_dump_context->ostream() << " = ";
1350   ast_dump_context->dump_expression(this->val_);
1351   ast_dump_context->ostream() << ", ";
1352   ast_dump_context->dump_expression(this->should_set_);
1353   ast_dump_context->ostream() << std::endl;
1354 }
1355 
1356 // Make a statement which assigns a pair of entries to a map.
1357 
1358 Statement*
make_map_assignment(Expression * map_index,Expression * val,Expression * should_set,Location location)1359 Statement::make_map_assignment(Expression* map_index,
1360 			       Expression* val, Expression* should_set,
1361 			       Location location)
1362 {
1363   return new Map_assignment_statement(map_index, val, should_set, location);
1364 }
1365 
1366 // A tuple assignment from a receive statement.
1367 
1368 class Tuple_receive_assignment_statement : public Statement
1369 {
1370  public:
Tuple_receive_assignment_statement(Expression * val,Expression * closed,Expression * channel,Location location)1371   Tuple_receive_assignment_statement(Expression* val, Expression* closed,
1372 				     Expression* channel, Location location)
1373     : Statement(STATEMENT_TUPLE_RECEIVE_ASSIGNMENT, location),
1374       val_(val), closed_(closed), channel_(channel)
1375   { }
1376 
1377  protected:
1378   int
1379   do_traverse(Traverse* traverse);
1380 
1381   bool
do_traverse_assignments(Traverse_assignments *)1382   do_traverse_assignments(Traverse_assignments*)
1383   { go_unreachable(); }
1384 
1385   Statement*
1386   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1387 
1388   Bstatement*
do_get_backend(Translate_context *)1389   do_get_backend(Translate_context*)
1390   { go_unreachable(); }
1391 
1392   void
1393   do_dump_statement(Ast_dump_context*) const;
1394 
1395  private:
1396   // Lvalue which receives the value from the channel.
1397   Expression* val_;
1398   // Lvalue which receives whether the channel is closed.
1399   Expression* closed_;
1400   // The channel on which we receive the value.
1401   Expression* channel_;
1402 };
1403 
1404 // Traversal.
1405 
1406 int
do_traverse(Traverse * traverse)1407 Tuple_receive_assignment_statement::do_traverse(Traverse* traverse)
1408 {
1409   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
1410       || this->traverse_expression(traverse, &this->closed_) == TRAVERSE_EXIT)
1411     return TRAVERSE_EXIT;
1412   return this->traverse_expression(traverse, &this->channel_);
1413 }
1414 
1415 // Lower to a function call.
1416 
1417 Statement*
do_lower(Gogo *,Named_object *,Block * enclosing,Statement_inserter *)1418 Tuple_receive_assignment_statement::do_lower(Gogo*, Named_object*,
1419 					     Block* enclosing,
1420 					     Statement_inserter*)
1421 {
1422   Location loc = this->location();
1423 
1424   Channel_type* channel_type = this->channel_->type()->channel_type();
1425   if (channel_type == NULL)
1426     {
1427       this->report_error(_("expected channel"));
1428       return Statement::make_error_statement(loc);
1429     }
1430   if (!channel_type->may_receive())
1431     {
1432       this->report_error(_("invalid receive on send-only channel"));
1433       return Statement::make_error_statement(loc);
1434     }
1435 
1436   Block* b = new Block(enclosing, loc);
1437 
1438   // Make sure that any subexpressions on the left hand side are
1439   // evaluated in the right order.
1440   Move_ordered_evals moe(b);
1441   this->val_->traverse_subexpressions(&moe);
1442   this->closed_->traverse_subexpressions(&moe);
1443 
1444   // var val_temp ELEMENT_TYPE
1445   Temporary_statement* val_temp =
1446     Statement::make_temporary(channel_type->element_type(), NULL, loc);
1447   b->add_statement(val_temp);
1448 
1449   // var closed_temp bool
1450   Temporary_statement* closed_temp =
1451     Statement::make_temporary((this->closed_->type()->is_sink_type())
1452 			      ? Type::make_boolean_type()
1453 			      : this->closed_->type(),
1454 			      NULL, loc);
1455   b->add_statement(closed_temp);
1456 
1457   // closed_temp = chanrecv2(type, channel, &val_temp)
1458   Expression* td = Expression::make_type_descriptor(this->channel_->type(),
1459 						    loc);
1460   Temporary_reference_expression* ref =
1461     Expression::make_temporary_reference(val_temp, loc);
1462   Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
1463   Expression* call = Runtime::make_call(Runtime::CHANRECV2,
1464 					loc, 3, td, this->channel_, p2);
1465   ref = Expression::make_temporary_reference(closed_temp, loc);
1466   ref->set_is_lvalue();
1467   Statement* s = Statement::make_assignment(ref, call, loc);
1468   b->add_statement(s);
1469 
1470   // val = val_temp
1471   ref = Expression::make_temporary_reference(val_temp, loc);
1472   s = Statement::make_assignment(this->val_, ref, loc);
1473   b->add_statement(s);
1474 
1475   // closed = closed_temp
1476   ref = Expression::make_temporary_reference(closed_temp, loc);
1477   s = Statement::make_assignment(this->closed_, ref, loc);
1478   b->add_statement(s);
1479 
1480   return Statement::make_block_statement(b, loc);
1481 }
1482 
1483 // Dump the AST representation for a tuple receive statement.
1484 
1485 void
do_dump_statement(Ast_dump_context * ast_dump_context) const1486 Tuple_receive_assignment_statement::do_dump_statement(
1487     Ast_dump_context* ast_dump_context) const
1488 {
1489   ast_dump_context->print_indent();
1490   ast_dump_context->dump_expression(this->val_);
1491   ast_dump_context->ostream() << ", ";
1492   ast_dump_context->dump_expression(this->closed_);
1493   ast_dump_context->ostream() << " <- ";
1494   ast_dump_context->dump_expression(this->channel_);
1495   ast_dump_context->ostream() << std::endl;
1496 }
1497 
1498 // Make a nonblocking receive statement.
1499 
1500 Statement*
make_tuple_receive_assignment(Expression * val,Expression * closed,Expression * channel,Location location)1501 Statement::make_tuple_receive_assignment(Expression* val, Expression* closed,
1502 					 Expression* channel,
1503 					 Location location)
1504 {
1505   return new Tuple_receive_assignment_statement(val, closed, channel,
1506 						location);
1507 }
1508 
1509 // An assignment to a pair of values from a type guard.  This is a
1510 // conditional type guard.  v, ok = i.(type).
1511 
1512 class Tuple_type_guard_assignment_statement : public Statement
1513 {
1514  public:
Tuple_type_guard_assignment_statement(Expression * val,Expression * ok,Expression * expr,Type * type,Location location)1515   Tuple_type_guard_assignment_statement(Expression* val, Expression* ok,
1516 					Expression* expr, Type* type,
1517 					Location location)
1518     : Statement(STATEMENT_TUPLE_TYPE_GUARD_ASSIGNMENT, location),
1519       val_(val), ok_(ok), expr_(expr), type_(type)
1520   { }
1521 
1522  protected:
1523   int
1524   do_traverse(Traverse*);
1525 
1526   bool
do_traverse_assignments(Traverse_assignments *)1527   do_traverse_assignments(Traverse_assignments*)
1528   { go_unreachable(); }
1529 
1530   Statement*
1531   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1532 
1533   Bstatement*
do_get_backend(Translate_context *)1534   do_get_backend(Translate_context*)
1535   { go_unreachable(); }
1536 
1537   void
1538   do_dump_statement(Ast_dump_context*) const;
1539 
1540  private:
1541   Call_expression*
1542   lower_to_type(Runtime::Function);
1543 
1544   void
1545   lower_to_object_type(Block*, Runtime::Function);
1546 
1547   // The variable which recieves the converted value.
1548   Expression* val_;
1549   // The variable which receives the indication of success.
1550   Expression* ok_;
1551   // The expression being converted.
1552   Expression* expr_;
1553   // The type to which the expression is being converted.
1554   Type* type_;
1555 };
1556 
1557 // Traverse a type guard tuple assignment.
1558 
1559 int
do_traverse(Traverse * traverse)1560 Tuple_type_guard_assignment_statement::do_traverse(Traverse* traverse)
1561 {
1562   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
1563       || this->traverse_expression(traverse, &this->ok_) == TRAVERSE_EXIT
1564       || this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
1565     return TRAVERSE_EXIT;
1566   return this->traverse_expression(traverse, &this->expr_);
1567 }
1568 
1569 // Lower to a function call.
1570 
1571 Statement*
do_lower(Gogo *,Named_object *,Block * enclosing,Statement_inserter *)1572 Tuple_type_guard_assignment_statement::do_lower(Gogo*, Named_object*,
1573 						Block* enclosing,
1574 						Statement_inserter*)
1575 {
1576   Location loc = this->location();
1577 
1578   Type* expr_type = this->expr_->type();
1579   if (expr_type->interface_type() == NULL)
1580     {
1581       if (!expr_type->is_error() && !this->type_->is_error())
1582 	this->report_error(_("type assertion only valid for interface types"));
1583       return Statement::make_error_statement(loc);
1584     }
1585 
1586   Block* b = new Block(enclosing, loc);
1587 
1588   // Make sure that any subexpressions on the left hand side are
1589   // evaluated in the right order.
1590   Move_ordered_evals moe(b);
1591   this->val_->traverse_subexpressions(&moe);
1592   this->ok_->traverse_subexpressions(&moe);
1593 
1594   bool expr_is_empty = expr_type->interface_type()->is_empty();
1595   Call_expression* call;
1596   if (this->type_->interface_type() != NULL)
1597     {
1598       if (this->type_->interface_type()->is_empty())
1599 	call = Runtime::make_call((expr_is_empty
1600 				   ? Runtime::IFACEE2E2
1601 				   : Runtime::IFACEI2E2),
1602 				  loc, 1, this->expr_);
1603       else
1604 	call = this->lower_to_type(expr_is_empty
1605 				   ? Runtime::IFACEE2I2
1606 				   : Runtime::IFACEI2I2);
1607     }
1608   else if (this->type_->points_to() != NULL)
1609     call = this->lower_to_type(expr_is_empty
1610 			       ? Runtime::IFACEE2T2P
1611 			       : Runtime::IFACEI2T2P);
1612   else
1613     {
1614       this->lower_to_object_type(b,
1615 				 (expr_is_empty
1616 				  ? Runtime::IFACEE2T2
1617 				  : Runtime::IFACEI2T2));
1618       call = NULL;
1619     }
1620 
1621   if (call != NULL)
1622     {
1623       Expression* res = Expression::make_call_result(call, 0);
1624       res = Expression::make_unsafe_cast(this->type_, res, loc);
1625       Statement* s = Statement::make_assignment(this->val_, res, loc);
1626       b->add_statement(s);
1627 
1628       res = Expression::make_call_result(call, 1);
1629       s = Statement::make_assignment(this->ok_, res, loc);
1630       b->add_statement(s);
1631     }
1632 
1633   return Statement::make_block_statement(b, loc);
1634 }
1635 
1636 // Lower a conversion to a non-empty interface type or a pointer type.
1637 
1638 Call_expression*
lower_to_type(Runtime::Function code)1639 Tuple_type_guard_assignment_statement::lower_to_type(Runtime::Function code)
1640 {
1641   Location loc = this->location();
1642   return Runtime::make_call(code, loc, 2,
1643 			    Expression::make_type_descriptor(this->type_, loc),
1644 			    this->expr_);
1645 }
1646 
1647 // Lower a conversion to a non-interface non-pointer type.
1648 
1649 void
lower_to_object_type(Block * b,Runtime::Function code)1650 Tuple_type_guard_assignment_statement::lower_to_object_type(
1651     Block* b,
1652     Runtime::Function code)
1653 {
1654   Location loc = this->location();
1655 
1656   // var val_temp TYPE
1657   Temporary_statement* val_temp = Statement::make_temporary(this->type_,
1658 							    NULL, loc);
1659   b->add_statement(val_temp);
1660 
1661   // ok = CODE(type_descriptor, expr, &val_temp)
1662   Expression* p1 = Expression::make_type_descriptor(this->type_, loc);
1663   Expression* ref = Expression::make_temporary_reference(val_temp, loc);
1664   Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
1665   Expression* call = Runtime::make_call(code, loc, 3, p1, this->expr_, p3);
1666   Statement* s = Statement::make_assignment(this->ok_, call, loc);
1667   b->add_statement(s);
1668 
1669   // val = val_temp
1670   ref = Expression::make_temporary_reference(val_temp, loc);
1671   s = Statement::make_assignment(this->val_, ref, loc);
1672   b->add_statement(s);
1673 }
1674 
1675 // Dump the AST representation for a tuple type guard statement.
1676 
1677 void
do_dump_statement(Ast_dump_context * ast_dump_context) const1678 Tuple_type_guard_assignment_statement::do_dump_statement(
1679     Ast_dump_context* ast_dump_context) const
1680 {
1681   ast_dump_context->print_indent();
1682   ast_dump_context->dump_expression(this->val_);
1683   ast_dump_context->ostream() << ", ";
1684   ast_dump_context->dump_expression(this->ok_);
1685   ast_dump_context->ostream() << " = ";
1686   ast_dump_context->dump_expression(this->expr_);
1687   ast_dump_context->ostream() << " . ";
1688   ast_dump_context->dump_type(this->type_);
1689   ast_dump_context->ostream()  << std::endl;
1690 }
1691 
1692 // Make an assignment from a type guard to a pair of variables.
1693 
1694 Statement*
make_tuple_type_guard_assignment(Expression * val,Expression * ok,Expression * expr,Type * type,Location location)1695 Statement::make_tuple_type_guard_assignment(Expression* val, Expression* ok,
1696 					    Expression* expr, Type* type,
1697 					    Location location)
1698 {
1699   return new Tuple_type_guard_assignment_statement(val, ok, expr, type,
1700 						   location);
1701 }
1702 
1703 // Class Expression_statement.
1704 
1705 // Constructor.
1706 
Expression_statement(Expression * expr,bool is_ignored)1707 Expression_statement::Expression_statement(Expression* expr, bool is_ignored)
1708   : Statement(STATEMENT_EXPRESSION, expr->location()),
1709     expr_(expr), is_ignored_(is_ignored)
1710 {
1711 }
1712 
1713 // Determine types.
1714 
1715 void
do_determine_types()1716 Expression_statement::do_determine_types()
1717 {
1718   this->expr_->determine_type_no_context();
1719 }
1720 
1721 // Check the types of an expression statement.  The only check we do
1722 // is to possibly give an error about discarding the value of the
1723 // expression.
1724 
1725 void
do_check_types(Gogo *)1726 Expression_statement::do_check_types(Gogo*)
1727 {
1728   if (!this->is_ignored_)
1729     this->expr_->discarding_value();
1730 }
1731 
1732 // An expression statement is only a terminating statement if it is
1733 // a call to panic.
1734 
1735 bool
do_may_fall_through() const1736 Expression_statement::do_may_fall_through() const
1737 {
1738   const Call_expression* call = this->expr_->call_expression();
1739   if (call != NULL)
1740     {
1741       const Expression* fn = call->fn();
1742       // panic is still an unknown named object.
1743       const Unknown_expression* ue = fn->unknown_expression();
1744       if (ue != NULL)
1745 	{
1746 	  Named_object* no = ue->named_object();
1747 
1748           if (no->is_unknown())
1749             no = no->unknown_value()->real_named_object();
1750           if (no != NULL)
1751             {
1752               Function_type* fntype;
1753               if (no->is_function())
1754                 fntype = no->func_value()->type();
1755               else if (no->is_function_declaration())
1756                 fntype = no->func_declaration_value()->type();
1757               else
1758                 fntype = NULL;
1759 
1760               // The builtin function panic does not return.
1761               if (fntype != NULL && fntype->is_builtin() && no->name() == "panic")
1762                 return false;
1763             }
1764 	}
1765     }
1766   return true;
1767 }
1768 
1769 // Convert to backend representation.
1770 
1771 Bstatement*
do_get_backend(Translate_context * context)1772 Expression_statement::do_get_backend(Translate_context* context)
1773 {
1774   Bexpression* bexpr = this->expr_->get_backend(context);
1775   return context->backend()->expression_statement(bexpr);
1776 }
1777 
1778 // Dump the AST representation for an expression statement
1779 
1780 void
do_dump_statement(Ast_dump_context * ast_dump_context) const1781 Expression_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
1782     const
1783 {
1784   ast_dump_context->print_indent();
1785   ast_dump_context->dump_expression(expr_);
1786   ast_dump_context->ostream() << std::endl;
1787 }
1788 
1789 // Make an expression statement from an Expression.
1790 
1791 Statement*
make_statement(Expression * expr,bool is_ignored)1792 Statement::make_statement(Expression* expr, bool is_ignored)
1793 {
1794   return new Expression_statement(expr, is_ignored);
1795 }
1796 
1797 // A block statement--a list of statements which may include variable
1798 // definitions.
1799 
1800 class Block_statement : public Statement
1801 {
1802  public:
Block_statement(Block * block,Location location)1803   Block_statement(Block* block, Location location)
1804     : Statement(STATEMENT_BLOCK, location),
1805       block_(block)
1806   { }
1807 
1808  protected:
1809   int
do_traverse(Traverse * traverse)1810   do_traverse(Traverse* traverse)
1811   { return this->block_->traverse(traverse); }
1812 
1813   void
do_determine_types()1814   do_determine_types()
1815   { this->block_->determine_types(); }
1816 
1817   bool
do_may_fall_through() const1818   do_may_fall_through() const
1819   { return this->block_->may_fall_through(); }
1820 
1821   Bstatement*
1822   do_get_backend(Translate_context* context);
1823 
1824   void
1825   do_dump_statement(Ast_dump_context*) const;
1826 
1827  private:
1828   Block* block_;
1829 };
1830 
1831 // Convert a block to the backend representation of a statement.
1832 
1833 Bstatement*
do_get_backend(Translate_context * context)1834 Block_statement::do_get_backend(Translate_context* context)
1835 {
1836   Bblock* bblock = this->block_->get_backend(context);
1837   return context->backend()->block_statement(bblock);
1838 }
1839 
1840 // Dump the AST for a block statement
1841 
1842 void
do_dump_statement(Ast_dump_context *) const1843 Block_statement::do_dump_statement(Ast_dump_context*) const
1844 {
1845   // block statement braces are dumped when traversing.
1846 }
1847 
1848 // Make a block statement.
1849 
1850 Statement*
make_block_statement(Block * block,Location location)1851 Statement::make_block_statement(Block* block, Location location)
1852 {
1853   return new Block_statement(block, location);
1854 }
1855 
1856 // An increment or decrement statement.
1857 
1858 class Inc_dec_statement : public Statement
1859 {
1860  public:
Inc_dec_statement(bool is_inc,Expression * expr)1861   Inc_dec_statement(bool is_inc, Expression* expr)
1862     : Statement(STATEMENT_INCDEC, expr->location()),
1863       expr_(expr), is_inc_(is_inc)
1864   { }
1865 
1866  protected:
1867   int
do_traverse(Traverse * traverse)1868   do_traverse(Traverse* traverse)
1869   { return this->traverse_expression(traverse, &this->expr_); }
1870 
1871   bool
do_traverse_assignments(Traverse_assignments *)1872   do_traverse_assignments(Traverse_assignments*)
1873   { go_unreachable(); }
1874 
1875   Statement*
1876   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1877 
1878   Bstatement*
do_get_backend(Translate_context *)1879   do_get_backend(Translate_context*)
1880   { go_unreachable(); }
1881 
1882   void
1883   do_dump_statement(Ast_dump_context*) const;
1884 
1885  private:
1886   // The l-value to increment or decrement.
1887   Expression* expr_;
1888   // Whether to increment or decrement.
1889   bool is_inc_;
1890 };
1891 
1892 // Lower to += or -=.
1893 
1894 Statement*
do_lower(Gogo *,Named_object *,Block *,Statement_inserter *)1895 Inc_dec_statement::do_lower(Gogo*, Named_object*, Block*, Statement_inserter*)
1896 {
1897   Location loc = this->location();
1898   Expression* oexpr = Expression::make_integer_ul(1, this->expr_->type(), loc);
1899   Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ;
1900   return Statement::make_assignment_operation(op, this->expr_, oexpr, loc);
1901 }
1902 
1903 // Dump the AST representation for a inc/dec statement.
1904 
1905 void
do_dump_statement(Ast_dump_context * ast_dump_context) const1906 Inc_dec_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
1907 {
1908   ast_dump_context->print_indent();
1909   ast_dump_context->dump_expression(expr_);
1910   ast_dump_context->ostream() << (is_inc_? "++": "--") << std::endl;
1911 }
1912 
1913 // Make an increment statement.
1914 
1915 Statement*
make_inc_statement(Expression * expr)1916 Statement::make_inc_statement(Expression* expr)
1917 {
1918   return new Inc_dec_statement(true, expr);
1919 }
1920 
1921 // Make a decrement statement.
1922 
1923 Statement*
make_dec_statement(Expression * expr)1924 Statement::make_dec_statement(Expression* expr)
1925 {
1926   return new Inc_dec_statement(false, expr);
1927 }
1928 
1929 // Class Thunk_statement.  This is the base class for go and defer
1930 // statements.
1931 
1932 Unordered_set(const Struct_type*) Thunk_statement::thunk_types;
1933 
1934 // Constructor.
1935 
Thunk_statement(Statement_classification classification,Call_expression * call,Location location)1936 Thunk_statement::Thunk_statement(Statement_classification classification,
1937 				 Call_expression* call,
1938 				 Location location)
1939     : Statement(classification, location),
1940       call_(call), struct_type_(NULL)
1941 {
1942 }
1943 
1944 // Return whether this is a simple statement which does not require a
1945 // thunk.
1946 
1947 bool
is_simple(Function_type * fntype) const1948 Thunk_statement::is_simple(Function_type* fntype) const
1949 {
1950   // We need a thunk to call a method, or to pass a variable number of
1951   // arguments.
1952   if (fntype->is_method() || fntype->is_varargs())
1953     return false;
1954 
1955   // A defer statement requires a thunk to set up for whether the
1956   // function can call recover.
1957   if (this->classification() == STATEMENT_DEFER)
1958     return false;
1959 
1960   // We can only permit a single parameter of pointer type.
1961   const Typed_identifier_list* parameters = fntype->parameters();
1962   if (parameters != NULL
1963       && (parameters->size() > 1
1964 	  || (parameters->size() == 1
1965 	      && parameters->begin()->type()->points_to() == NULL)))
1966     return false;
1967 
1968   // If the function returns multiple values, or returns a type other
1969   // than integer, floating point, or pointer, then it may get a
1970   // hidden first parameter, in which case we need the more
1971   // complicated approach.  This is true even though we are going to
1972   // ignore the return value.
1973   const Typed_identifier_list* results = fntype->results();
1974   if (results != NULL
1975       && (results->size() > 1
1976 	  || (results->size() == 1
1977 	      && !results->begin()->type()->is_basic_type()
1978 	      && results->begin()->type()->points_to() == NULL)))
1979     return false;
1980 
1981   // If this calls something that is not a simple function, then we
1982   // need a thunk.
1983   Expression* fn = this->call_->call_expression()->fn();
1984   if (fn->func_expression() == NULL)
1985     return false;
1986 
1987   // If the function uses a closure, then we need a thunk.  FIXME: We
1988   // could accept a zero argument function with a closure.
1989   if (fn->func_expression()->closure() != NULL)
1990     return false;
1991 
1992   return true;
1993 }
1994 
1995 // Traverse a thunk statement.
1996 
1997 int
do_traverse(Traverse * traverse)1998 Thunk_statement::do_traverse(Traverse* traverse)
1999 {
2000   return this->traverse_expression(traverse, &this->call_);
2001 }
2002 
2003 // We implement traverse_assignment for a thunk statement because it
2004 // effectively copies the function call.
2005 
2006 bool
do_traverse_assignments(Traverse_assignments * tassign)2007 Thunk_statement::do_traverse_assignments(Traverse_assignments* tassign)
2008 {
2009   Expression* fn = this->call_->call_expression()->fn();
2010   Expression* fn2 = fn;
2011   tassign->value(&fn2, true, false);
2012   return true;
2013 }
2014 
2015 // Determine types in a thunk statement.
2016 
2017 void
do_determine_types()2018 Thunk_statement::do_determine_types()
2019 {
2020   this->call_->determine_type_no_context();
2021 
2022   // Now that we know the types of the call, build the struct used to
2023   // pass parameters.
2024   Call_expression* ce = this->call_->call_expression();
2025   if (ce == NULL)
2026     return;
2027   Function_type* fntype = ce->get_function_type();
2028   if (fntype != NULL && !this->is_simple(fntype))
2029     this->struct_type_ = this->build_struct(fntype);
2030 }
2031 
2032 // Check types in a thunk statement.
2033 
2034 void
do_check_types(Gogo *)2035 Thunk_statement::do_check_types(Gogo*)
2036 {
2037   if (!this->call_->discarding_value())
2038     return;
2039   Call_expression* ce = this->call_->call_expression();
2040   if (ce == NULL)
2041     {
2042       if (!this->call_->is_error_expression())
2043 	this->report_error("expected call expression");
2044       return;
2045     }
2046 }
2047 
2048 // The Traverse class used to find and simplify thunk statements.
2049 
2050 class Simplify_thunk_traverse : public Traverse
2051 {
2052  public:
Simplify_thunk_traverse(Gogo * gogo)2053   Simplify_thunk_traverse(Gogo* gogo)
2054     : Traverse(traverse_functions | traverse_blocks),
2055       gogo_(gogo), function_(NULL)
2056   { }
2057 
2058   int
2059   function(Named_object*);
2060 
2061   int
2062   block(Block*);
2063 
2064  private:
2065   // General IR.
2066   Gogo* gogo_;
2067   // The function we are traversing.
2068   Named_object* function_;
2069 };
2070 
2071 // Keep track of the current function while looking for thunks.
2072 
2073 int
function(Named_object * no)2074 Simplify_thunk_traverse::function(Named_object* no)
2075 {
2076   go_assert(this->function_ == NULL);
2077   this->function_ = no;
2078   int t = no->func_value()->traverse(this);
2079   this->function_ = NULL;
2080   if (t == TRAVERSE_EXIT)
2081     return t;
2082   return TRAVERSE_SKIP_COMPONENTS;
2083 }
2084 
2085 // Look for thunks in a block.
2086 
2087 int
block(Block * b)2088 Simplify_thunk_traverse::block(Block* b)
2089 {
2090   // The parser ensures that thunk statements always appear at the end
2091   // of a block.
2092   if (b->statements()->size() < 1)
2093     return TRAVERSE_CONTINUE;
2094   Thunk_statement* stat = b->statements()->back()->thunk_statement();
2095   if (stat == NULL)
2096     return TRAVERSE_CONTINUE;
2097   if (stat->simplify_statement(this->gogo_, this->function_, b))
2098     return TRAVERSE_SKIP_COMPONENTS;
2099   return TRAVERSE_CONTINUE;
2100 }
2101 
2102 // Simplify all thunk statements.
2103 
2104 void
simplify_thunk_statements()2105 Gogo::simplify_thunk_statements()
2106 {
2107   Simplify_thunk_traverse thunk_traverse(this);
2108   this->traverse(&thunk_traverse);
2109 }
2110 
2111 // Return true if the thunk function is a constant, which means that
2112 // it does not need to be passed to the thunk routine.
2113 
2114 bool
is_constant_function() const2115 Thunk_statement::is_constant_function() const
2116 {
2117   Call_expression* ce = this->call_->call_expression();
2118   Function_type* fntype = ce->get_function_type();
2119   if (fntype == NULL)
2120     {
2121       go_assert(saw_errors());
2122       return false;
2123     }
2124   if (fntype->is_builtin())
2125     return true;
2126   Expression* fn = ce->fn();
2127   if (fn->func_expression() != NULL)
2128     return fn->func_expression()->closure() == NULL;
2129   if (fn->interface_field_reference_expression() != NULL)
2130     return true;
2131   return false;
2132 }
2133 
2134 // Simplify complex thunk statements into simple ones.  A complicated
2135 // thunk statement is one which takes anything other than zero
2136 // parameters or a single pointer parameter.  We rewrite it into code
2137 // which allocates a struct, stores the parameter values into the
2138 // struct, and does a simple go or defer statement which passes the
2139 // struct to a thunk.  The thunk does the real call.
2140 
2141 bool
simplify_statement(Gogo * gogo,Named_object * function,Block * block)2142 Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
2143 				    Block* block)
2144 {
2145   if (this->classification() == STATEMENT_ERROR)
2146     return false;
2147   if (this->call_->is_error_expression())
2148     return false;
2149 
2150   if (this->classification() == STATEMENT_DEFER)
2151     {
2152       // Make sure that the defer stack exists for the function.  We
2153       // will use when converting this statement to the backend
2154       // representation, but we want it to exist when we start
2155       // converting the function.
2156       function->func_value()->defer_stack(this->location());
2157     }
2158 
2159   Call_expression* ce = this->call_->call_expression();
2160   Function_type* fntype = ce->get_function_type();
2161   if (fntype == NULL)
2162     {
2163       go_assert(saw_errors());
2164       this->set_is_error();
2165       return false;
2166     }
2167   if (this->is_simple(fntype))
2168     return false;
2169 
2170   Expression* fn = ce->fn();
2171   Interface_field_reference_expression* interface_method =
2172     fn->interface_field_reference_expression();
2173 
2174   Location location = this->location();
2175 
2176   std::string thunk_name = Gogo::thunk_name();
2177 
2178   // Build the thunk.
2179   this->build_thunk(gogo, thunk_name);
2180 
2181   // Generate code to call the thunk.
2182 
2183   // Get the values to store into the struct which is the single
2184   // argument to the thunk.
2185 
2186   Expression_list* vals = new Expression_list();
2187   if (!this->is_constant_function())
2188     vals->push_back(fn);
2189 
2190   if (interface_method != NULL)
2191     vals->push_back(interface_method->expr());
2192 
2193   if (ce->args() != NULL)
2194     {
2195       for (Expression_list::const_iterator p = ce->args()->begin();
2196 	   p != ce->args()->end();
2197 	   ++p)
2198 	{
2199 	  if ((*p)->is_constant())
2200 	    continue;
2201 	  vals->push_back(*p);
2202 	}
2203     }
2204 
2205   // Build the struct.
2206   Expression* constructor =
2207     Expression::make_struct_composite_literal(this->struct_type_, vals,
2208 					      location);
2209 
2210   // Allocate the initialized struct on the heap.
2211   constructor = Expression::make_heap_expression(constructor, location);
2212 
2213   // Look up the thunk.
2214   Named_object* named_thunk = gogo->lookup(thunk_name, NULL);
2215   go_assert(named_thunk != NULL && named_thunk->is_function());
2216 
2217   // Build the call.
2218   Expression* func = Expression::make_func_reference(named_thunk, NULL,
2219 						     location);
2220   Expression_list* params = new Expression_list();
2221   params->push_back(constructor);
2222   Call_expression* call = Expression::make_call(func, params, false, location);
2223 
2224   // Build the simple go or defer statement.
2225   Statement* s;
2226   if (this->classification() == STATEMENT_GO)
2227     s = Statement::make_go_statement(call, location);
2228   else if (this->classification() == STATEMENT_DEFER)
2229     s = Statement::make_defer_statement(call, location);
2230   else
2231     go_unreachable();
2232 
2233   // The current block should end with the go statement.
2234   go_assert(block->statements()->size() >= 1);
2235   go_assert(block->statements()->back() == this);
2236   block->replace_statement(block->statements()->size() - 1, s);
2237 
2238   // We already ran the determine_types pass, so we need to run it now
2239   // for the new statement.
2240   s->determine_types();
2241 
2242   // Sanity check.
2243   gogo->check_types_in_block(block);
2244 
2245   // Return true to tell the block not to keep looking at statements.
2246   return true;
2247 }
2248 
2249 // Set the name to use for thunk parameter N.
2250 
2251 void
thunk_field_param(int n,char * buf,size_t buflen)2252 Thunk_statement::thunk_field_param(int n, char* buf, size_t buflen)
2253 {
2254   snprintf(buf, buflen, "a%d", n);
2255 }
2256 
2257 // Build a new struct type to hold the parameters for a complicated
2258 // thunk statement.  FNTYPE is the type of the function call.
2259 
2260 Struct_type*
build_struct(Function_type * fntype)2261 Thunk_statement::build_struct(Function_type* fntype)
2262 {
2263   Location location = this->location();
2264 
2265   Struct_field_list* fields = new Struct_field_list();
2266 
2267   Call_expression* ce = this->call_->call_expression();
2268   Expression* fn = ce->fn();
2269 
2270   if (!this->is_constant_function())
2271     {
2272       // The function to call.
2273       fields->push_back(Struct_field(Typed_identifier("fn", fntype,
2274 						      location)));
2275     }
2276 
2277   // If this thunk statement calls a method on an interface, we pass
2278   // the interface object to the thunk.
2279   Interface_field_reference_expression* interface_method =
2280     fn->interface_field_reference_expression();
2281   if (interface_method != NULL)
2282     {
2283       Typed_identifier tid("object", interface_method->expr()->type(),
2284 			   location);
2285       fields->push_back(Struct_field(tid));
2286     }
2287 
2288   // The predeclared recover function has no argument.  However, we
2289   // add an argument when building recover thunks.  Handle that here.
2290   if (ce->is_recover_call())
2291     {
2292       fields->push_back(Struct_field(Typed_identifier("can_recover",
2293 						      Type::lookup_bool_type(),
2294 						      location)));
2295     }
2296 
2297   const Expression_list* args = ce->args();
2298   if (args != NULL)
2299     {
2300       int i = 0;
2301       for (Expression_list::const_iterator p = args->begin();
2302 	   p != args->end();
2303 	   ++p, ++i)
2304 	{
2305 	  if ((*p)->is_constant())
2306 	    continue;
2307 
2308 	  char buf[50];
2309 	  this->thunk_field_param(i, buf, sizeof buf);
2310 	  fields->push_back(Struct_field(Typed_identifier(buf, (*p)->type(),
2311 							  location)));
2312 	}
2313     }
2314 
2315   Struct_type *st = Type::make_struct_type(fields, location);
2316 
2317   Thunk_statement::thunk_types.insert(st);
2318 
2319   return st;
2320 }
2321 
2322 // Return whether ST is a type created to hold thunk parameters.
2323 
2324 bool
is_thunk_struct(const Struct_type * st)2325 Thunk_statement::is_thunk_struct(const Struct_type* st)
2326 {
2327   return (Thunk_statement::thunk_types.find(st)
2328 	  != Thunk_statement::thunk_types.end());
2329 }
2330 
2331 // Build the thunk we are going to call.  This is a brand new, albeit
2332 // artificial, function.
2333 
2334 void
build_thunk(Gogo * gogo,const std::string & thunk_name)2335 Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
2336 {
2337   Location location = this->location();
2338 
2339   Call_expression* ce = this->call_->call_expression();
2340 
2341   bool may_call_recover = false;
2342   if (this->classification() == STATEMENT_DEFER)
2343     {
2344       Func_expression* fn = ce->fn()->func_expression();
2345       if (fn == NULL)
2346 	may_call_recover = true;
2347       else
2348 	{
2349 	  const Named_object* no = fn->named_object();
2350 	  if (!no->is_function())
2351 	    may_call_recover = true;
2352 	  else
2353 	    may_call_recover = no->func_value()->calls_recover();
2354 	}
2355     }
2356 
2357   // Build the type of the thunk.  The thunk takes a single parameter,
2358   // which is a pointer to the special structure we build.
2359   const char* const parameter_name = "__go_thunk_parameter";
2360   Typed_identifier_list* thunk_parameters = new Typed_identifier_list();
2361   Type* pointer_to_struct_type = Type::make_pointer_type(this->struct_type_);
2362   thunk_parameters->push_back(Typed_identifier(parameter_name,
2363 					       pointer_to_struct_type,
2364 					       location));
2365 
2366   Typed_identifier_list* thunk_results = NULL;
2367   if (may_call_recover)
2368     {
2369       // When deferring a function which may call recover, add a
2370       // return value, to disable tail call optimizations which will
2371       // break the way we check whether recover is permitted.
2372       thunk_results = new Typed_identifier_list();
2373       thunk_results->push_back(Typed_identifier("", Type::lookup_bool_type(),
2374 						location));
2375     }
2376 
2377   Function_type* thunk_type = Type::make_function_type(NULL, thunk_parameters,
2378 						       thunk_results,
2379 						       location);
2380 
2381   // Start building the thunk.
2382   Named_object* function = gogo->start_function(thunk_name, thunk_type, true,
2383 						location);
2384 
2385   gogo->start_block(location);
2386 
2387   // For a defer statement, start with a call to
2388   // __go_set_defer_retaddr.  */
2389   Label* retaddr_label = NULL;
2390   if (may_call_recover)
2391     {
2392       retaddr_label = gogo->add_label_reference("retaddr", location, false);
2393       Expression* arg = Expression::make_label_addr(retaddr_label, location);
2394       Expression* call = Runtime::make_call(Runtime::SET_DEFER_RETADDR,
2395 					    location, 1, arg);
2396 
2397       // This is a hack to prevent the middle-end from deleting the
2398       // label.
2399       gogo->start_block(location);
2400       gogo->add_statement(Statement::make_goto_statement(retaddr_label,
2401 							 location));
2402       Block* then_block = gogo->finish_block(location);
2403       then_block->determine_types();
2404 
2405       Statement* s = Statement::make_if_statement(call, then_block, NULL,
2406 						  location);
2407       s->determine_types();
2408       gogo->add_statement(s);
2409 
2410       function->func_value()->set_calls_defer_retaddr();
2411     }
2412 
2413   // Get a reference to the parameter.
2414   Named_object* named_parameter = gogo->lookup(parameter_name, NULL);
2415   go_assert(named_parameter != NULL && named_parameter->is_variable());
2416 
2417   // Build the call.  Note that the field names are the same as the
2418   // ones used in build_struct.
2419   Expression* thunk_parameter = Expression::make_var_reference(named_parameter,
2420 							       location);
2421   thunk_parameter = Expression::make_unary(OPERATOR_MULT, thunk_parameter,
2422 					   location);
2423 
2424   Interface_field_reference_expression* interface_method =
2425     ce->fn()->interface_field_reference_expression();
2426 
2427   Expression* func_to_call;
2428   unsigned int next_index;
2429   if (this->is_constant_function())
2430     {
2431       func_to_call = ce->fn();
2432       next_index = 0;
2433     }
2434   else
2435     {
2436       func_to_call = Expression::make_field_reference(thunk_parameter,
2437 						      0, location);
2438       next_index = 1;
2439     }
2440 
2441   if (interface_method != NULL)
2442     {
2443       // The main program passes the interface object.
2444       go_assert(next_index == 0);
2445       Expression* r = Expression::make_field_reference(thunk_parameter, 0,
2446 						       location);
2447       const std::string& name(interface_method->name());
2448       func_to_call = Expression::make_interface_field_reference(r, name,
2449 								location);
2450       next_index = 1;
2451     }
2452 
2453   Expression_list* call_params = new Expression_list();
2454   const Struct_field_list* fields = this->struct_type_->fields();
2455   Struct_field_list::const_iterator p = fields->begin();
2456   for (unsigned int i = 0; i < next_index; ++i)
2457     ++p;
2458   bool is_recover_call = ce->is_recover_call();
2459   Expression* recover_arg = NULL;
2460 
2461   const Expression_list* args = ce->args();
2462   if (args != NULL)
2463     {
2464       for (Expression_list::const_iterator arg = args->begin();
2465 	   arg != args->end();
2466 	   ++arg)
2467 	{
2468 	  Expression* param;
2469 	  if ((*arg)->is_constant())
2470 	    param = *arg;
2471 	  else
2472 	    {
2473 	      Expression* thunk_param =
2474 		Expression::make_var_reference(named_parameter, location);
2475 	      thunk_param =
2476 		Expression::make_unary(OPERATOR_MULT, thunk_param, location);
2477 	      param = Expression::make_field_reference(thunk_param,
2478 						       next_index,
2479 						       location);
2480 	      ++next_index;
2481 	    }
2482 
2483 	  if (!is_recover_call)
2484 	    call_params->push_back(param);
2485 	  else
2486 	    {
2487 	      go_assert(call_params->empty());
2488 	      recover_arg = param;
2489 	    }
2490 	}
2491     }
2492 
2493   if (call_params->empty())
2494     {
2495       delete call_params;
2496       call_params = NULL;
2497     }
2498 
2499   Call_expression* call = Expression::make_call(func_to_call, call_params,
2500 						false, location);
2501 
2502   // This call expression was already lowered before entering the
2503   // thunk statement.  Don't try to lower varargs again, as that will
2504   // cause confusion for, e.g., method calls which already have a
2505   // receiver parameter.
2506   call->set_varargs_are_lowered();
2507 
2508   Statement* call_statement = Statement::make_statement(call, true);
2509 
2510   gogo->add_statement(call_statement);
2511 
2512   // If this is a defer statement, the label comes immediately after
2513   // the call.
2514   if (may_call_recover)
2515     {
2516       gogo->add_label_definition("retaddr", location);
2517 
2518       Expression_list* vals = new Expression_list();
2519       vals->push_back(Expression::make_boolean(false, location));
2520       gogo->add_statement(Statement::make_return_statement(vals, location));
2521     }
2522 
2523   Block* b = gogo->finish_block(location);
2524 
2525   gogo->add_block(b, location);
2526 
2527   gogo->lower_block(function, b);
2528 
2529   // We already ran the determine_types pass, so we need to run it
2530   // just for the call statement now.  The other types are known.
2531   call_statement->determine_types();
2532 
2533   gogo->flatten_block(function, b);
2534 
2535   if (may_call_recover || recover_arg != NULL)
2536     {
2537       // Dig up the call expression, which may have been changed
2538       // during lowering.
2539       go_assert(call_statement->classification() == STATEMENT_EXPRESSION);
2540       Expression_statement* es =
2541 	static_cast<Expression_statement*>(call_statement);
2542       Call_expression* ce = es->expr()->call_expression();
2543       if (ce == NULL)
2544 	go_assert(saw_errors());
2545       else
2546 	{
2547 	  if (may_call_recover)
2548 	    ce->set_is_deferred();
2549 	  if (recover_arg != NULL)
2550 	    ce->set_recover_arg(recover_arg);
2551 	}
2552     }
2553 
2554   // That is all the thunk has to do.
2555   gogo->finish_function(location);
2556 }
2557 
2558 // Get the function and argument expressions.
2559 
2560 bool
get_fn_and_arg(Expression ** pfn,Expression ** parg)2561 Thunk_statement::get_fn_and_arg(Expression** pfn, Expression** parg)
2562 {
2563   if (this->call_->is_error_expression())
2564     return false;
2565 
2566   Call_expression* ce = this->call_->call_expression();
2567 
2568   Expression* fn = ce->fn();
2569   Func_expression* fe = fn->func_expression();
2570   go_assert(fe != NULL);
2571   *pfn = Expression::make_func_code_reference(fe->named_object(),
2572 					      fe->location());
2573 
2574   const Expression_list* args = ce->args();
2575   if (args == NULL || args->empty())
2576     *parg = Expression::make_nil(this->location());
2577   else
2578     {
2579       go_assert(args->size() == 1);
2580       *parg = args->front();
2581     }
2582 
2583   return true;
2584 }
2585 
2586 // Class Go_statement.
2587 
2588 Bstatement*
do_get_backend(Translate_context * context)2589 Go_statement::do_get_backend(Translate_context* context)
2590 {
2591   Expression* fn;
2592   Expression* arg;
2593   if (!this->get_fn_and_arg(&fn, &arg))
2594     return context->backend()->error_statement();
2595 
2596   Expression* call = Runtime::make_call(Runtime::GO, this->location(), 2,
2597 					fn, arg);
2598   Bexpression* bcall = call->get_backend(context);
2599   return context->backend()->expression_statement(bcall);
2600 }
2601 
2602 // Dump the AST representation for go statement.
2603 
2604 void
do_dump_statement(Ast_dump_context * ast_dump_context) const2605 Go_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2606 {
2607   ast_dump_context->print_indent();
2608   ast_dump_context->ostream() << "go ";
2609   ast_dump_context->dump_expression(this->call());
2610   ast_dump_context->ostream() << std::endl;
2611 }
2612 
2613 // Make a go statement.
2614 
2615 Statement*
make_go_statement(Call_expression * call,Location location)2616 Statement::make_go_statement(Call_expression* call, Location location)
2617 {
2618   return new Go_statement(call, location);
2619 }
2620 
2621 // Class Defer_statement.
2622 
2623 Bstatement*
do_get_backend(Translate_context * context)2624 Defer_statement::do_get_backend(Translate_context* context)
2625 {
2626   Expression* fn;
2627   Expression* arg;
2628   if (!this->get_fn_and_arg(&fn, &arg))
2629     return context->backend()->error_statement();
2630 
2631   Location loc = this->location();
2632   Expression* ds = context->function()->func_value()->defer_stack(loc);
2633 
2634   Expression* call = Runtime::make_call(Runtime::DEFER, loc, 3,
2635 					ds, fn, arg);
2636   Bexpression* bcall = call->get_backend(context);
2637   return context->backend()->expression_statement(bcall);
2638 }
2639 
2640 // Dump the AST representation for defer statement.
2641 
2642 void
do_dump_statement(Ast_dump_context * ast_dump_context) const2643 Defer_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2644 {
2645   ast_dump_context->print_indent();
2646   ast_dump_context->ostream() << "defer ";
2647   ast_dump_context->dump_expression(this->call());
2648   ast_dump_context->ostream() << std::endl;
2649 }
2650 
2651 // Make a defer statement.
2652 
2653 Statement*
make_defer_statement(Call_expression * call,Location location)2654 Statement::make_defer_statement(Call_expression* call,
2655 				Location location)
2656 {
2657   return new Defer_statement(call, location);
2658 }
2659 
2660 // Class Return_statement.
2661 
2662 // Traverse assignments.  We treat each return value as a top level
2663 // RHS in an expression.
2664 
2665 bool
do_traverse_assignments(Traverse_assignments * tassign)2666 Return_statement::do_traverse_assignments(Traverse_assignments* tassign)
2667 {
2668   Expression_list* vals = this->vals_;
2669   if (vals != NULL)
2670     {
2671       for (Expression_list::iterator p = vals->begin();
2672 	   p != vals->end();
2673 	   ++p)
2674 	tassign->value(&*p, true, true);
2675     }
2676   return true;
2677 }
2678 
2679 // Lower a return statement.  If we are returning a function call
2680 // which returns multiple values which match the current function,
2681 // split up the call's results.  If the return statement lists
2682 // explicit values, implement this statement by assigning the values
2683 // to the result variables and change this statement to a naked
2684 // return.  This lets panic/recover work correctly.
2685 
2686 Statement*
do_lower(Gogo *,Named_object * function,Block * enclosing,Statement_inserter *)2687 Return_statement::do_lower(Gogo*, Named_object* function, Block* enclosing,
2688 			   Statement_inserter*)
2689 {
2690   if (this->is_lowered_)
2691     return this;
2692 
2693   Expression_list* vals = this->vals_;
2694   this->vals_ = NULL;
2695   this->is_lowered_ = true;
2696 
2697   Location loc = this->location();
2698 
2699   size_t vals_count = vals == NULL ? 0 : vals->size();
2700   Function::Results* results = function->func_value()->result_variables();
2701   size_t results_count = results == NULL ? 0 : results->size();
2702 
2703   if (vals_count == 0)
2704     {
2705       if (results_count > 0 && !function->func_value()->results_are_named())
2706 	{
2707 	  this->report_error(_("not enough arguments to return"));
2708 	  return this;
2709 	}
2710       return this;
2711     }
2712 
2713   if (results_count == 0)
2714     {
2715       this->report_error(_("return with value in function "
2716 			   "with no return type"));
2717       return this;
2718     }
2719 
2720   // If the current function has multiple return values, and we are
2721   // returning a single call expression, split up the call expression.
2722   if (results_count > 1
2723       && vals->size() == 1
2724       && vals->front()->call_expression() != NULL)
2725     {
2726       Call_expression* call = vals->front()->call_expression();
2727       call->set_expected_result_count(results_count);
2728       delete vals;
2729       vals = new Expression_list;
2730       for (size_t i = 0; i < results_count; ++i)
2731 	vals->push_back(Expression::make_call_result(call, i));
2732       vals_count = results_count;
2733     }
2734 
2735   if (vals_count < results_count)
2736     {
2737       this->report_error(_("not enough arguments to return"));
2738       return this;
2739     }
2740 
2741   if (vals_count > results_count)
2742     {
2743       this->report_error(_("too many values in return statement"));
2744       return this;
2745     }
2746 
2747   Block* b = new Block(enclosing, loc);
2748 
2749   Expression_list* lhs = new Expression_list();
2750   Expression_list* rhs = new Expression_list();
2751 
2752   Expression_list::const_iterator pe = vals->begin();
2753   int i = 1;
2754   for (Function::Results::const_iterator pr = results->begin();
2755        pr != results->end();
2756        ++pr, ++pe, ++i)
2757     {
2758       Named_object* rv = *pr;
2759       Expression* e = *pe;
2760 
2761       // Check types now so that we give a good error message.  The
2762       // result type is known.  We determine the expression type
2763       // early.
2764 
2765       Type *rvtype = rv->result_var_value()->type();
2766       Type_context type_context(rvtype, false);
2767       e->determine_type(&type_context);
2768 
2769       std::string reason;
2770       if (Type::are_assignable(rvtype, e->type(), &reason))
2771 	{
2772 	  Expression* ve = Expression::make_var_reference(rv, e->location());
2773 	  lhs->push_back(ve);
2774 	  rhs->push_back(e);
2775 	}
2776       else
2777 	{
2778 	  if (reason.empty())
2779 	    error_at(e->location(), "incompatible type for return value %d", i);
2780 	  else
2781 	    error_at(e->location(),
2782 		     "incompatible type for return value %d (%s)",
2783 		     i, reason.c_str());
2784 	}
2785     }
2786   go_assert(lhs->size() == rhs->size());
2787 
2788   if (lhs->empty())
2789     ;
2790   else if (lhs->size() == 1)
2791     {
2792       b->add_statement(Statement::make_assignment(lhs->front(), rhs->front(),
2793 						  loc));
2794       delete lhs;
2795       delete rhs;
2796     }
2797   else
2798     b->add_statement(Statement::make_tuple_assignment(lhs, rhs, loc));
2799 
2800   b->add_statement(this);
2801 
2802   delete vals;
2803 
2804   return Statement::make_block_statement(b, loc);
2805 }
2806 
2807 // Convert a return statement to the backend representation.
2808 
2809 Bstatement*
do_get_backend(Translate_context * context)2810 Return_statement::do_get_backend(Translate_context* context)
2811 {
2812   Location loc = this->location();
2813 
2814   Function* function = context->function()->func_value();
2815   Function::Results* results = function->result_variables();
2816   std::vector<Bexpression*> retvals;
2817   if (results != NULL && !results->empty())
2818     {
2819       retvals.reserve(results->size());
2820       for (Function::Results::const_iterator p = results->begin();
2821 	   p != results->end();
2822 	   p++)
2823 	{
2824 	  Expression* vr = Expression::make_var_reference(*p, loc);
2825 	  retvals.push_back(vr->get_backend(context));
2826 	}
2827     }
2828 
2829   return context->backend()->return_statement(function->get_decl(),
2830 					      retvals, loc);
2831 }
2832 
2833 // Dump the AST representation for a return statement.
2834 
2835 void
do_dump_statement(Ast_dump_context * ast_dump_context) const2836 Return_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2837 {
2838   ast_dump_context->print_indent();
2839   ast_dump_context->ostream() << "return " ;
2840   ast_dump_context->dump_expression_list(this->vals_);
2841   ast_dump_context->ostream() << std::endl;
2842 }
2843 
2844 // Make a return statement.
2845 
2846 Return_statement*
make_return_statement(Expression_list * vals,Location location)2847 Statement::make_return_statement(Expression_list* vals,
2848 				 Location location)
2849 {
2850   return new Return_statement(vals, location);
2851 }
2852 
2853 // Make a statement that returns the result of a call expression.
2854 
2855 Statement*
make_return_from_call(Call_expression * call,Location location)2856 Statement::make_return_from_call(Call_expression* call, Location location)
2857 {
2858   size_t rc = call->result_count();
2859   if (rc == 0)
2860     return Statement::make_statement(call, true);
2861   else
2862     {
2863       Expression_list* vals = new Expression_list();
2864       if (rc == 1)
2865 	vals->push_back(call);
2866       else
2867 	{
2868 	  for (size_t i = 0; i < rc; ++i)
2869 	    vals->push_back(Expression::make_call_result(call, i));
2870 	}
2871       return Statement::make_return_statement(vals, location);
2872     }
2873 }
2874 
2875 // A break or continue statement.
2876 
2877 class Bc_statement : public Statement
2878 {
2879  public:
Bc_statement(bool is_break,Unnamed_label * label,Location location)2880   Bc_statement(bool is_break, Unnamed_label* label, Location location)
2881     : Statement(STATEMENT_BREAK_OR_CONTINUE, location),
2882       label_(label), is_break_(is_break)
2883   { }
2884 
2885   bool
is_break() const2886   is_break() const
2887   { return this->is_break_; }
2888 
2889  protected:
2890   int
do_traverse(Traverse *)2891   do_traverse(Traverse*)
2892   { return TRAVERSE_CONTINUE; }
2893 
2894   bool
do_may_fall_through() const2895   do_may_fall_through() const
2896   { return false; }
2897 
2898   Bstatement*
do_get_backend(Translate_context * context)2899   do_get_backend(Translate_context* context)
2900   { return this->label_->get_goto(context, this->location()); }
2901 
2902   void
2903   do_dump_statement(Ast_dump_context*) const;
2904 
2905  private:
2906   // The label that this branches to.
2907   Unnamed_label* label_;
2908   // True if this is "break", false if it is "continue".
2909   bool is_break_;
2910 };
2911 
2912 // Dump the AST representation for a break/continue statement
2913 
2914 void
do_dump_statement(Ast_dump_context * ast_dump_context) const2915 Bc_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2916 {
2917   ast_dump_context->print_indent();
2918   ast_dump_context->ostream() << (this->is_break_ ? "break" : "continue");
2919   if (this->label_ != NULL)
2920     {
2921       ast_dump_context->ostream() << " ";
2922       ast_dump_context->dump_label_name(this->label_);
2923     }
2924   ast_dump_context->ostream() << std::endl;
2925 }
2926 
2927 // Make a break statement.
2928 
2929 Statement*
make_break_statement(Unnamed_label * label,Location location)2930 Statement::make_break_statement(Unnamed_label* label, Location location)
2931 {
2932   return new Bc_statement(true, label, location);
2933 }
2934 
2935 // Make a continue statement.
2936 
2937 Statement*
make_continue_statement(Unnamed_label * label,Location location)2938 Statement::make_continue_statement(Unnamed_label* label,
2939 				   Location location)
2940 {
2941   return new Bc_statement(false, label, location);
2942 }
2943 
2944 // A goto statement.
2945 
2946 class Goto_statement : public Statement
2947 {
2948  public:
Goto_statement(Label * label,Location location)2949   Goto_statement(Label* label, Location location)
2950     : Statement(STATEMENT_GOTO, location),
2951       label_(label)
2952   { }
2953 
2954  protected:
2955   int
do_traverse(Traverse *)2956   do_traverse(Traverse*)
2957   { return TRAVERSE_CONTINUE; }
2958 
2959   void
2960   do_check_types(Gogo*);
2961 
2962   bool
do_may_fall_through() const2963   do_may_fall_through() const
2964   { return false; }
2965 
2966   Bstatement*
2967   do_get_backend(Translate_context*);
2968 
2969   void
2970   do_dump_statement(Ast_dump_context*) const;
2971 
2972  private:
2973   Label* label_;
2974 };
2975 
2976 // Check types for a label.  There aren't any types per se, but we use
2977 // this to give an error if the label was never defined.
2978 
2979 void
do_check_types(Gogo *)2980 Goto_statement::do_check_types(Gogo*)
2981 {
2982   if (!this->label_->is_defined())
2983     {
2984       error_at(this->location(), "reference to undefined label %qs",
2985 	       Gogo::message_name(this->label_->name()).c_str());
2986       this->set_is_error();
2987     }
2988 }
2989 
2990 // Convert the goto statement to the backend representation.
2991 
2992 Bstatement*
do_get_backend(Translate_context * context)2993 Goto_statement::do_get_backend(Translate_context* context)
2994 {
2995   Blabel* blabel = this->label_->get_backend_label(context);
2996   return context->backend()->goto_statement(blabel, this->location());
2997 }
2998 
2999 // Dump the AST representation for a goto statement.
3000 
3001 void
do_dump_statement(Ast_dump_context * ast_dump_context) const3002 Goto_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3003 {
3004   ast_dump_context->print_indent();
3005   ast_dump_context->ostream() << "goto " << this->label_->name() << std::endl;
3006 }
3007 
3008 // Make a goto statement.
3009 
3010 Statement*
make_goto_statement(Label * label,Location location)3011 Statement::make_goto_statement(Label* label, Location location)
3012 {
3013   return new Goto_statement(label, location);
3014 }
3015 
3016 // A goto statement to an unnamed label.
3017 
3018 class Goto_unnamed_statement : public Statement
3019 {
3020  public:
Goto_unnamed_statement(Unnamed_label * label,Location location)3021   Goto_unnamed_statement(Unnamed_label* label, Location location)
3022     : Statement(STATEMENT_GOTO_UNNAMED, location),
3023       label_(label)
3024   { }
3025 
3026  protected:
3027   int
do_traverse(Traverse *)3028   do_traverse(Traverse*)
3029   { return TRAVERSE_CONTINUE; }
3030 
3031   bool
do_may_fall_through() const3032   do_may_fall_through() const
3033   { return false; }
3034 
3035   Bstatement*
do_get_backend(Translate_context * context)3036   do_get_backend(Translate_context* context)
3037   { return this->label_->get_goto(context, this->location()); }
3038 
3039   void
3040   do_dump_statement(Ast_dump_context*) const;
3041 
3042  private:
3043   Unnamed_label* label_;
3044 };
3045 
3046 // Dump the AST representation for an unnamed goto statement
3047 
3048 void
do_dump_statement(Ast_dump_context * ast_dump_context) const3049 Goto_unnamed_statement::do_dump_statement(
3050     Ast_dump_context* ast_dump_context) const
3051 {
3052   ast_dump_context->print_indent();
3053   ast_dump_context->ostream() << "goto ";
3054   ast_dump_context->dump_label_name(this->label_);
3055   ast_dump_context->ostream() << std::endl;
3056 }
3057 
3058 // Make a goto statement to an unnamed label.
3059 
3060 Statement*
make_goto_unnamed_statement(Unnamed_label * label,Location location)3061 Statement::make_goto_unnamed_statement(Unnamed_label* label,
3062 				       Location location)
3063 {
3064   return new Goto_unnamed_statement(label, location);
3065 }
3066 
3067 // Class Label_statement.
3068 
3069 // Traversal.
3070 
3071 int
do_traverse(Traverse *)3072 Label_statement::do_traverse(Traverse*)
3073 {
3074   return TRAVERSE_CONTINUE;
3075 }
3076 
3077 // Return the backend representation of the statement defining this
3078 // label.
3079 
3080 Bstatement*
do_get_backend(Translate_context * context)3081 Label_statement::do_get_backend(Translate_context* context)
3082 {
3083   if (this->label_->is_dummy_label())
3084     {
3085       Bexpression* bce = context->backend()->boolean_constant_expression(false);
3086       return context->backend()->expression_statement(bce);
3087     }
3088   Blabel* blabel = this->label_->get_backend_label(context);
3089   return context->backend()->label_definition_statement(blabel);
3090 }
3091 
3092 // Dump the AST for a label definition statement.
3093 
3094 void
do_dump_statement(Ast_dump_context * ast_dump_context) const3095 Label_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3096 {
3097   ast_dump_context->print_indent();
3098   ast_dump_context->ostream() << this->label_->name() << ":" << std::endl;
3099 }
3100 
3101 // Make a label statement.
3102 
3103 Statement*
make_label_statement(Label * label,Location location)3104 Statement::make_label_statement(Label* label, Location location)
3105 {
3106   return new Label_statement(label, location);
3107 }
3108 
3109 // An unnamed label statement.
3110 
3111 class Unnamed_label_statement : public Statement
3112 {
3113  public:
Unnamed_label_statement(Unnamed_label * label)3114   Unnamed_label_statement(Unnamed_label* label)
3115     : Statement(STATEMENT_UNNAMED_LABEL, label->location()),
3116       label_(label)
3117   { }
3118 
3119  protected:
3120   int
do_traverse(Traverse *)3121   do_traverse(Traverse*)
3122   { return TRAVERSE_CONTINUE; }
3123 
3124   Bstatement*
do_get_backend(Translate_context * context)3125   do_get_backend(Translate_context* context)
3126   { return this->label_->get_definition(context); }
3127 
3128   void
3129   do_dump_statement(Ast_dump_context*) const;
3130 
3131  private:
3132   // The label.
3133   Unnamed_label* label_;
3134 };
3135 
3136 // Dump the AST representation for an unnamed label definition statement.
3137 
3138 void
do_dump_statement(Ast_dump_context * ast_dump_context) const3139 Unnamed_label_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
3140     const
3141 {
3142   ast_dump_context->print_indent();
3143   ast_dump_context->dump_label_name(this->label_);
3144   ast_dump_context->ostream() << ":" << std::endl;
3145 }
3146 
3147 // Make an unnamed label statement.
3148 
3149 Statement*
make_unnamed_label_statement(Unnamed_label * label)3150 Statement::make_unnamed_label_statement(Unnamed_label* label)
3151 {
3152   return new Unnamed_label_statement(label);
3153 }
3154 
3155 // Class If_statement.
3156 
3157 // Traversal.
3158 
3159 int
do_traverse(Traverse * traverse)3160 If_statement::do_traverse(Traverse* traverse)
3161 {
3162   if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT
3163       || this->then_block_->traverse(traverse) == TRAVERSE_EXIT)
3164     return TRAVERSE_EXIT;
3165   if (this->else_block_ != NULL)
3166     {
3167       if (this->else_block_->traverse(traverse) == TRAVERSE_EXIT)
3168 	return TRAVERSE_EXIT;
3169     }
3170   return TRAVERSE_CONTINUE;
3171 }
3172 
3173 void
do_determine_types()3174 If_statement::do_determine_types()
3175 {
3176   Type_context context(Type::lookup_bool_type(), false);
3177   this->cond_->determine_type(&context);
3178   this->then_block_->determine_types();
3179   if (this->else_block_ != NULL)
3180     this->else_block_->determine_types();
3181 }
3182 
3183 // Check types.
3184 
3185 void
do_check_types(Gogo *)3186 If_statement::do_check_types(Gogo*)
3187 {
3188   Type* type = this->cond_->type();
3189   if (type->is_error())
3190     this->set_is_error();
3191   else if (!type->is_boolean_type())
3192     this->report_error(_("expected boolean expression"));
3193 }
3194 
3195 // Whether the overall statement may fall through.
3196 
3197 bool
do_may_fall_through() const3198 If_statement::do_may_fall_through() const
3199 {
3200   return (this->else_block_ == NULL
3201 	  || this->then_block_->may_fall_through()
3202 	  || this->else_block_->may_fall_through());
3203 }
3204 
3205 // Get the backend representation.
3206 
3207 Bstatement*
do_get_backend(Translate_context * context)3208 If_statement::do_get_backend(Translate_context* context)
3209 {
3210   go_assert(this->cond_->type()->is_boolean_type()
3211 	     || this->cond_->type()->is_error());
3212   Bexpression* cond = this->cond_->get_backend(context);
3213   Bblock* then_block = this->then_block_->get_backend(context);
3214   Bblock* else_block = (this->else_block_ == NULL
3215 			? NULL
3216 			: this->else_block_->get_backend(context));
3217   return context->backend()->if_statement(cond, then_block, else_block,
3218 					  this->location());
3219 }
3220 
3221 // Dump the AST representation for an if statement
3222 
3223 void
do_dump_statement(Ast_dump_context * ast_dump_context) const3224 If_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3225 {
3226   ast_dump_context->print_indent();
3227   ast_dump_context->ostream() << "if ";
3228   ast_dump_context->dump_expression(this->cond_);
3229   ast_dump_context->ostream() << std::endl;
3230   if (ast_dump_context->dump_subblocks())
3231     {
3232       ast_dump_context->dump_block(this->then_block_);
3233       if (this->else_block_ != NULL)
3234 	{
3235 	  ast_dump_context->print_indent();
3236 	  ast_dump_context->ostream() << "else" << std::endl;
3237 	  ast_dump_context->dump_block(this->else_block_);
3238 	}
3239     }
3240 }
3241 
3242 // Make an if statement.
3243 
3244 Statement*
make_if_statement(Expression * cond,Block * then_block,Block * else_block,Location location)3245 Statement::make_if_statement(Expression* cond, Block* then_block,
3246 			     Block* else_block, Location location)
3247 {
3248   return new If_statement(cond, then_block, else_block, location);
3249 }
3250 
3251 // Class Case_clauses::Hash_integer_value.
3252 
3253 class Case_clauses::Hash_integer_value
3254 {
3255  public:
3256   size_t
3257   operator()(Expression*) const;
3258 };
3259 
3260 size_t
operator ()(Expression * pe) const3261 Case_clauses::Hash_integer_value::operator()(Expression* pe) const
3262 {
3263   Numeric_constant nc;
3264   mpz_t ival;
3265   if (!pe->numeric_constant_value(&nc) || !nc.to_int(&ival))
3266     go_unreachable();
3267   size_t ret = mpz_get_ui(ival);
3268   mpz_clear(ival);
3269   return ret;
3270 }
3271 
3272 // Class Case_clauses::Eq_integer_value.
3273 
3274 class Case_clauses::Eq_integer_value
3275 {
3276  public:
3277   bool
3278   operator()(Expression*, Expression*) const;
3279 };
3280 
3281 bool
operator ()(Expression * a,Expression * b) const3282 Case_clauses::Eq_integer_value::operator()(Expression* a, Expression* b) const
3283 {
3284   Numeric_constant anc;
3285   mpz_t aval;
3286   Numeric_constant bnc;
3287   mpz_t bval;
3288   if (!a->numeric_constant_value(&anc)
3289       || !anc.to_int(&aval)
3290       || !b->numeric_constant_value(&bnc)
3291       || !bnc.to_int(&bval))
3292     go_unreachable();
3293   bool ret = mpz_cmp(aval, bval) == 0;
3294   mpz_clear(aval);
3295   mpz_clear(bval);
3296   return ret;
3297 }
3298 
3299 // Class Case_clauses::Case_clause.
3300 
3301 // Traversal.
3302 
3303 int
traverse(Traverse * traverse)3304 Case_clauses::Case_clause::traverse(Traverse* traverse)
3305 {
3306   if (this->cases_ != NULL
3307       && (traverse->traverse_mask()
3308 	  & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
3309     {
3310       if (this->cases_->traverse(traverse) == TRAVERSE_EXIT)
3311 	return TRAVERSE_EXIT;
3312     }
3313   if (this->statements_ != NULL)
3314     {
3315       if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
3316 	return TRAVERSE_EXIT;
3317     }
3318   return TRAVERSE_CONTINUE;
3319 }
3320 
3321 // Check whether all the case expressions are integer constants.
3322 
3323 bool
is_constant() const3324 Case_clauses::Case_clause::is_constant() const
3325 {
3326   if (this->cases_ != NULL)
3327     {
3328       for (Expression_list::const_iterator p = this->cases_->begin();
3329 	   p != this->cases_->end();
3330 	   ++p)
3331 	if (!(*p)->is_constant() || (*p)->type()->integer_type() == NULL)
3332 	  return false;
3333     }
3334   return true;
3335 }
3336 
3337 // Lower a case clause for a nonconstant switch.  VAL_TEMP is the
3338 // value we are switching on; it may be NULL.  If START_LABEL is not
3339 // NULL, it goes at the start of the statements, after the condition
3340 // test.  We branch to FINISH_LABEL at the end of the statements.
3341 
3342 void
lower(Block * b,Temporary_statement * val_temp,Unnamed_label * start_label,Unnamed_label * finish_label) const3343 Case_clauses::Case_clause::lower(Block* b, Temporary_statement* val_temp,
3344 				 Unnamed_label* start_label,
3345 				 Unnamed_label* finish_label) const
3346 {
3347   Location loc = this->location_;
3348   Unnamed_label* next_case_label;
3349   if (this->cases_ == NULL || this->cases_->empty())
3350     {
3351       go_assert(this->is_default_);
3352       next_case_label = NULL;
3353     }
3354   else
3355     {
3356       Expression* cond = NULL;
3357 
3358       for (Expression_list::const_iterator p = this->cases_->begin();
3359 	   p != this->cases_->end();
3360 	   ++p)
3361 	{
3362 	  Expression* ref = Expression::make_temporary_reference(val_temp,
3363 								 loc);
3364 	  Expression* this_cond = Expression::make_binary(OPERATOR_EQEQ, ref,
3365 							  *p, loc);
3366 	  if (cond == NULL)
3367 	    cond = this_cond;
3368 	  else
3369 	    cond = Expression::make_binary(OPERATOR_OROR, cond, this_cond, loc);
3370 	}
3371 
3372       Block* then_block = new Block(b, loc);
3373       next_case_label = new Unnamed_label(Linemap::unknown_location());
3374       Statement* s = Statement::make_goto_unnamed_statement(next_case_label,
3375 							    loc);
3376       then_block->add_statement(s);
3377 
3378       // if !COND { goto NEXT_CASE_LABEL }
3379       cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
3380       s = Statement::make_if_statement(cond, then_block, NULL, loc);
3381       b->add_statement(s);
3382     }
3383 
3384   if (start_label != NULL)
3385     b->add_statement(Statement::make_unnamed_label_statement(start_label));
3386 
3387   if (this->statements_ != NULL)
3388     b->add_statement(Statement::make_block_statement(this->statements_, loc));
3389 
3390   Statement* s = Statement::make_goto_unnamed_statement(finish_label, loc);
3391   b->add_statement(s);
3392 
3393   if (next_case_label != NULL)
3394     b->add_statement(Statement::make_unnamed_label_statement(next_case_label));
3395 }
3396 
3397 // Determine types.
3398 
3399 void
determine_types(Type * type)3400 Case_clauses::Case_clause::determine_types(Type* type)
3401 {
3402   if (this->cases_ != NULL)
3403     {
3404       Type_context case_context(type, false);
3405       for (Expression_list::iterator p = this->cases_->begin();
3406 	   p != this->cases_->end();
3407 	   ++p)
3408 	(*p)->determine_type(&case_context);
3409     }
3410   if (this->statements_ != NULL)
3411     this->statements_->determine_types();
3412 }
3413 
3414 // Check types.  Returns false if there was an error.
3415 
3416 bool
check_types(Type * type)3417 Case_clauses::Case_clause::check_types(Type* type)
3418 {
3419   if (this->cases_ != NULL)
3420     {
3421       for (Expression_list::iterator p = this->cases_->begin();
3422 	   p != this->cases_->end();
3423 	   ++p)
3424 	{
3425 	  if (!Type::are_assignable(type, (*p)->type(), NULL)
3426 	      && !Type::are_assignable((*p)->type(), type, NULL))
3427 	    {
3428 	      error_at((*p)->location(),
3429 		       "type mismatch between switch value and case clause");
3430 	      return false;
3431 	    }
3432 	}
3433     }
3434   return true;
3435 }
3436 
3437 // Return true if this clause may fall through to the following
3438 // statements.  Note that this is not the same as whether the case
3439 // uses the "fallthrough" keyword.
3440 
3441 bool
may_fall_through() const3442 Case_clauses::Case_clause::may_fall_through() const
3443 {
3444   if (this->statements_ == NULL)
3445     return true;
3446   return this->statements_->may_fall_through();
3447 }
3448 
3449 // Convert the case values and statements to the backend
3450 // representation.  BREAK_LABEL is the label which break statements
3451 // should branch to.  CASE_CONSTANTS is used to detect duplicate
3452 // constants.  *CASES should be passed as an empty vector; the values
3453 // for this case will be added to it.  If this is the default case,
3454 // *CASES will remain empty.  This returns the statement to execute if
3455 // one of these cases is selected.
3456 
3457 Bstatement*
get_backend(Translate_context * context,Unnamed_label * break_label,Case_constants * case_constants,std::vector<Bexpression * > * cases) const3458 Case_clauses::Case_clause::get_backend(Translate_context* context,
3459 				       Unnamed_label* break_label,
3460 				       Case_constants* case_constants,
3461 				       std::vector<Bexpression*>* cases) const
3462 {
3463   if (this->cases_ != NULL)
3464     {
3465       go_assert(!this->is_default_);
3466       for (Expression_list::const_iterator p = this->cases_->begin();
3467 	   p != this->cases_->end();
3468 	   ++p)
3469 	{
3470 	  Expression* e = *p;
3471 	  if (e->classification() != Expression::EXPRESSION_INTEGER)
3472 	    {
3473 	      Numeric_constant nc;
3474 	      mpz_t ival;
3475 	      if (!(*p)->numeric_constant_value(&nc) || !nc.to_int(&ival))
3476 		{
3477 		  // Something went wrong.  This can happen with a
3478 		  // negative constant and an unsigned switch value.
3479 		  go_assert(saw_errors());
3480 		  continue;
3481 		}
3482 	      go_assert(nc.type() != NULL);
3483 	      e = Expression::make_integer_z(&ival, nc.type(), e->location());
3484 	      mpz_clear(ival);
3485 	    }
3486 
3487 	  std::pair<Case_constants::iterator, bool> ins =
3488 	    case_constants->insert(e);
3489 	  if (!ins.second)
3490 	    {
3491 	      // Value was already present.
3492 	      error_at(this->location_, "duplicate case in switch");
3493 	      e = Expression::make_error(this->location_);
3494 	    }
3495 	  cases->push_back(e->get_backend(context));
3496 	}
3497     }
3498 
3499   Bstatement* statements;
3500   if (this->statements_ == NULL)
3501     statements = NULL;
3502   else
3503     {
3504       Bblock* bblock = this->statements_->get_backend(context);
3505       statements = context->backend()->block_statement(bblock);
3506     }
3507 
3508   Bstatement* break_stat;
3509   if (this->is_fallthrough_)
3510     break_stat = NULL;
3511   else
3512     break_stat = break_label->get_goto(context, this->location_);
3513 
3514   if (statements == NULL)
3515     return break_stat;
3516   else if (break_stat == NULL)
3517     return statements;
3518   else
3519     return context->backend()->compound_statement(statements, break_stat);
3520 }
3521 
3522 // Dump the AST representation for a case clause
3523 
3524 void
dump_clause(Ast_dump_context * ast_dump_context) const3525 Case_clauses::Case_clause::dump_clause(Ast_dump_context* ast_dump_context)
3526     const
3527 {
3528   ast_dump_context->print_indent();
3529   if (this->is_default_)
3530     {
3531       ast_dump_context->ostream() << "default:";
3532     }
3533   else
3534     {
3535       ast_dump_context->ostream() << "case ";
3536       ast_dump_context->dump_expression_list(this->cases_);
3537       ast_dump_context->ostream() << ":" ;
3538     }
3539   ast_dump_context->dump_block(this->statements_);
3540   if (this->is_fallthrough_)
3541     {
3542       ast_dump_context->print_indent();
3543       ast_dump_context->ostream() <<  " (fallthrough)" << std::endl;
3544     }
3545 }
3546 
3547 // Class Case_clauses.
3548 
3549 // Traversal.
3550 
3551 int
traverse(Traverse * traverse)3552 Case_clauses::traverse(Traverse* traverse)
3553 {
3554   for (Clauses::iterator p = this->clauses_.begin();
3555        p != this->clauses_.end();
3556        ++p)
3557     {
3558       if (p->traverse(traverse) == TRAVERSE_EXIT)
3559 	return TRAVERSE_EXIT;
3560     }
3561   return TRAVERSE_CONTINUE;
3562 }
3563 
3564 // Check whether all the case expressions are constant.
3565 
3566 bool
is_constant() const3567 Case_clauses::is_constant() const
3568 {
3569   for (Clauses::const_iterator p = this->clauses_.begin();
3570        p != this->clauses_.end();
3571        ++p)
3572     if (!p->is_constant())
3573       return false;
3574   return true;
3575 }
3576 
3577 // Lower case clauses for a nonconstant switch.
3578 
3579 void
lower(Block * b,Temporary_statement * val_temp,Unnamed_label * break_label) const3580 Case_clauses::lower(Block* b, Temporary_statement* val_temp,
3581 		    Unnamed_label* break_label) const
3582 {
3583   // The default case.
3584   const Case_clause* default_case = NULL;
3585 
3586   // The label for the fallthrough of the previous case.
3587   Unnamed_label* last_fallthrough_label = NULL;
3588 
3589   // The label for the start of the default case.  This is used if the
3590   // case before the default case falls through.
3591   Unnamed_label* default_start_label = NULL;
3592 
3593   // The label for the end of the default case.  This normally winds
3594   // up as BREAK_LABEL, but it will be different if the default case
3595   // falls through.
3596   Unnamed_label* default_finish_label = NULL;
3597 
3598   for (Clauses::const_iterator p = this->clauses_.begin();
3599        p != this->clauses_.end();
3600        ++p)
3601     {
3602       // The label to use for the start of the statements for this
3603       // case.  This is NULL unless the previous case falls through.
3604       Unnamed_label* start_label = last_fallthrough_label;
3605 
3606       // The label to jump to after the end of the statements for this
3607       // case.
3608       Unnamed_label* finish_label = break_label;
3609 
3610       last_fallthrough_label = NULL;
3611       if (p->is_fallthrough() && p + 1 != this->clauses_.end())
3612 	{
3613 	  finish_label = new Unnamed_label(p->location());
3614 	  last_fallthrough_label = finish_label;
3615 	}
3616 
3617       if (!p->is_default())
3618 	p->lower(b, val_temp, start_label, finish_label);
3619       else
3620 	{
3621 	  // We have to move the default case to the end, so that we
3622 	  // only use it if all the other tests fail.
3623 	  default_case = &*p;
3624 	  default_start_label = start_label;
3625 	  default_finish_label = finish_label;
3626 	}
3627     }
3628 
3629   if (default_case != NULL)
3630     default_case->lower(b, val_temp, default_start_label,
3631 			default_finish_label);
3632 }
3633 
3634 // Determine types.
3635 
3636 void
determine_types(Type * type)3637 Case_clauses::determine_types(Type* type)
3638 {
3639   for (Clauses::iterator p = this->clauses_.begin();
3640        p != this->clauses_.end();
3641        ++p)
3642     p->determine_types(type);
3643 }
3644 
3645 // Check types.  Returns false if there was an error.
3646 
3647 bool
check_types(Type * type)3648 Case_clauses::check_types(Type* type)
3649 {
3650   bool ret = true;
3651   for (Clauses::iterator p = this->clauses_.begin();
3652        p != this->clauses_.end();
3653        ++p)
3654     {
3655       if (!p->check_types(type))
3656 	ret = false;
3657     }
3658   return ret;
3659 }
3660 
3661 // Return true if these clauses may fall through to the statements
3662 // following the switch statement.
3663 
3664 bool
may_fall_through() const3665 Case_clauses::may_fall_through() const
3666 {
3667   bool found_default = false;
3668   for (Clauses::const_iterator p = this->clauses_.begin();
3669        p != this->clauses_.end();
3670        ++p)
3671     {
3672       if (p->may_fall_through() && !p->is_fallthrough())
3673 	return true;
3674       if (p->is_default())
3675 	found_default = true;
3676     }
3677   return !found_default;
3678 }
3679 
3680 // Convert the cases to the backend representation.  This sets
3681 // *ALL_CASES and *ALL_STATEMENTS.
3682 
3683 void
get_backend(Translate_context * context,Unnamed_label * break_label,std::vector<std::vector<Bexpression * >> * all_cases,std::vector<Bstatement * > * all_statements) const3684 Case_clauses::get_backend(Translate_context* context,
3685 			  Unnamed_label* break_label,
3686 			  std::vector<std::vector<Bexpression*> >* all_cases,
3687 			  std::vector<Bstatement*>* all_statements) const
3688 {
3689   Case_constants case_constants;
3690 
3691   size_t c = this->clauses_.size();
3692   all_cases->resize(c);
3693   all_statements->resize(c);
3694 
3695   size_t i = 0;
3696   for (Clauses::const_iterator p = this->clauses_.begin();
3697        p != this->clauses_.end();
3698        ++p, ++i)
3699     {
3700       std::vector<Bexpression*> cases;
3701       Bstatement* stat = p->get_backend(context, break_label, &case_constants,
3702 					&cases);
3703       (*all_cases)[i].swap(cases);
3704       (*all_statements)[i] = stat;
3705     }
3706 }
3707 
3708 // Dump the AST representation for case clauses (from a switch statement)
3709 
3710 void
dump_clauses(Ast_dump_context * ast_dump_context) const3711 Case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
3712 {
3713   for (Clauses::const_iterator p = this->clauses_.begin();
3714        p != this->clauses_.end();
3715        ++p)
3716     p->dump_clause(ast_dump_context);
3717 }
3718 
3719 // A constant switch statement.  A Switch_statement is lowered to this
3720 // when all the cases are constants.
3721 
3722 class Constant_switch_statement : public Statement
3723 {
3724  public:
Constant_switch_statement(Expression * val,Case_clauses * clauses,Unnamed_label * break_label,Location location)3725   Constant_switch_statement(Expression* val, Case_clauses* clauses,
3726 			    Unnamed_label* break_label,
3727 			    Location location)
3728     : Statement(STATEMENT_CONSTANT_SWITCH, location),
3729       val_(val), clauses_(clauses), break_label_(break_label)
3730   { }
3731 
3732  protected:
3733   int
3734   do_traverse(Traverse*);
3735 
3736   void
3737   do_determine_types();
3738 
3739   void
3740   do_check_types(Gogo*);
3741 
3742   Bstatement*
3743   do_get_backend(Translate_context*);
3744 
3745   void
3746   do_dump_statement(Ast_dump_context*) const;
3747 
3748  private:
3749   // The value to switch on.
3750   Expression* val_;
3751   // The case clauses.
3752   Case_clauses* clauses_;
3753   // The break label, if needed.
3754   Unnamed_label* break_label_;
3755 };
3756 
3757 // Traversal.
3758 
3759 int
do_traverse(Traverse * traverse)3760 Constant_switch_statement::do_traverse(Traverse* traverse)
3761 {
3762   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
3763     return TRAVERSE_EXIT;
3764   return this->clauses_->traverse(traverse);
3765 }
3766 
3767 // Determine types.
3768 
3769 void
do_determine_types()3770 Constant_switch_statement::do_determine_types()
3771 {
3772   this->val_->determine_type_no_context();
3773   this->clauses_->determine_types(this->val_->type());
3774 }
3775 
3776 // Check types.
3777 
3778 void
do_check_types(Gogo *)3779 Constant_switch_statement::do_check_types(Gogo*)
3780 {
3781   if (!this->clauses_->check_types(this->val_->type()))
3782     this->set_is_error();
3783 }
3784 
3785 // Convert to GENERIC.
3786 
3787 Bstatement*
do_get_backend(Translate_context * context)3788 Constant_switch_statement::do_get_backend(Translate_context* context)
3789 {
3790   Bexpression* switch_val_expr = this->val_->get_backend(context);
3791 
3792   Unnamed_label* break_label = this->break_label_;
3793   if (break_label == NULL)
3794     break_label = new Unnamed_label(this->location());
3795 
3796   std::vector<std::vector<Bexpression*> > all_cases;
3797   std::vector<Bstatement*> all_statements;
3798   this->clauses_->get_backend(context, break_label, &all_cases,
3799 			      &all_statements);
3800 
3801   Bfunction* bfunction = context->function()->func_value()->get_decl();
3802   Bstatement* switch_statement;
3803   switch_statement = context->backend()->switch_statement(bfunction,
3804 							  switch_val_expr,
3805 							  all_cases,
3806 							  all_statements,
3807 							  this->location());
3808   Bstatement* ldef = break_label->get_definition(context);
3809   return context->backend()->compound_statement(switch_statement, ldef);
3810 }
3811 
3812 // Dump the AST representation for a constant switch statement.
3813 
3814 void
do_dump_statement(Ast_dump_context * ast_dump_context) const3815 Constant_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
3816     const
3817 {
3818   ast_dump_context->print_indent();
3819   ast_dump_context->ostream() << "switch ";
3820   ast_dump_context->dump_expression(this->val_);
3821 
3822   if (ast_dump_context->dump_subblocks())
3823     {
3824       ast_dump_context->ostream() << " {" << std::endl;
3825       this->clauses_->dump_clauses(ast_dump_context);
3826       ast_dump_context->ostream() << "}";
3827     }
3828 
3829    ast_dump_context->ostream() << std::endl;
3830 }
3831 
3832 // Class Switch_statement.
3833 
3834 // Traversal.
3835 
3836 int
do_traverse(Traverse * traverse)3837 Switch_statement::do_traverse(Traverse* traverse)
3838 {
3839   if (this->val_ != NULL)
3840     {
3841       if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
3842 	return TRAVERSE_EXIT;
3843     }
3844   return this->clauses_->traverse(traverse);
3845 }
3846 
3847 // Lower a Switch_statement to a Constant_switch_statement or a series
3848 // of if statements.
3849 
3850 Statement*
do_lower(Gogo *,Named_object *,Block * enclosing,Statement_inserter *)3851 Switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
3852 			   Statement_inserter*)
3853 {
3854   Location loc = this->location();
3855 
3856   if (this->val_ != NULL
3857       && (this->val_->is_error_expression()
3858 	  || this->val_->type()->is_error()))
3859     {
3860       go_assert(saw_errors());
3861       return Statement::make_error_statement(loc);
3862     }
3863 
3864   if (this->val_ != NULL
3865       && this->val_->type()->integer_type() != NULL
3866       && !this->clauses_->empty()
3867       && this->clauses_->is_constant())
3868     return new Constant_switch_statement(this->val_, this->clauses_,
3869 					 this->break_label_, loc);
3870 
3871   if (this->val_ != NULL
3872       && !this->val_->type()->is_comparable()
3873       && !Type::are_compatible_for_comparison(true, this->val_->type(),
3874 					      Type::make_nil_type(), NULL))
3875     {
3876       error_at(this->val_->location(),
3877 	       "cannot switch on value whose type that may not be compared");
3878       return Statement::make_error_statement(loc);
3879     }
3880 
3881   Block* b = new Block(enclosing, loc);
3882 
3883   if (this->clauses_->empty())
3884     {
3885       Expression* val = this->val_;
3886       if (val == NULL)
3887 	val = Expression::make_boolean(true, loc);
3888       return Statement::make_statement(val, true);
3889     }
3890 
3891   // var val_temp VAL_TYPE = VAL
3892   Expression* val = this->val_;
3893   if (val == NULL)
3894     val = Expression::make_boolean(true, loc);
3895 
3896   Type* type = val->type();
3897   if (type->is_abstract())
3898     type = type->make_non_abstract_type();
3899   Temporary_statement* val_temp = Statement::make_temporary(type, val, loc);
3900   b->add_statement(val_temp);
3901 
3902   this->clauses_->lower(b, val_temp, this->break_label());
3903 
3904   Statement* s = Statement::make_unnamed_label_statement(this->break_label_);
3905   b->add_statement(s);
3906 
3907   return Statement::make_block_statement(b, loc);
3908 }
3909 
3910 // Return the break label for this switch statement, creating it if
3911 // necessary.
3912 
3913 Unnamed_label*
break_label()3914 Switch_statement::break_label()
3915 {
3916   if (this->break_label_ == NULL)
3917     this->break_label_ = new Unnamed_label(this->location());
3918   return this->break_label_;
3919 }
3920 
3921 // Dump the AST representation for a switch statement.
3922 
3923 void
do_dump_statement(Ast_dump_context * ast_dump_context) const3924 Switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3925 {
3926   ast_dump_context->print_indent();
3927   ast_dump_context->ostream() << "switch ";
3928   if (this->val_ != NULL)
3929     {
3930       ast_dump_context->dump_expression(this->val_);
3931     }
3932   if (ast_dump_context->dump_subblocks())
3933     {
3934       ast_dump_context->ostream() << " {" << std::endl;
3935       this->clauses_->dump_clauses(ast_dump_context);
3936       ast_dump_context->print_indent();
3937       ast_dump_context->ostream() << "}";
3938     }
3939   ast_dump_context->ostream() << std::endl;
3940 }
3941 
3942 // Return whether this switch may fall through.
3943 
3944 bool
do_may_fall_through() const3945 Switch_statement::do_may_fall_through() const
3946 {
3947   if (this->clauses_ == NULL)
3948     return true;
3949 
3950   // If we have a break label, then some case needed it.  That implies
3951   // that the switch statement as a whole can fall through.
3952   if (this->break_label_ != NULL)
3953     return true;
3954 
3955   return this->clauses_->may_fall_through();
3956 }
3957 
3958 // Make a switch statement.
3959 
3960 Switch_statement*
make_switch_statement(Expression * val,Location location)3961 Statement::make_switch_statement(Expression* val, Location location)
3962 {
3963   return new Switch_statement(val, location);
3964 }
3965 
3966 // Class Type_case_clauses::Type_case_clause.
3967 
3968 // Traversal.
3969 
3970 int
traverse(Traverse * traverse)3971 Type_case_clauses::Type_case_clause::traverse(Traverse* traverse)
3972 {
3973   if (!this->is_default_
3974       && ((traverse->traverse_mask()
3975 	   & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
3976       && Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
3977     return TRAVERSE_EXIT;
3978   if (this->statements_ != NULL)
3979     return this->statements_->traverse(traverse);
3980   return TRAVERSE_CONTINUE;
3981 }
3982 
3983 // Lower one clause in a type switch.  Add statements to the block B.
3984 // The type descriptor we are switching on is in DESCRIPTOR_TEMP.
3985 // BREAK_LABEL is the label at the end of the type switch.
3986 // *STMTS_LABEL, if not NULL, is a label to put at the start of the
3987 // statements.
3988 
3989 void
lower(Type * switch_val_type,Block * b,Temporary_statement * descriptor_temp,Unnamed_label * break_label,Unnamed_label ** stmts_label) const3990 Type_case_clauses::Type_case_clause::lower(Type* switch_val_type,
3991 					   Block* b,
3992 					   Temporary_statement* descriptor_temp,
3993 					   Unnamed_label* break_label,
3994 					   Unnamed_label** stmts_label) const
3995 {
3996   Location loc = this->location_;
3997 
3998   Unnamed_label* next_case_label = NULL;
3999   if (!this->is_default_)
4000     {
4001       Type* type = this->type_;
4002 
4003       std::string reason;
4004       if (switch_val_type->interface_type() != NULL
4005 	  && !type->is_nil_constant_as_type()
4006 	  && type->interface_type() == NULL
4007 	  && !switch_val_type->interface_type()->implements_interface(type,
4008 								      &reason))
4009 	{
4010 	  if (reason.empty())
4011 	    error_at(this->location_, "impossible type switch case");
4012 	  else
4013 	    error_at(this->location_, "impossible type switch case (%s)",
4014 		     reason.c_str());
4015 	}
4016 
4017       Expression* ref = Expression::make_temporary_reference(descriptor_temp,
4018 							     loc);
4019 
4020       Expression* cond;
4021       // The language permits case nil, which is of course a constant
4022       // rather than a type.  It will appear here as an invalid
4023       // forwarding type.
4024       if (type->is_nil_constant_as_type())
4025 	cond = Expression::make_binary(OPERATOR_EQEQ, ref,
4026 				       Expression::make_nil(loc),
4027 				       loc);
4028       else
4029 	cond = Runtime::make_call((type->interface_type() == NULL
4030 				   ? Runtime::IFACETYPEEQ
4031 				   : Runtime::IFACEI2TP),
4032 				  loc, 2,
4033 				  Expression::make_type_descriptor(type, loc),
4034 				  ref);
4035 
4036       Unnamed_label* dest;
4037       if (!this->is_fallthrough_)
4038 	{
4039 	  // if !COND { goto NEXT_CASE_LABEL }
4040 	  next_case_label = new Unnamed_label(Linemap::unknown_location());
4041 	  dest = next_case_label;
4042 	  cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
4043 	}
4044       else
4045 	{
4046 	  // if COND { goto STMTS_LABEL }
4047 	  go_assert(stmts_label != NULL);
4048 	  if (*stmts_label == NULL)
4049 	    *stmts_label = new Unnamed_label(Linemap::unknown_location());
4050 	  dest = *stmts_label;
4051 	}
4052       Block* then_block = new Block(b, loc);
4053       Statement* s = Statement::make_goto_unnamed_statement(dest, loc);
4054       then_block->add_statement(s);
4055       s = Statement::make_if_statement(cond, then_block, NULL, loc);
4056       b->add_statement(s);
4057     }
4058 
4059   if (this->statements_ != NULL
4060       || (!this->is_fallthrough_
4061 	  && stmts_label != NULL
4062 	  && *stmts_label != NULL))
4063     {
4064       go_assert(!this->is_fallthrough_);
4065       if (stmts_label != NULL && *stmts_label != NULL)
4066 	{
4067 	  go_assert(!this->is_default_);
4068 	  if (this->statements_ != NULL)
4069 	    (*stmts_label)->set_location(this->statements_->start_location());
4070 	  Statement* s = Statement::make_unnamed_label_statement(*stmts_label);
4071 	  b->add_statement(s);
4072 	  *stmts_label = NULL;
4073 	}
4074       if (this->statements_ != NULL)
4075 	b->add_statement(Statement::make_block_statement(this->statements_,
4076 							 loc));
4077     }
4078 
4079   if (this->is_fallthrough_)
4080     go_assert(next_case_label == NULL);
4081   else
4082     {
4083       Location gloc = (this->statements_ == NULL
4084 			      ? loc
4085 			      : this->statements_->end_location());
4086       b->add_statement(Statement::make_goto_unnamed_statement(break_label,
4087 							      gloc));
4088       if (next_case_label != NULL)
4089 	{
4090 	  Statement* s =
4091 	    Statement::make_unnamed_label_statement(next_case_label);
4092 	  b->add_statement(s);
4093 	}
4094     }
4095 }
4096 
4097 // Return true if this type clause may fall through to the statements
4098 // following the switch.
4099 
4100 bool
may_fall_through() const4101 Type_case_clauses::Type_case_clause::may_fall_through() const
4102 {
4103   if (this->is_fallthrough_)
4104     {
4105       // This case means that we automatically fall through to the
4106       // next case (it's used for T1 in case T1, T2:).  It does not
4107       // mean that we fall through to the end of the type switch as a
4108       // whole.  There is sure to be a next case and that next case
4109       // will determine whether we fall through to the statements
4110       // after the type switch.
4111       return false;
4112     }
4113   if (this->statements_ == NULL)
4114     return true;
4115   return this->statements_->may_fall_through();
4116 }
4117 
4118 // Dump the AST representation for a type case clause
4119 
4120 void
dump_clause(Ast_dump_context * ast_dump_context) const4121 Type_case_clauses::Type_case_clause::dump_clause(
4122     Ast_dump_context* ast_dump_context) const
4123 {
4124   ast_dump_context->print_indent();
4125   if (this->is_default_)
4126     {
4127       ast_dump_context->ostream() << "default:";
4128     }
4129   else
4130     {
4131       ast_dump_context->ostream() << "case ";
4132       ast_dump_context->dump_type(this->type_);
4133       ast_dump_context->ostream() << ":" ;
4134     }
4135   ast_dump_context->dump_block(this->statements_);
4136   if (this->is_fallthrough_)
4137     {
4138       ast_dump_context->print_indent();
4139       ast_dump_context->ostream() <<  " (fallthrough)" << std::endl;
4140     }
4141 }
4142 
4143 // Class Type_case_clauses.
4144 
4145 // Traversal.
4146 
4147 int
traverse(Traverse * traverse)4148 Type_case_clauses::traverse(Traverse* traverse)
4149 {
4150   for (Type_clauses::iterator p = this->clauses_.begin();
4151        p != this->clauses_.end();
4152        ++p)
4153     {
4154       if (p->traverse(traverse) == TRAVERSE_EXIT)
4155 	return TRAVERSE_EXIT;
4156     }
4157   return TRAVERSE_CONTINUE;
4158 }
4159 
4160 // Check for duplicate types.
4161 
4162 void
check_duplicates() const4163 Type_case_clauses::check_duplicates() const
4164 {
4165   typedef Unordered_set_hash(const Type*, Type_hash_identical,
4166 			     Type_identical) Types_seen;
4167   Types_seen types_seen;
4168   for (Type_clauses::const_iterator p = this->clauses_.begin();
4169        p != this->clauses_.end();
4170        ++p)
4171     {
4172       Type* t = p->type();
4173       if (t == NULL)
4174 	continue;
4175       if (t->is_nil_constant_as_type())
4176 	t = Type::make_nil_type();
4177       std::pair<Types_seen::iterator, bool> ins = types_seen.insert(t);
4178       if (!ins.second)
4179 	error_at(p->location(), "duplicate type in switch");
4180     }
4181 }
4182 
4183 // Lower the clauses in a type switch.  Add statements to the block B.
4184 // The type descriptor we are switching on is in DESCRIPTOR_TEMP.
4185 // BREAK_LABEL is the label at the end of the type switch.
4186 
4187 void
lower(Type * switch_val_type,Block * b,Temporary_statement * descriptor_temp,Unnamed_label * break_label) const4188 Type_case_clauses::lower(Type* switch_val_type, Block* b,
4189 			 Temporary_statement* descriptor_temp,
4190 			 Unnamed_label* break_label) const
4191 {
4192   const Type_case_clause* default_case = NULL;
4193 
4194   Unnamed_label* stmts_label = NULL;
4195   for (Type_clauses::const_iterator p = this->clauses_.begin();
4196        p != this->clauses_.end();
4197        ++p)
4198     {
4199       if (!p->is_default())
4200 	p->lower(switch_val_type, b, descriptor_temp, break_label,
4201 		 &stmts_label);
4202       else
4203 	{
4204 	  // We are generating a series of tests, which means that we
4205 	  // need to move the default case to the end.
4206 	  default_case = &*p;
4207 	}
4208     }
4209   go_assert(stmts_label == NULL);
4210 
4211   if (default_case != NULL)
4212     default_case->lower(switch_val_type, b, descriptor_temp, break_label,
4213 			NULL);
4214 }
4215 
4216 // Return true if these clauses may fall through to the statements
4217 // following the switch statement.
4218 
4219 bool
may_fall_through() const4220 Type_case_clauses::may_fall_through() const
4221 {
4222   bool found_default = false;
4223   for (Type_clauses::const_iterator p = this->clauses_.begin();
4224        p != this->clauses_.end();
4225        ++p)
4226     {
4227       if (p->may_fall_through())
4228 	return true;
4229       if (p->is_default())
4230 	found_default = true;
4231     }
4232   return !found_default;
4233 }
4234 
4235 // Dump the AST representation for case clauses (from a switch statement)
4236 
4237 void
dump_clauses(Ast_dump_context * ast_dump_context) const4238 Type_case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
4239 {
4240   for (Type_clauses::const_iterator p = this->clauses_.begin();
4241        p != this->clauses_.end();
4242        ++p)
4243     p->dump_clause(ast_dump_context);
4244 }
4245 
4246 // Class Type_switch_statement.
4247 
4248 // Traversal.
4249 
4250 int
do_traverse(Traverse * traverse)4251 Type_switch_statement::do_traverse(Traverse* traverse)
4252 {
4253   if (this->traverse_expression(traverse, &this->expr_) == TRAVERSE_EXIT)
4254     return TRAVERSE_EXIT;
4255   if (this->clauses_ != NULL)
4256     return this->clauses_->traverse(traverse);
4257   return TRAVERSE_CONTINUE;
4258 }
4259 
4260 // Lower a type switch statement to a series of if statements.  The gc
4261 // compiler is able to generate a table in some cases.  However, that
4262 // does not work for us because we may have type descriptors in
4263 // different shared libraries, so we can't compare them with simple
4264 // equality testing.
4265 
4266 Statement*
do_lower(Gogo *,Named_object *,Block * enclosing,Statement_inserter *)4267 Type_switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
4268 				Statement_inserter*)
4269 {
4270   const Location loc = this->location();
4271 
4272   if (this->clauses_ != NULL)
4273     this->clauses_->check_duplicates();
4274 
4275   Block* b = new Block(enclosing, loc);
4276 
4277   Type* val_type = this->expr_->type();
4278   if (val_type->interface_type() == NULL)
4279     {
4280       if (!val_type->is_error())
4281 	this->report_error(_("cannot type switch on non-interface value"));
4282       return Statement::make_error_statement(loc);
4283     }
4284 
4285   // var descriptor_temp DESCRIPTOR_TYPE
4286   Type* descriptor_type = Type::make_type_descriptor_ptr_type();
4287   Temporary_statement* descriptor_temp =
4288     Statement::make_temporary(descriptor_type, NULL, loc);
4289   b->add_statement(descriptor_temp);
4290 
4291   // descriptor_temp = ifacetype(val_temp) FIXME: This should be
4292   // inlined.
4293   bool is_empty = val_type->interface_type()->is_empty();
4294   Expression* call = Runtime::make_call((is_empty
4295 					 ? Runtime::EFACETYPE
4296 					 : Runtime::IFACETYPE),
4297 					loc, 1, this->expr_);
4298   Temporary_reference_expression* lhs =
4299     Expression::make_temporary_reference(descriptor_temp, loc);
4300   lhs->set_is_lvalue();
4301   Statement* s = Statement::make_assignment(lhs, call, loc);
4302   b->add_statement(s);
4303 
4304   if (this->clauses_ != NULL)
4305     this->clauses_->lower(val_type, b, descriptor_temp, this->break_label());
4306 
4307   s = Statement::make_unnamed_label_statement(this->break_label_);
4308   b->add_statement(s);
4309 
4310   return Statement::make_block_statement(b, loc);
4311 }
4312 
4313 // Return whether this switch may fall through.
4314 
4315 bool
do_may_fall_through() const4316 Type_switch_statement::do_may_fall_through() const
4317 {
4318   if (this->clauses_ == NULL)
4319     return true;
4320 
4321   // If we have a break label, then some case needed it.  That implies
4322   // that the switch statement as a whole can fall through.
4323   if (this->break_label_ != NULL)
4324     return true;
4325 
4326   return this->clauses_->may_fall_through();
4327 }
4328 
4329 // Return the break label for this type switch statement, creating it
4330 // if necessary.
4331 
4332 Unnamed_label*
break_label()4333 Type_switch_statement::break_label()
4334 {
4335   if (this->break_label_ == NULL)
4336     this->break_label_ = new Unnamed_label(this->location());
4337   return this->break_label_;
4338 }
4339 
4340 // Dump the AST representation for a type switch statement
4341 
4342 void
do_dump_statement(Ast_dump_context * ast_dump_context) const4343 Type_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
4344     const
4345 {
4346   ast_dump_context->print_indent();
4347   ast_dump_context->ostream() << "switch ";
4348   if (!this->name_.empty())
4349     ast_dump_context->ostream() << this->name_ << " = ";
4350   ast_dump_context->dump_expression(this->expr_);
4351   ast_dump_context->ostream() << " .(type)";
4352   if (ast_dump_context->dump_subblocks())
4353     {
4354       ast_dump_context->ostream() << " {" << std::endl;
4355       this->clauses_->dump_clauses(ast_dump_context);
4356       ast_dump_context->ostream() << "}";
4357     }
4358   ast_dump_context->ostream() << std::endl;
4359 }
4360 
4361 // Make a type switch statement.
4362 
4363 Type_switch_statement*
make_type_switch_statement(const std::string & name,Expression * expr,Location location)4364 Statement::make_type_switch_statement(const std::string& name, Expression* expr,
4365 				      Location location)
4366 {
4367   return new Type_switch_statement(name, expr, location);
4368 }
4369 
4370 // Class Send_statement.
4371 
4372 // Traversal.
4373 
4374 int
do_traverse(Traverse * traverse)4375 Send_statement::do_traverse(Traverse* traverse)
4376 {
4377   if (this->traverse_expression(traverse, &this->channel_) == TRAVERSE_EXIT)
4378     return TRAVERSE_EXIT;
4379   return this->traverse_expression(traverse, &this->val_);
4380 }
4381 
4382 // Determine types.
4383 
4384 void
do_determine_types()4385 Send_statement::do_determine_types()
4386 {
4387   this->channel_->determine_type_no_context();
4388   Type* type = this->channel_->type();
4389   Type_context context;
4390   if (type->channel_type() != NULL)
4391     context.type = type->channel_type()->element_type();
4392   this->val_->determine_type(&context);
4393 }
4394 
4395 // Check types.
4396 
4397 void
do_check_types(Gogo *)4398 Send_statement::do_check_types(Gogo*)
4399 {
4400   Type* type = this->channel_->type();
4401   if (type->is_error())
4402     {
4403       this->set_is_error();
4404       return;
4405     }
4406   Channel_type* channel_type = type->channel_type();
4407   if (channel_type == NULL)
4408     {
4409       error_at(this->location(), "left operand of %<<-%> must be channel");
4410       this->set_is_error();
4411       return;
4412     }
4413   Type* element_type = channel_type->element_type();
4414   if (!Type::are_assignable(element_type, this->val_->type(), NULL))
4415     {
4416       this->report_error(_("incompatible types in send"));
4417       return;
4418     }
4419   if (!channel_type->may_send())
4420     {
4421       this->report_error(_("invalid send on receive-only channel"));
4422       return;
4423     }
4424 }
4425 
4426 // Flatten a send statement.  We may need a temporary for interface
4427 // conversion.
4428 
4429 Statement*
do_flatten(Gogo *,Named_object *,Block *,Statement_inserter * inserter)4430 Send_statement::do_flatten(Gogo*, Named_object*, Block*,
4431 			   Statement_inserter* inserter)
4432 {
4433   if (this->channel_->is_error_expression()
4434       || this->channel_->type()->is_error_type())
4435     {
4436       go_assert(saw_errors());
4437       return Statement::make_error_statement(this->location());
4438     }
4439 
4440   Type* element_type = this->channel_->type()->channel_type()->element_type();
4441   if (!Type::are_identical(element_type, this->val_->type(), false, NULL)
4442       && this->val_->type()->interface_type() != NULL
4443       && !this->val_->is_variable())
4444     {
4445       Temporary_statement* temp =
4446 	Statement::make_temporary(NULL, this->val_, this->location());
4447       inserter->insert(temp);
4448       this->val_ = Expression::make_temporary_reference(temp,
4449 							this->location());
4450     }
4451   return this;
4452 }
4453 
4454 // Convert a send statement to the backend representation.
4455 
4456 Bstatement*
do_get_backend(Translate_context * context)4457 Send_statement::do_get_backend(Translate_context* context)
4458 {
4459   Location loc = this->location();
4460 
4461   Channel_type* channel_type = this->channel_->type()->channel_type();
4462   Type* element_type = channel_type->element_type();
4463   Expression* val = Expression::convert_for_assignment(context->gogo(),
4464 						       element_type,
4465 						       this->val_, loc);
4466 
4467   bool is_small;
4468   bool can_take_address;
4469   switch (element_type->base()->classification())
4470     {
4471     case Type::TYPE_BOOLEAN:
4472     case Type::TYPE_INTEGER:
4473     case Type::TYPE_FUNCTION:
4474     case Type::TYPE_POINTER:
4475     case Type::TYPE_MAP:
4476     case Type::TYPE_CHANNEL:
4477       is_small = true;
4478       can_take_address = false;
4479       break;
4480 
4481     case Type::TYPE_FLOAT:
4482     case Type::TYPE_COMPLEX:
4483     case Type::TYPE_STRING:
4484     case Type::TYPE_INTERFACE:
4485       is_small = false;
4486       can_take_address = false;
4487       break;
4488 
4489     case Type::TYPE_STRUCT:
4490       is_small = false;
4491       can_take_address = true;
4492       break;
4493 
4494     case Type::TYPE_ARRAY:
4495       is_small = false;
4496       can_take_address = !element_type->is_slice_type();
4497       break;
4498 
4499     default:
4500     case Type::TYPE_ERROR:
4501     case Type::TYPE_VOID:
4502     case Type::TYPE_SINK:
4503     case Type::TYPE_NIL:
4504     case Type::TYPE_NAMED:
4505     case Type::TYPE_FORWARD:
4506       go_assert(saw_errors());
4507       return context->backend()->error_statement();
4508     }
4509 
4510   // Only try to take the address of a variable.  We have already
4511   // moved variables to the heap, so this should not cause that to
4512   // happen unnecessarily.
4513   if (can_take_address
4514       && val->var_expression() == NULL
4515       && val->temporary_reference_expression() == NULL)
4516     can_take_address = false;
4517 
4518   Expression* td = Expression::make_type_descriptor(this->channel_->type(),
4519 						    loc);
4520 
4521   Runtime::Function code;
4522   Bstatement* btemp = NULL;
4523   if (is_small)
4524       {
4525 	// Type is small enough to handle as uint64.
4526 	code = Runtime::SEND_SMALL;
4527 	val = Expression::make_unsafe_cast(Type::lookup_integer_type("uint64"),
4528 					   val, loc);
4529       }
4530   else if (can_take_address)
4531     {
4532       // Must pass address of value.  The function doesn't change the
4533       // value, so just take its address directly.
4534       code = Runtime::SEND_BIG;
4535       val = Expression::make_unary(OPERATOR_AND, val, loc);
4536     }
4537   else
4538     {
4539       // Must pass address of value, but the value is small enough
4540       // that it might be in registers.  Copy value into temporary
4541       // variable to take address.
4542       code = Runtime::SEND_BIG;
4543       Temporary_statement* temp = Statement::make_temporary(element_type,
4544 							    val, loc);
4545       Expression* ref = Expression::make_temporary_reference(temp, loc);
4546       val = Expression::make_unary(OPERATOR_AND, ref, loc);
4547       btemp = temp->get_backend(context);
4548     }
4549 
4550   Expression* call = Runtime::make_call(code, loc, 3, td, this->channel_, val);
4551 
4552   context->gogo()->lower_expression(context->function(), NULL, &call);
4553   Bexpression* bcall = call->get_backend(context);
4554   Bstatement* s = context->backend()->expression_statement(bcall);
4555 
4556   if (btemp == NULL)
4557     return s;
4558   else
4559     return context->backend()->compound_statement(btemp, s);
4560 }
4561 
4562 // Dump the AST representation for a send statement
4563 
4564 void
do_dump_statement(Ast_dump_context * ast_dump_context) const4565 Send_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
4566 {
4567   ast_dump_context->print_indent();
4568   ast_dump_context->dump_expression(this->channel_);
4569   ast_dump_context->ostream() << " <- ";
4570   ast_dump_context->dump_expression(this->val_);
4571   ast_dump_context->ostream() << std::endl;
4572 }
4573 
4574 // Make a send statement.
4575 
4576 Send_statement*
make_send_statement(Expression * channel,Expression * val,Location location)4577 Statement::make_send_statement(Expression* channel, Expression* val,
4578 			       Location location)
4579 {
4580   return new Send_statement(channel, val, location);
4581 }
4582 
4583 // Class Select_clauses::Select_clause.
4584 
4585 // Traversal.
4586 
4587 int
traverse(Traverse * traverse)4588 Select_clauses::Select_clause::traverse(Traverse* traverse)
4589 {
4590   if (!this->is_lowered_
4591       && (traverse->traverse_mask()
4592 	  & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
4593     {
4594       if (this->channel_ != NULL)
4595 	{
4596 	  if (Expression::traverse(&this->channel_, traverse) == TRAVERSE_EXIT)
4597 	    return TRAVERSE_EXIT;
4598 	}
4599       if (this->val_ != NULL)
4600 	{
4601 	  if (Expression::traverse(&this->val_, traverse) == TRAVERSE_EXIT)
4602 	    return TRAVERSE_EXIT;
4603 	}
4604       if (this->closed_ != NULL)
4605 	{
4606 	  if (Expression::traverse(&this->closed_, traverse) == TRAVERSE_EXIT)
4607 	    return TRAVERSE_EXIT;
4608 	}
4609     }
4610   if (this->statements_ != NULL)
4611     {
4612       if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
4613 	return TRAVERSE_EXIT;
4614     }
4615   return TRAVERSE_CONTINUE;
4616 }
4617 
4618 // Lowering.  We call a function to register this clause, and arrange
4619 // to set any variables in any receive clause.
4620 
4621 void
lower(Gogo * gogo,Named_object * function,Block * b,Temporary_statement * sel)4622 Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
4623 				     Block* b, Temporary_statement* sel)
4624 {
4625   Location loc = this->location_;
4626 
4627   Expression* selref = Expression::make_temporary_reference(sel, loc);
4628 
4629   Expression* index_expr = Expression::make_integer_ul(this->index_, NULL,
4630 						       loc);
4631 
4632   if (this->is_default_)
4633     {
4634       go_assert(this->channel_ == NULL && this->val_ == NULL);
4635       this->lower_default(b, selref, index_expr);
4636       this->is_lowered_ = true;
4637       return;
4638     }
4639 
4640   // Evaluate the channel before the select statement.
4641   Temporary_statement* channel_temp = Statement::make_temporary(NULL,
4642 								this->channel_,
4643 								loc);
4644   b->add_statement(channel_temp);
4645   Expression* chanref = Expression::make_temporary_reference(channel_temp,
4646 							     loc);
4647 
4648   if (this->is_send_)
4649     this->lower_send(b, selref, chanref, index_expr);
4650   else
4651     this->lower_recv(gogo, function, b, selref, chanref, index_expr);
4652 
4653   // Now all references should be handled through the statements, not
4654   // through here.
4655   this->is_lowered_ = true;
4656   this->val_ = NULL;
4657 }
4658 
4659 // Lower a default clause in a select statement.
4660 
4661 void
lower_default(Block * b,Expression * selref,Expression * index_expr)4662 Select_clauses::Select_clause::lower_default(Block* b, Expression* selref,
4663 					     Expression* index_expr)
4664 {
4665   Location loc = this->location_;
4666   Expression* call = Runtime::make_call(Runtime::SELECTDEFAULT, loc, 2, selref,
4667 					index_expr);
4668   b->add_statement(Statement::make_statement(call, true));
4669 }
4670 
4671 // Lower a send clause in a select statement.
4672 
4673 void
lower_send(Block * b,Expression * selref,Expression * chanref,Expression * index_expr)4674 Select_clauses::Select_clause::lower_send(Block* b, Expression* selref,
4675 					  Expression* chanref,
4676 					  Expression* index_expr)
4677 {
4678   Location loc = this->location_;
4679 
4680   Channel_type* ct = this->channel_->type()->channel_type();
4681   if (ct == NULL)
4682     return;
4683 
4684   Type* valtype = ct->element_type();
4685 
4686   // Note that copying the value to a temporary here means that we
4687   // evaluate the send values in the required order.
4688   Temporary_statement* val = Statement::make_temporary(valtype, this->val_,
4689 						       loc);
4690   b->add_statement(val);
4691 
4692   Expression* valref = Expression::make_temporary_reference(val, loc);
4693   Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
4694 
4695   Expression* call = Runtime::make_call(Runtime::SELECTSEND, loc, 4, selref,
4696 					chanref, valaddr, index_expr);
4697   b->add_statement(Statement::make_statement(call, true));
4698 }
4699 
4700 // Lower a receive clause in a select statement.
4701 
4702 void
lower_recv(Gogo * gogo,Named_object * function,Block * b,Expression * selref,Expression * chanref,Expression * index_expr)4703 Select_clauses::Select_clause::lower_recv(Gogo* gogo, Named_object* function,
4704 					  Block* b, Expression* selref,
4705 					  Expression* chanref,
4706 					  Expression* index_expr)
4707 {
4708   Location loc = this->location_;
4709 
4710   Channel_type* ct = this->channel_->type()->channel_type();
4711   if (ct == NULL)
4712     return;
4713 
4714   Type* valtype = ct->element_type();
4715   Temporary_statement* val = Statement::make_temporary(valtype, NULL, loc);
4716   b->add_statement(val);
4717 
4718   Expression* valref = Expression::make_temporary_reference(val, loc);
4719   Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
4720 
4721   Temporary_statement* closed_temp = NULL;
4722 
4723   Expression* call;
4724   if (this->closed_ == NULL && this->closedvar_ == NULL)
4725     call = Runtime::make_call(Runtime::SELECTRECV, loc, 4, selref, chanref,
4726 			      valaddr, index_expr);
4727   else
4728     {
4729       closed_temp = Statement::make_temporary(Type::lookup_bool_type(), NULL,
4730 					      loc);
4731       b->add_statement(closed_temp);
4732       Expression* cref = Expression::make_temporary_reference(closed_temp,
4733 							      loc);
4734       Expression* caddr = Expression::make_unary(OPERATOR_AND, cref, loc);
4735       call = Runtime::make_call(Runtime::SELECTRECV2, loc, 5, selref, chanref,
4736 				valaddr, caddr, index_expr);
4737     }
4738 
4739   b->add_statement(Statement::make_statement(call, true));
4740 
4741   // If the block of statements is executed, arrange for the received
4742   // value to move from VAL to the place where the statements expect
4743   // it.
4744 
4745   Block* init = NULL;
4746 
4747   if (this->var_ != NULL)
4748     {
4749       go_assert(this->val_ == NULL);
4750       valref = Expression::make_temporary_reference(val, loc);
4751       this->var_->var_value()->set_init(valref);
4752       this->var_->var_value()->clear_type_from_chan_element();
4753     }
4754   else if (this->val_ != NULL && !this->val_->is_sink_expression())
4755     {
4756       init = new Block(b, loc);
4757       valref = Expression::make_temporary_reference(val, loc);
4758       init->add_statement(Statement::make_assignment(this->val_, valref, loc));
4759     }
4760 
4761   if (this->closedvar_ != NULL)
4762     {
4763       go_assert(this->closed_ == NULL);
4764       Expression* cref = Expression::make_temporary_reference(closed_temp,
4765 							      loc);
4766       this->closedvar_->var_value()->set_init(cref);
4767     }
4768   else if (this->closed_ != NULL && !this->closed_->is_sink_expression())
4769     {
4770       if (init == NULL)
4771 	init = new Block(b, loc);
4772       Expression* cref = Expression::make_temporary_reference(closed_temp,
4773 							      loc);
4774       init->add_statement(Statement::make_assignment(this->closed_, cref,
4775 						     loc));
4776     }
4777 
4778   if (init != NULL)
4779     {
4780       gogo->lower_block(function, init);
4781 
4782       if (this->statements_ != NULL)
4783 	init->add_statement(Statement::make_block_statement(this->statements_,
4784 							    loc));
4785       this->statements_ = init;
4786     }
4787 }
4788 
4789 // Determine types.
4790 
4791 void
determine_types()4792 Select_clauses::Select_clause::determine_types()
4793 {
4794   go_assert(this->is_lowered_);
4795   if (this->statements_ != NULL)
4796     this->statements_->determine_types();
4797 }
4798 
4799 // Check types.
4800 
4801 void
check_types()4802 Select_clauses::Select_clause::check_types()
4803 {
4804   if (this->is_default_)
4805     return;
4806 
4807   Channel_type* ct = this->channel_->type()->channel_type();
4808   if (ct == NULL)
4809     {
4810       error_at(this->channel_->location(), "expected channel");
4811       return;
4812     }
4813 
4814   if (this->is_send_ && !ct->may_send())
4815     error_at(this->location(), "invalid send on receive-only channel");
4816   else if (!this->is_send_ && !ct->may_receive())
4817     error_at(this->location(), "invalid receive on send-only channel");
4818 }
4819 
4820 // Analyze the dataflow across each case statement.
4821 
4822 void
analyze_dataflow(Dataflow * dataflow)4823 Select_clauses::Select_clause::analyze_dataflow(Dataflow* dataflow)
4824 {
4825   if (this->is_default_)
4826     return;
4827 
4828   // For a CommClause, the dataflow analysis should record a definition of
4829   // VAR and CLOSEDVAR
4830   if (this->var_ != NULL && !this->var_->is_sink())
4831     dataflow->add_def(this->var_, this->channel_, NULL, false);
4832   if (this->closedvar_ != NULL && !this->closedvar_->is_sink())
4833     dataflow->add_def(this->closedvar_, this->channel_, NULL, false);
4834 }
4835 
4836 // Whether this clause may fall through to the statement which follows
4837 // the overall select statement.
4838 
4839 bool
may_fall_through() const4840 Select_clauses::Select_clause::may_fall_through() const
4841 {
4842   if (this->statements_ == NULL)
4843     return true;
4844   return this->statements_->may_fall_through();
4845 }
4846 
4847 // Return the backend representation for the statements to execute.
4848 
4849 Bstatement*
get_statements_backend(Translate_context * context)4850 Select_clauses::Select_clause::get_statements_backend(
4851     Translate_context* context)
4852 {
4853   if (this->statements_ == NULL)
4854     return NULL;
4855   Bblock* bblock = this->statements_->get_backend(context);
4856   return context->backend()->block_statement(bblock);
4857 }
4858 
4859 // Dump the AST representation for a select case clause
4860 
4861 void
dump_clause(Ast_dump_context * ast_dump_context) const4862 Select_clauses::Select_clause::dump_clause(
4863     Ast_dump_context* ast_dump_context) const
4864 {
4865   ast_dump_context->print_indent();
4866   if (this->is_default_)
4867     {
4868       ast_dump_context->ostream() << "default:";
4869     }
4870   else
4871     {
4872       ast_dump_context->ostream() << "case "  ;
4873       if (this->is_send_)
4874         {
4875           ast_dump_context->dump_expression(this->channel_);
4876           ast_dump_context->ostream() << " <- " ;
4877 	  if (this->val_ != NULL)
4878 	    ast_dump_context->dump_expression(this->val_);
4879         }
4880       else
4881         {
4882 	  if (this->val_ != NULL)
4883 	    ast_dump_context->dump_expression(this->val_);
4884           if (this->closed_ != NULL)
4885             {
4886 	      // FIXME: can val_ == NULL and closed_ ! = NULL?
4887               ast_dump_context->ostream() << " , " ;
4888               ast_dump_context->dump_expression(this->closed_);
4889             }
4890           if (this->closedvar_ != NULL || this->var_ != NULL)
4891             ast_dump_context->ostream() << " := " ;
4892 
4893           ast_dump_context->ostream() << " <- " ;
4894           ast_dump_context->dump_expression(this->channel_);
4895         }
4896       ast_dump_context->ostream() << ":" ;
4897     }
4898   ast_dump_context->dump_block(this->statements_);
4899 }
4900 
4901 // Class Select_clauses.
4902 
4903 // Traversal.
4904 
4905 int
traverse(Traverse * traverse)4906 Select_clauses::traverse(Traverse* traverse)
4907 {
4908   for (Clauses::iterator p = this->clauses_.begin();
4909        p != this->clauses_.end();
4910        ++p)
4911     {
4912       if (p->traverse(traverse) == TRAVERSE_EXIT)
4913 	return TRAVERSE_EXIT;
4914     }
4915   return TRAVERSE_CONTINUE;
4916 }
4917 
4918 // Lowering.  Here we pull out the channel and the send values, to
4919 // enforce the order of evaluation.  We also add explicit send and
4920 // receive statements to the clauses.
4921 
4922 void
lower(Gogo * gogo,Named_object * function,Block * b,Temporary_statement * sel)4923 Select_clauses::lower(Gogo* gogo, Named_object* function, Block* b,
4924 		      Temporary_statement* sel)
4925 {
4926   for (Clauses::iterator p = this->clauses_.begin();
4927        p != this->clauses_.end();
4928        ++p)
4929     p->lower(gogo, function, b, sel);
4930 }
4931 
4932 // Determine types.
4933 
4934 void
determine_types()4935 Select_clauses::determine_types()
4936 {
4937   for (Clauses::iterator p = this->clauses_.begin();
4938        p != this->clauses_.end();
4939        ++p)
4940     p->determine_types();
4941 }
4942 
4943 // Check types.
4944 
4945 void
check_types()4946 Select_clauses::check_types()
4947 {
4948   for (Clauses::iterator p = this->clauses_.begin();
4949        p != this->clauses_.end();
4950        ++p)
4951     p->check_types();
4952 }
4953 
4954 // Analyze the dataflow across each case statement.
4955 
4956 void
analyze_dataflow(Dataflow * dataflow)4957 Select_clauses::analyze_dataflow(Dataflow* dataflow)
4958 {
4959   for (Clauses::iterator p = this->clauses_.begin();
4960        p != this->clauses_.end();
4961        ++p)
4962     p->analyze_dataflow(dataflow);
4963 }
4964 
4965 // Return whether these select clauses fall through to the statement
4966 // following the overall select statement.
4967 
4968 bool
may_fall_through() const4969 Select_clauses::may_fall_through() const
4970 {
4971   for (Clauses::const_iterator p = this->clauses_.begin();
4972        p != this->clauses_.end();
4973        ++p)
4974     if (p->may_fall_through())
4975       return true;
4976   return false;
4977 }
4978 
4979 // Convert to the backend representation.  We have already accumulated
4980 // all the select information.  Now we call selectgo, which will
4981 // return the index of the clause to execute.
4982 
4983 Bstatement*
get_backend(Translate_context * context,Temporary_statement * sel,Unnamed_label * break_label,Location location)4984 Select_clauses::get_backend(Translate_context* context,
4985 			    Temporary_statement* sel,
4986 			    Unnamed_label *break_label,
4987 			    Location location)
4988 {
4989   size_t count = this->clauses_.size();
4990   std::vector<std::vector<Bexpression*> > cases(count);
4991   std::vector<Bstatement*> clauses(count);
4992 
4993   Type* int32_type = Type::lookup_integer_type("int32");
4994 
4995   int i = 0;
4996   for (Clauses::iterator p = this->clauses_.begin();
4997        p != this->clauses_.end();
4998        ++p, ++i)
4999     {
5000       int index = p->index();
5001       Expression* index_expr = Expression::make_integer_ul(index, int32_type,
5002 							   location);
5003       cases[i].push_back(index_expr->get_backend(context));
5004 
5005       Bstatement* s = p->get_statements_backend(context);
5006       Location gloc = (p->statements() == NULL
5007 		       ? p->location()
5008 		       : p->statements()->end_location());
5009       Bstatement* g = break_label->get_goto(context, gloc);
5010 
5011       if (s == NULL)
5012 	clauses[i] = g;
5013       else
5014 	clauses[i] = context->backend()->compound_statement(s, g);
5015     }
5016 
5017   Expression* selref = Expression::make_temporary_reference(sel, location);
5018   Expression* call = Runtime::make_call(Runtime::SELECTGO, location, 1,
5019 					selref);
5020   context->gogo()->lower_expression(context->function(), NULL, &call);
5021   Bexpression* bcall = call->get_backend(context);
5022 
5023   if (count == 0)
5024     return context->backend()->expression_statement(bcall);
5025 
5026   std::vector<Bstatement*> statements;
5027   statements.reserve(2);
5028 
5029   Bfunction* bfunction = context->function()->func_value()->get_decl();
5030   Bstatement* switch_stmt = context->backend()->switch_statement(bfunction,
5031 								 bcall,
5032 								 cases,
5033 								 clauses,
5034 								 location);
5035   statements.push_back(switch_stmt);
5036 
5037   Bstatement* ldef = break_label->get_definition(context);
5038   statements.push_back(ldef);
5039 
5040   return context->backend()->statement_list(statements);
5041 }
5042 // Dump the AST representation for select clauses.
5043 
5044 void
dump_clauses(Ast_dump_context * ast_dump_context) const5045 Select_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
5046 {
5047   for (Clauses::const_iterator p = this->clauses_.begin();
5048        p != this->clauses_.end();
5049        ++p)
5050     p->dump_clause(ast_dump_context);
5051 }
5052 
5053 // Class Select_statement.
5054 
5055 // Return the break label for this switch statement, creating it if
5056 // necessary.
5057 
5058 Unnamed_label*
break_label()5059 Select_statement::break_label()
5060 {
5061   if (this->break_label_ == NULL)
5062     this->break_label_ = new Unnamed_label(this->location());
5063   return this->break_label_;
5064 }
5065 
5066 // Lower a select statement.  This will still return a select
5067 // statement, but it will be modified to implement the order of
5068 // evaluation rules, and to include the send and receive statements as
5069 // explicit statements in the clauses.
5070 
5071 Statement*
do_lower(Gogo * gogo,Named_object * function,Block * enclosing,Statement_inserter *)5072 Select_statement::do_lower(Gogo* gogo, Named_object* function,
5073 			   Block* enclosing, Statement_inserter*)
5074 {
5075   if (this->is_lowered_)
5076     return this;
5077 
5078   Location loc = this->location();
5079 
5080   Block* b = new Block(enclosing, loc);
5081 
5082   go_assert(this->sel_ == NULL);
5083 
5084   Expression* size_expr = Expression::make_integer_ul(this->clauses_->size(),
5085 						      NULL, loc);
5086   Expression* call = Runtime::make_call(Runtime::NEWSELECT, loc, 1, size_expr);
5087 
5088   this->sel_ = Statement::make_temporary(NULL, call, loc);
5089   b->add_statement(this->sel_);
5090 
5091   this->clauses_->lower(gogo, function, b, this->sel_);
5092   this->is_lowered_ = true;
5093   b->add_statement(this);
5094 
5095   return Statement::make_block_statement(b, loc);
5096 }
5097 
5098 // Whether the select statement itself may fall through to the following
5099 // statement.
5100 
5101 bool
do_may_fall_through() const5102 Select_statement::do_may_fall_through() const
5103 {
5104   // A select statement is terminating if no break statement
5105   // refers to it and all of its clauses are terminating.
5106   if (this->break_label_ != NULL)
5107     return true;
5108   return this->clauses_->may_fall_through();
5109 }
5110 
5111 // Return the backend representation for a select statement.
5112 
5113 Bstatement*
do_get_backend(Translate_context * context)5114 Select_statement::do_get_backend(Translate_context* context)
5115 {
5116   return this->clauses_->get_backend(context, this->sel_, this->break_label(),
5117 				     this->location());
5118 }
5119 
5120 // Dump the AST representation for a select statement.
5121 
5122 void
do_dump_statement(Ast_dump_context * ast_dump_context) const5123 Select_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
5124 {
5125   ast_dump_context->print_indent();
5126   ast_dump_context->ostream() << "select";
5127   if (ast_dump_context->dump_subblocks())
5128     {
5129       ast_dump_context->ostream() << " {" << std::endl;
5130       this->clauses_->dump_clauses(ast_dump_context);
5131       ast_dump_context->ostream() << "}";
5132     }
5133   ast_dump_context->ostream() << std::endl;
5134 }
5135 
5136 // Make a select statement.
5137 
5138 Select_statement*
make_select_statement(Location location)5139 Statement::make_select_statement(Location location)
5140 {
5141   return new Select_statement(location);
5142 }
5143 
5144 // Class For_statement.
5145 
5146 // Traversal.
5147 
5148 int
do_traverse(Traverse * traverse)5149 For_statement::do_traverse(Traverse* traverse)
5150 {
5151   if (this->init_ != NULL)
5152     {
5153       if (this->init_->traverse(traverse) == TRAVERSE_EXIT)
5154 	return TRAVERSE_EXIT;
5155     }
5156   if (this->cond_ != NULL)
5157     {
5158       if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT)
5159 	return TRAVERSE_EXIT;
5160     }
5161   if (this->post_ != NULL)
5162     {
5163       if (this->post_->traverse(traverse) == TRAVERSE_EXIT)
5164 	return TRAVERSE_EXIT;
5165     }
5166   return this->statements_->traverse(traverse);
5167 }
5168 
5169 // Lower a For_statement into if statements and gotos.  Getting rid of
5170 // complex statements make it easier to handle garbage collection.
5171 
5172 Statement*
do_lower(Gogo *,Named_object *,Block * enclosing,Statement_inserter *)5173 For_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
5174 			Statement_inserter*)
5175 {
5176   Statement* s;
5177   Location loc = this->location();
5178 
5179   Block* b = new Block(enclosing, this->location());
5180   if (this->init_ != NULL)
5181     {
5182       s = Statement::make_block_statement(this->init_,
5183 					  this->init_->start_location());
5184       b->add_statement(s);
5185     }
5186 
5187   Unnamed_label* entry = NULL;
5188   if (this->cond_ != NULL)
5189     {
5190       entry = new Unnamed_label(this->location());
5191       b->add_statement(Statement::make_goto_unnamed_statement(entry, loc));
5192     }
5193 
5194   Unnamed_label* top = new Unnamed_label(this->location());
5195   b->add_statement(Statement::make_unnamed_label_statement(top));
5196 
5197   s = Statement::make_block_statement(this->statements_,
5198 				      this->statements_->start_location());
5199   b->add_statement(s);
5200 
5201   Location end_loc = this->statements_->end_location();
5202 
5203   Unnamed_label* cont = this->continue_label_;
5204   if (cont != NULL)
5205     b->add_statement(Statement::make_unnamed_label_statement(cont));
5206 
5207   if (this->post_ != NULL)
5208     {
5209       s = Statement::make_block_statement(this->post_,
5210 					  this->post_->start_location());
5211       b->add_statement(s);
5212       end_loc = this->post_->end_location();
5213     }
5214 
5215   if (this->cond_ == NULL)
5216     b->add_statement(Statement::make_goto_unnamed_statement(top, end_loc));
5217   else
5218     {
5219       b->add_statement(Statement::make_unnamed_label_statement(entry));
5220 
5221       Location cond_loc = this->cond_->location();
5222       Block* then_block = new Block(b, cond_loc);
5223       s = Statement::make_goto_unnamed_statement(top, cond_loc);
5224       then_block->add_statement(s);
5225 
5226       s = Statement::make_if_statement(this->cond_, then_block, NULL, cond_loc);
5227       b->add_statement(s);
5228     }
5229 
5230   Unnamed_label* brk = this->break_label_;
5231   if (brk != NULL)
5232     b->add_statement(Statement::make_unnamed_label_statement(brk));
5233 
5234   b->set_end_location(end_loc);
5235 
5236   return Statement::make_block_statement(b, loc);
5237 }
5238 
5239 // Return the break label, creating it if necessary.
5240 
5241 Unnamed_label*
break_label()5242 For_statement::break_label()
5243 {
5244   if (this->break_label_ == NULL)
5245     this->break_label_ = new Unnamed_label(this->location());
5246   return this->break_label_;
5247 }
5248 
5249 // Return the continue LABEL_EXPR.
5250 
5251 Unnamed_label*
continue_label()5252 For_statement::continue_label()
5253 {
5254   if (this->continue_label_ == NULL)
5255     this->continue_label_ = new Unnamed_label(this->location());
5256   return this->continue_label_;
5257 }
5258 
5259 // Set the break and continue labels a for statement.  This is used
5260 // when lowering a for range statement.
5261 
5262 void
set_break_continue_labels(Unnamed_label * break_label,Unnamed_label * continue_label)5263 For_statement::set_break_continue_labels(Unnamed_label* break_label,
5264 					 Unnamed_label* continue_label)
5265 {
5266   go_assert(this->break_label_ == NULL && this->continue_label_ == NULL);
5267   this->break_label_ = break_label;
5268   this->continue_label_ = continue_label;
5269 }
5270 
5271 // Whether the overall statement may fall through.
5272 
5273 bool
do_may_fall_through() const5274 For_statement::do_may_fall_through() const
5275 {
5276   // A for loop is terminating if it has no condition and
5277   // no break statement.
5278   if(this->cond_ != NULL)
5279     return true;
5280   if(this->break_label_ != NULL)
5281     return true;
5282   return false;
5283 }
5284 
5285 // Dump the AST representation for a for statement.
5286 
5287 void
do_dump_statement(Ast_dump_context * ast_dump_context) const5288 For_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
5289 {
5290   if (this->init_ != NULL && ast_dump_context->dump_subblocks())
5291     {
5292       ast_dump_context->print_indent();
5293       ast_dump_context->indent();
5294       ast_dump_context->ostream() << "// INIT  " << std::endl;
5295       ast_dump_context->dump_block(this->init_);
5296       ast_dump_context->unindent();
5297     }
5298   ast_dump_context->print_indent();
5299   ast_dump_context->ostream() << "for ";
5300   if (this->cond_ != NULL)
5301     ast_dump_context->dump_expression(this->cond_);
5302 
5303   if (ast_dump_context->dump_subblocks())
5304     {
5305       ast_dump_context->ostream() << " {" << std::endl;
5306       ast_dump_context->dump_block(this->statements_);
5307       if (this->init_ != NULL)
5308 	{
5309 	  ast_dump_context->print_indent();
5310 	  ast_dump_context->ostream() << "// POST " << std::endl;
5311 	  ast_dump_context->dump_block(this->post_);
5312 	}
5313       ast_dump_context->unindent();
5314 
5315       ast_dump_context->print_indent();
5316       ast_dump_context->ostream() << "}";
5317     }
5318 
5319   ast_dump_context->ostream() << std::endl;
5320 }
5321 
5322 // Make a for statement.
5323 
5324 For_statement*
make_for_statement(Block * init,Expression * cond,Block * post,Location location)5325 Statement::make_for_statement(Block* init, Expression* cond, Block* post,
5326 			      Location location)
5327 {
5328   return new For_statement(init, cond, post, location);
5329 }
5330 
5331 // Class For_range_statement.
5332 
5333 // Traversal.
5334 
5335 int
do_traverse(Traverse * traverse)5336 For_range_statement::do_traverse(Traverse* traverse)
5337 {
5338   if (this->index_var_ != NULL)
5339     {
5340       if (this->traverse_expression(traverse, &this->index_var_)
5341 	  == TRAVERSE_EXIT)
5342 	return TRAVERSE_EXIT;
5343     }
5344   if (this->value_var_ != NULL)
5345     {
5346       if (this->traverse_expression(traverse, &this->value_var_)
5347 	  == TRAVERSE_EXIT)
5348 	return TRAVERSE_EXIT;
5349     }
5350   if (this->traverse_expression(traverse, &this->range_) == TRAVERSE_EXIT)
5351     return TRAVERSE_EXIT;
5352   return this->statements_->traverse(traverse);
5353 }
5354 
5355 // Lower a for range statement.  For simplicity we lower this into a
5356 // for statement, which will then be lowered in turn to goto
5357 // statements.
5358 
5359 Statement*
do_lower(Gogo * gogo,Named_object *,Block * enclosing,Statement_inserter *)5360 For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
5361 			      Statement_inserter*)
5362 {
5363   Type* range_type = this->range_->type();
5364   if (range_type->points_to() != NULL
5365       && range_type->points_to()->array_type() != NULL
5366       && !range_type->points_to()->is_slice_type())
5367     range_type = range_type->points_to();
5368 
5369   Type* index_type;
5370   Type* value_type = NULL;
5371   if (range_type->array_type() != NULL)
5372     {
5373       index_type = Type::lookup_integer_type("int");
5374       value_type = range_type->array_type()->element_type();
5375     }
5376   else if (range_type->is_string_type())
5377     {
5378       index_type = Type::lookup_integer_type("int");
5379       value_type = Type::lookup_integer_type("int32");
5380     }
5381   else if (range_type->map_type() != NULL)
5382     {
5383       index_type = range_type->map_type()->key_type();
5384       value_type = range_type->map_type()->val_type();
5385     }
5386   else if (range_type->channel_type() != NULL)
5387     {
5388       index_type = range_type->channel_type()->element_type();
5389       if (this->value_var_ != NULL)
5390 	{
5391 	  if (!this->value_var_->type()->is_error())
5392 	    this->report_error(_("too many variables for range clause "
5393 				 "with channel"));
5394 	  return Statement::make_error_statement(this->location());
5395 	}
5396     }
5397   else
5398     {
5399       this->report_error(_("range clause must have "
5400 			   "array, slice, string, map, or channel type"));
5401       return Statement::make_error_statement(this->location());
5402     }
5403 
5404   Location loc = this->location();
5405   Block* temp_block = new Block(enclosing, loc);
5406 
5407   Named_object* range_object = NULL;
5408   Temporary_statement* range_temp = NULL;
5409   Var_expression* ve = this->range_->var_expression();
5410   if (ve != NULL)
5411     range_object = ve->named_object();
5412   else
5413     {
5414       range_temp = Statement::make_temporary(NULL, this->range_, loc);
5415       temp_block->add_statement(range_temp);
5416       this->range_ = NULL;
5417     }
5418 
5419   Temporary_statement* index_temp = Statement::make_temporary(index_type,
5420 							      NULL, loc);
5421   temp_block->add_statement(index_temp);
5422 
5423   Temporary_statement* value_temp = NULL;
5424   if (this->value_var_ != NULL)
5425     {
5426       value_temp = Statement::make_temporary(value_type, NULL, loc);
5427       temp_block->add_statement(value_temp);
5428     }
5429 
5430   Block* body = new Block(temp_block, loc);
5431 
5432   Block* init;
5433   Expression* cond;
5434   Block* iter_init;
5435   Block* post;
5436 
5437   // Arrange to do a loop appropriate for the type.  We will produce
5438   //   for INIT ; COND ; POST {
5439   //           ITER_INIT
5440   //           INDEX = INDEX_TEMP
5441   //           VALUE = VALUE_TEMP // If there is a value
5442   //           original statements
5443   //   }
5444 
5445   if (range_type->is_slice_type())
5446     this->lower_range_slice(gogo, temp_block, body, range_object, range_temp,
5447 			    index_temp, value_temp, &init, &cond, &iter_init,
5448 			    &post);
5449   else if (range_type->array_type() != NULL)
5450     this->lower_range_array(gogo, temp_block, body, range_object, range_temp,
5451 			    index_temp, value_temp, &init, &cond, &iter_init,
5452 			    &post);
5453   else if (range_type->is_string_type())
5454     this->lower_range_string(gogo, temp_block, body, range_object, range_temp,
5455 			     index_temp, value_temp, &init, &cond, &iter_init,
5456 			     &post);
5457   else if (range_type->map_type() != NULL)
5458     this->lower_range_map(gogo, temp_block, body, range_object, range_temp,
5459 			  index_temp, value_temp, &init, &cond, &iter_init,
5460 			  &post);
5461   else if (range_type->channel_type() != NULL)
5462     this->lower_range_channel(gogo, temp_block, body, range_object, range_temp,
5463 			      index_temp, value_temp, &init, &cond, &iter_init,
5464 			      &post);
5465   else
5466     go_unreachable();
5467 
5468   if (iter_init != NULL)
5469     body->add_statement(Statement::make_block_statement(iter_init, loc));
5470 
5471   if (this->index_var_ != NULL)
5472     {
5473       Statement* assign;
5474       Expression* index_ref =
5475 	Expression::make_temporary_reference(index_temp, loc);
5476       if (this->value_var_ == NULL)
5477 	assign = Statement::make_assignment(this->index_var_, index_ref, loc);
5478       else
5479 	{
5480 	  Expression_list* lhs = new Expression_list();
5481 	  lhs->push_back(this->index_var_);
5482 	  lhs->push_back(this->value_var_);
5483 
5484 	  Expression_list* rhs = new Expression_list();
5485 	  rhs->push_back(index_ref);
5486 	  rhs->push_back(Expression::make_temporary_reference(value_temp, loc));
5487 
5488 	  assign = Statement::make_tuple_assignment(lhs, rhs, loc);
5489 	}
5490       body->add_statement(assign);
5491     }
5492 
5493   body->add_statement(Statement::make_block_statement(this->statements_, loc));
5494 
5495   body->set_end_location(this->statements_->end_location());
5496 
5497   For_statement* loop = Statement::make_for_statement(init, cond, post,
5498 						      this->location());
5499   loop->add_statements(body);
5500   loop->set_break_continue_labels(this->break_label_, this->continue_label_);
5501 
5502   temp_block->add_statement(loop);
5503 
5504   return Statement::make_block_statement(temp_block, loc);
5505 }
5506 
5507 // Return a reference to the range, which may be in RANGE_OBJECT or in
5508 // RANGE_TEMP.
5509 
5510 Expression*
make_range_ref(Named_object * range_object,Temporary_statement * range_temp,Location loc)5511 For_range_statement::make_range_ref(Named_object* range_object,
5512 				    Temporary_statement* range_temp,
5513 				    Location loc)
5514 {
5515   if (range_object != NULL)
5516     return Expression::make_var_reference(range_object, loc);
5517   else
5518     return Expression::make_temporary_reference(range_temp, loc);
5519 }
5520 
5521 // Return a call to the predeclared function FUNCNAME passing a
5522 // reference to the temporary variable ARG.
5523 
5524 Expression*
call_builtin(Gogo * gogo,const char * funcname,Expression * arg,Location loc)5525 For_range_statement::call_builtin(Gogo* gogo, const char* funcname,
5526 				  Expression* arg,
5527 				  Location loc)
5528 {
5529   Named_object* no = gogo->lookup_global(funcname);
5530   go_assert(no != NULL && no->is_function_declaration());
5531   Expression* func = Expression::make_func_reference(no, NULL, loc);
5532   Expression_list* params = new Expression_list();
5533   params->push_back(arg);
5534   return Expression::make_call(func, params, false, loc);
5535 }
5536 
5537 // Lower a for range over an array.
5538 
5539 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)5540 For_range_statement::lower_range_array(Gogo* gogo,
5541 				       Block* enclosing,
5542 				       Block* body_block,
5543 				       Named_object* range_object,
5544 				       Temporary_statement* range_temp,
5545 				       Temporary_statement* index_temp,
5546 				       Temporary_statement* value_temp,
5547 				       Block** pinit,
5548 				       Expression** pcond,
5549 				       Block** piter_init,
5550 				       Block** ppost)
5551 {
5552   Location loc = this->location();
5553 
5554   // The loop we generate:
5555   //   len_temp := len(range)
5556   //   range_temp := range
5557   //   for index_temp = 0; index_temp < len_temp; index_temp++ {
5558   //           value_temp = range_temp[index_temp]
5559   //           index = index_temp
5560   //           value = value_temp
5561   //           original body
5562   //   }
5563 
5564   // Set *PINIT to
5565   //   var len_temp int
5566   //   len_temp = len(range)
5567   //   index_temp = 0
5568 
5569   Block* init = new Block(enclosing, loc);
5570 
5571   Expression* ref = this->make_range_ref(range_object, range_temp, loc);
5572   range_temp = Statement::make_temporary(NULL, ref, loc);
5573   Expression* len_call = this->call_builtin(gogo, "len", ref, loc);
5574   Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
5575 							    len_call, loc);
5576   init->add_statement(range_temp);
5577   init->add_statement(len_temp);
5578 
5579   Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);
5580 
5581   Temporary_reference_expression* tref =
5582     Expression::make_temporary_reference(index_temp, loc);
5583   tref->set_is_lvalue();
5584   Statement* s = Statement::make_assignment(tref, zexpr, loc);
5585   init->add_statement(s);
5586 
5587   *pinit = init;
5588 
5589   // Set *PCOND to
5590   //   index_temp < len_temp
5591 
5592   ref = Expression::make_temporary_reference(index_temp, loc);
5593   Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
5594   Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);
5595 
5596   *pcond = lt;
5597 
5598   // Set *PITER_INIT to
5599   //   value_temp = range[index_temp]
5600 
5601   Block* iter_init = NULL;
5602   if (value_temp != NULL)
5603     {
5604       iter_init = new Block(body_block, loc);
5605 
5606       ref = Expression::make_temporary_reference(range_temp, loc);
5607       Expression* ref2 = Expression::make_temporary_reference(index_temp, loc);
5608       Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
5609 
5610       tref = Expression::make_temporary_reference(value_temp, loc);
5611       tref->set_is_lvalue();
5612       s = Statement::make_assignment(tref, index, loc);
5613 
5614       iter_init->add_statement(s);
5615     }
5616   *piter_init = iter_init;
5617 
5618   // Set *PPOST to
5619   //   index_temp++
5620 
5621   Block* post = new Block(enclosing, loc);
5622   tref = Expression::make_temporary_reference(index_temp, loc);
5623   tref->set_is_lvalue();
5624   s = Statement::make_inc_statement(tref);
5625   post->add_statement(s);
5626   *ppost = post;
5627 }
5628 
5629 // Lower a for range over a slice.
5630 
5631 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)5632 For_range_statement::lower_range_slice(Gogo* gogo,
5633 				       Block* enclosing,
5634 				       Block* body_block,
5635 				       Named_object* range_object,
5636 				       Temporary_statement* range_temp,
5637 				       Temporary_statement* index_temp,
5638 				       Temporary_statement* value_temp,
5639 				       Block** pinit,
5640 				       Expression** pcond,
5641 				       Block** piter_init,
5642 				       Block** ppost)
5643 {
5644   Location loc = this->location();
5645 
5646   // The loop we generate:
5647   //   for_temp := range
5648   //   len_temp := len(for_temp)
5649   //   for index_temp = 0; index_temp < len_temp; index_temp++ {
5650   //           value_temp = for_temp[index_temp]
5651   //           index = index_temp
5652   //           value = value_temp
5653   //           original body
5654   //   }
5655   //
5656   // Using for_temp means that we don't need to check bounds when
5657   // fetching range_temp[index_temp].
5658 
5659   // Set *PINIT to
5660   //   range_temp := range
5661   //   var len_temp int
5662   //   len_temp = len(range_temp)
5663   //   index_temp = 0
5664 
5665   Block* init = new Block(enclosing, loc);
5666 
5667   Expression* ref = this->make_range_ref(range_object, range_temp, loc);
5668   Temporary_statement* for_temp = Statement::make_temporary(NULL, ref, loc);
5669   init->add_statement(for_temp);
5670 
5671   ref = Expression::make_temporary_reference(for_temp, loc);
5672   Expression* len_call = this->call_builtin(gogo, "len", ref, loc);
5673   Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
5674 							    len_call, loc);
5675   init->add_statement(len_temp);
5676 
5677   Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);
5678 
5679   Temporary_reference_expression* tref =
5680     Expression::make_temporary_reference(index_temp, loc);
5681   tref->set_is_lvalue();
5682   Statement* s = Statement::make_assignment(tref, zexpr, loc);
5683   init->add_statement(s);
5684 
5685   *pinit = init;
5686 
5687   // Set *PCOND to
5688   //   index_temp < len_temp
5689 
5690   ref = Expression::make_temporary_reference(index_temp, loc);
5691   Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
5692   Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);
5693 
5694   *pcond = lt;
5695 
5696   // Set *PITER_INIT to
5697   //   value_temp = range[index_temp]
5698 
5699   Block* iter_init = NULL;
5700   if (value_temp != NULL)
5701     {
5702       iter_init = new Block(body_block, loc);
5703 
5704       ref = Expression::make_temporary_reference(for_temp, loc);
5705       Expression* ref2 = Expression::make_temporary_reference(index_temp, loc);
5706       Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
5707 
5708       tref = Expression::make_temporary_reference(value_temp, loc);
5709       tref->set_is_lvalue();
5710       s = Statement::make_assignment(tref, index, loc);
5711 
5712       iter_init->add_statement(s);
5713     }
5714   *piter_init = iter_init;
5715 
5716   // Set *PPOST to
5717   //   index_temp++
5718 
5719   Block* post = new Block(enclosing, loc);
5720   tref = Expression::make_temporary_reference(index_temp, loc);
5721   tref->set_is_lvalue();
5722   s = Statement::make_inc_statement(tref);
5723   post->add_statement(s);
5724   *ppost = post;
5725 }
5726 
5727 // Lower a for range over a string.
5728 
5729 void
lower_range_string(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)5730 For_range_statement::lower_range_string(Gogo*,
5731 					Block* enclosing,
5732 					Block* body_block,
5733 					Named_object* range_object,
5734 					Temporary_statement* range_temp,
5735 					Temporary_statement* index_temp,
5736 					Temporary_statement* value_temp,
5737 					Block** pinit,
5738 					Expression** pcond,
5739 					Block** piter_init,
5740 					Block** ppost)
5741 {
5742   Location loc = this->location();
5743 
5744   // The loop we generate:
5745   //   var next_index_temp int
5746   //   for index_temp = 0; ; index_temp = next_index_temp {
5747   //           next_index_temp, value_temp = stringiter2(range, index_temp)
5748   //           if next_index_temp == 0 {
5749   //                   break
5750   //           }
5751   //           index = index_temp
5752   //           value = value_temp
5753   //           original body
5754   //   }
5755 
5756   // Set *PINIT to
5757   //   var next_index_temp int
5758   //   index_temp = 0
5759 
5760   Block* init = new Block(enclosing, loc);
5761 
5762   Temporary_statement* next_index_temp =
5763     Statement::make_temporary(index_temp->type(), NULL, loc);
5764   init->add_statement(next_index_temp);
5765 
5766   Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);
5767 
5768   Temporary_reference_expression* ref =
5769     Expression::make_temporary_reference(index_temp, loc);
5770   ref->set_is_lvalue();
5771   Statement* s = Statement::make_assignment(ref, zexpr, loc);
5772 
5773   init->add_statement(s);
5774   *pinit = init;
5775 
5776   // The loop has no condition.
5777 
5778   *pcond = NULL;
5779 
5780   // Set *PITER_INIT to
5781   //   next_index_temp = runtime.stringiter(range, index_temp)
5782   // or
5783   //   next_index_temp, value_temp = runtime.stringiter2(range, index_temp)
5784   // followed by
5785   //   if next_index_temp == 0 {
5786   //           break
5787   //   }
5788 
5789   Block* iter_init = new Block(body_block, loc);
5790 
5791   Expression* p1 = this->make_range_ref(range_object, range_temp, loc);
5792   Expression* p2 = Expression::make_temporary_reference(index_temp, loc);
5793   Call_expression* call = Runtime::make_call((value_temp == NULL
5794 					      ? Runtime::STRINGITER
5795 					      : Runtime::STRINGITER2),
5796 					     loc, 2, p1, p2);
5797 
5798   if (value_temp == NULL)
5799     {
5800       ref = Expression::make_temporary_reference(next_index_temp, loc);
5801       ref->set_is_lvalue();
5802       s = Statement::make_assignment(ref, call, loc);
5803     }
5804   else
5805     {
5806       Expression_list* lhs = new Expression_list();
5807 
5808       ref = Expression::make_temporary_reference(next_index_temp, loc);
5809       ref->set_is_lvalue();
5810       lhs->push_back(ref);
5811 
5812       ref = Expression::make_temporary_reference(value_temp, loc);
5813       ref->set_is_lvalue();
5814       lhs->push_back(ref);
5815 
5816       Expression_list* rhs = new Expression_list();
5817       rhs->push_back(Expression::make_call_result(call, 0));
5818       rhs->push_back(Expression::make_call_result(call, 1));
5819 
5820       s = Statement::make_tuple_assignment(lhs, rhs, loc);
5821     }
5822   iter_init->add_statement(s);
5823 
5824   ref = Expression::make_temporary_reference(next_index_temp, loc);
5825   zexpr = Expression::make_integer_ul(0, NULL, loc);
5826   Expression* equals = Expression::make_binary(OPERATOR_EQEQ, ref, zexpr, loc);
5827 
5828   Block* then_block = new Block(iter_init, loc);
5829   s = Statement::make_break_statement(this->break_label(), loc);
5830   then_block->add_statement(s);
5831 
5832   s = Statement::make_if_statement(equals, then_block, NULL, loc);
5833   iter_init->add_statement(s);
5834 
5835   *piter_init = iter_init;
5836 
5837   // Set *PPOST to
5838   //   index_temp = next_index_temp
5839 
5840   Block* post = new Block(enclosing, loc);
5841 
5842   Temporary_reference_expression* lhs =
5843     Expression::make_temporary_reference(index_temp, loc);
5844   lhs->set_is_lvalue();
5845   Expression* rhs = Expression::make_temporary_reference(next_index_temp, loc);
5846   s = Statement::make_assignment(lhs, rhs, loc);
5847 
5848   post->add_statement(s);
5849   *ppost = post;
5850 }
5851 
5852 // Lower a for range over a map.
5853 
5854 void
lower_range_map(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)5855 For_range_statement::lower_range_map(Gogo*,
5856 				     Block* enclosing,
5857 				     Block* body_block,
5858 				     Named_object* range_object,
5859 				     Temporary_statement* range_temp,
5860 				     Temporary_statement* index_temp,
5861 				     Temporary_statement* value_temp,
5862 				     Block** pinit,
5863 				     Expression** pcond,
5864 				     Block** piter_init,
5865 				     Block** ppost)
5866 {
5867   Location loc = this->location();
5868 
5869   // The runtime uses a struct to handle ranges over a map.  The
5870   // struct is four pointers long.  The first pointer is NULL when we
5871   // have completed the iteration.
5872 
5873   // The loop we generate:
5874   //   var hiter map_iteration_struct
5875   //   for mapiterinit(range, &hiter); hiter[0] != nil; mapiternext(&hiter) {
5876   //           mapiter2(hiter, &index_temp, &value_temp)
5877   //           index = index_temp
5878   //           value = value_temp
5879   //           original body
5880   //   }
5881 
5882   // Set *PINIT to
5883   //   var hiter map_iteration_struct
5884   //   runtime.mapiterinit(range, &hiter)
5885 
5886   Block* init = new Block(enclosing, loc);
5887 
5888   Type* map_iteration_type = Runtime::map_iteration_type();
5889   Temporary_statement* hiter = Statement::make_temporary(map_iteration_type,
5890 							 NULL, loc);
5891   init->add_statement(hiter);
5892 
5893   Expression* p1 = this->make_range_ref(range_object, range_temp, loc);
5894   Expression* ref = Expression::make_temporary_reference(hiter, loc);
5895   Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
5896   Expression* call = Runtime::make_call(Runtime::MAPITERINIT, loc, 2, p1, p2);
5897   init->add_statement(Statement::make_statement(call, true));
5898 
5899   *pinit = init;
5900 
5901   // Set *PCOND to
5902   //   hiter[0] != nil
5903 
5904   ref = Expression::make_temporary_reference(hiter, loc);
5905   Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);
5906   Expression* index = Expression::make_index(ref, zexpr, NULL, NULL, loc);
5907   Expression* ne = Expression::make_binary(OPERATOR_NOTEQ, index,
5908 					   Expression::make_nil(loc),
5909 					   loc);
5910   *pcond = ne;
5911 
5912   // Set *PITER_INIT to
5913   //   mapiter1(hiter, &index_temp)
5914   // or
5915   //   mapiter2(hiter, &index_temp, &value_temp)
5916 
5917   Block* iter_init = new Block(body_block, loc);
5918 
5919   ref = Expression::make_temporary_reference(hiter, loc);
5920   p1 = Expression::make_unary(OPERATOR_AND, ref, loc);
5921   ref = Expression::make_temporary_reference(index_temp, loc);
5922   p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
5923   if (value_temp == NULL)
5924     call = Runtime::make_call(Runtime::MAPITER1, loc, 2, p1, p2);
5925   else
5926     {
5927       ref = Expression::make_temporary_reference(value_temp, loc);
5928       Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
5929       call = Runtime::make_call(Runtime::MAPITER2, loc, 3, p1, p2, p3);
5930     }
5931   iter_init->add_statement(Statement::make_statement(call, true));
5932 
5933   *piter_init = iter_init;
5934 
5935   // Set *PPOST to
5936   //   mapiternext(&hiter)
5937 
5938   Block* post = new Block(enclosing, loc);
5939 
5940   ref = Expression::make_temporary_reference(hiter, loc);
5941   p1 = Expression::make_unary(OPERATOR_AND, ref, loc);
5942   call = Runtime::make_call(Runtime::MAPITERNEXT, loc, 1, p1);
5943   post->add_statement(Statement::make_statement(call, true));
5944 
5945   *ppost = post;
5946 }
5947 
5948 // Lower a for range over a channel.
5949 
5950 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)5951 For_range_statement::lower_range_channel(Gogo*,
5952 					 Block*,
5953 					 Block* body_block,
5954 					 Named_object* range_object,
5955 					 Temporary_statement* range_temp,
5956 					 Temporary_statement* index_temp,
5957 					 Temporary_statement* value_temp,
5958 					 Block** pinit,
5959 					 Expression** pcond,
5960 					 Block** piter_init,
5961 					 Block** ppost)
5962 {
5963   go_assert(value_temp == NULL);
5964 
5965   Location loc = this->location();
5966 
5967   // The loop we generate:
5968   //   for {
5969   //           index_temp, ok_temp = <-range
5970   //           if !ok_temp {
5971   //                   break
5972   //           }
5973   //           index = index_temp
5974   //           original body
5975   //   }
5976 
5977   // We have no initialization code, no condition, and no post code.
5978 
5979   *pinit = NULL;
5980   *pcond = NULL;
5981   *ppost = NULL;
5982 
5983   // Set *PITER_INIT to
5984   //   index_temp, ok_temp = <-range
5985   //   if !ok_temp {
5986   //           break
5987   //   }
5988 
5989   Block* iter_init = new Block(body_block, loc);
5990 
5991   Temporary_statement* ok_temp =
5992     Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
5993   iter_init->add_statement(ok_temp);
5994 
5995   Expression* cref = this->make_range_ref(range_object, range_temp, loc);
5996   Temporary_reference_expression* iref =
5997     Expression::make_temporary_reference(index_temp, loc);
5998   iref->set_is_lvalue();
5999   Temporary_reference_expression* oref =
6000     Expression::make_temporary_reference(ok_temp, loc);
6001   oref->set_is_lvalue();
6002   Statement* s = Statement::make_tuple_receive_assignment(iref, oref, cref,
6003 							  loc);
6004   iter_init->add_statement(s);
6005 
6006   Block* then_block = new Block(iter_init, loc);
6007   s = Statement::make_break_statement(this->break_label(), loc);
6008   then_block->add_statement(s);
6009 
6010   oref = Expression::make_temporary_reference(ok_temp, loc);
6011   Expression* cond = Expression::make_unary(OPERATOR_NOT, oref, loc);
6012   s = Statement::make_if_statement(cond, then_block, NULL, loc);
6013   iter_init->add_statement(s);
6014 
6015   *piter_init = iter_init;
6016 }
6017 
6018 // Return the break LABEL_EXPR.
6019 
6020 Unnamed_label*
break_label()6021 For_range_statement::break_label()
6022 {
6023   if (this->break_label_ == NULL)
6024     this->break_label_ = new Unnamed_label(this->location());
6025   return this->break_label_;
6026 }
6027 
6028 // Return the continue LABEL_EXPR.
6029 
6030 Unnamed_label*
continue_label()6031 For_range_statement::continue_label()
6032 {
6033   if (this->continue_label_ == NULL)
6034     this->continue_label_ = new Unnamed_label(this->location());
6035   return this->continue_label_;
6036 }
6037 
6038 // Dump the AST representation for a for range statement.
6039 
6040 void
do_dump_statement(Ast_dump_context * ast_dump_context) const6041 For_range_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
6042 {
6043 
6044   ast_dump_context->print_indent();
6045   ast_dump_context->ostream() << "for ";
6046   ast_dump_context->dump_expression(this->index_var_);
6047   if (this->value_var_ != NULL)
6048     {
6049       ast_dump_context->ostream() << ", ";
6050       ast_dump_context->dump_expression(this->value_var_);
6051     }
6052 
6053   ast_dump_context->ostream() << " = range ";
6054   ast_dump_context->dump_expression(this->range_);
6055   if (ast_dump_context->dump_subblocks())
6056     {
6057       ast_dump_context->ostream() << " {" << std::endl;
6058 
6059       ast_dump_context->indent();
6060 
6061       ast_dump_context->dump_block(this->statements_);
6062 
6063       ast_dump_context->unindent();
6064       ast_dump_context->print_indent();
6065       ast_dump_context->ostream() << "}";
6066     }
6067   ast_dump_context->ostream() << std::endl;
6068 }
6069 
6070 // Make a for statement with a range clause.
6071 
6072 For_range_statement*
make_for_range_statement(Expression * index_var,Expression * value_var,Expression * range,Location location)6073 Statement::make_for_range_statement(Expression* index_var,
6074 				    Expression* value_var,
6075 				    Expression* range,
6076 				    Location location)
6077 {
6078   return new For_range_statement(index_var, value_var, range, location);
6079 }
6080