OSDN Git Service

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