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