OSDN Git Service

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