OSDN Git Service

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