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