OSDN Git Service

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