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