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