OSDN Git Service

compiler: Rewrite handling of untyped numeric constants.
[pf3gnuchains/gcc-fork.git] / gcc / go / gofrontend / statements.cc
1 // statements.cc -- Go frontend statements.
2
3 // Copyright 2009 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 #include "go-system.h"
8
9 #include <gmp.h>
10
11 #include "go-c.h"
12 #include "types.h"
13 #include "expressions.h"
14 #include "gogo.h"
15 #include "runtime.h"
16 #include "backend.h"
17 #include "statements.h"
18 #include "ast-dump.h"
19
20 // Class Statement.
21
22 Statement::Statement(Statement_classification classification,
23                      Location location)
24   : classification_(classification), location_(location)
25 {
26 }
27
28 Statement::~Statement()
29 {
30 }
31
32 // Traverse the tree.  The work of walking the components is handled
33 // by the subclasses.
34
35 int
36 Statement::traverse(Block* block, size_t* pindex, Traverse* traverse)
37 {
38   if (this->classification_ == STATEMENT_ERROR)
39     return TRAVERSE_CONTINUE;
40
41   unsigned int traverse_mask = traverse->traverse_mask();
42
43   if ((traverse_mask & Traverse::traverse_statements) != 0)
44     {
45       int t = traverse->statement(block, pindex, this);
46       if (t == TRAVERSE_EXIT)
47         return TRAVERSE_EXIT;
48       else if (t == TRAVERSE_SKIP_COMPONENTS)
49         return TRAVERSE_CONTINUE;
50     }
51
52   // No point in checking traverse_mask here--a statement may contain
53   // other blocks or statements, and if we got here we always want to
54   // walk them.
55   return this->do_traverse(traverse);
56 }
57
58 // Traverse the contents of a statement.
59
60 int
61 Statement::traverse_contents(Traverse* traverse)
62 {
63   return this->do_traverse(traverse);
64 }
65
66 // Traverse assignments.
67
68 bool
69 Statement::traverse_assignments(Traverse_assignments* tassign)
70 {
71   if (this->classification_ == STATEMENT_ERROR)
72     return false;
73   return this->do_traverse_assignments(tassign);
74 }
75
76 // Traverse an expression in a statement.  This is a helper function
77 // for child classes.
78
79 int
80 Statement::traverse_expression(Traverse* traverse, Expression** expr)
81 {
82   if ((traverse->traverse_mask()
83        & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
84     return TRAVERSE_CONTINUE;
85   return Expression::traverse(expr, traverse);
86 }
87
88 // Traverse an expression list in a statement.  This is a helper
89 // function for child classes.
90
91 int
92 Statement::traverse_expression_list(Traverse* traverse,
93                                     Expression_list* expr_list)
94 {
95   if (expr_list == NULL)
96     return TRAVERSE_CONTINUE;
97   if ((traverse->traverse_mask()
98        & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
99     return TRAVERSE_CONTINUE;
100   return expr_list->traverse(traverse);
101 }
102
103 // Traverse a type in a statement.  This is a helper function for
104 // child classes.
105
106 int
107 Statement::traverse_type(Traverse* traverse, Type* type)
108 {
109   if ((traverse->traverse_mask()
110        & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
111     return TRAVERSE_CONTINUE;
112   return Type::traverse(type, traverse);
113 }
114
115 // Set type information for unnamed constants.  This is really done by
116 // the child class.
117
118 void
119 Statement::determine_types()
120 {
121   this->do_determine_types();
122 }
123
124 // If this is a thunk statement, return it.
125
126 Thunk_statement*
127 Statement::thunk_statement()
128 {
129   Thunk_statement* ret = this->convert<Thunk_statement, STATEMENT_GO>();
130   if (ret == NULL)
131     ret = this->convert<Thunk_statement, STATEMENT_DEFER>();
132   return ret;
133 }
134
135 // Convert a Statement to the backend representation.  This is really
136 // done by the child class.
137
138 Bstatement*
139 Statement::get_backend(Translate_context* context)
140 {
141   if (this->classification_ == STATEMENT_ERROR)
142     return context->backend()->error_statement();
143   return this->do_get_backend(context);
144 }
145
146 // Dump AST representation for a statement to a dump context.
147
148 void
149 Statement::dump_statement(Ast_dump_context* ast_dump_context) const
150 {
151   this->do_dump_statement(ast_dump_context);
152 }
153
154 // Note that this statement is erroneous.  This is called by children
155 // when they discover an error.
156
157 void
158 Statement::set_is_error()
159 {
160   this->classification_ = STATEMENT_ERROR;
161 }
162
163 // For children to call to report an error conveniently.
164
165 void
166 Statement::report_error(const char* msg)
167 {
168   error_at(this->location_, "%s", msg);
169   this->set_is_error();
170 }
171
172 // An error statement, used to avoid crashing after we report an
173 // error.
174
175 class Error_statement : public Statement
176 {
177  public:
178   Error_statement(Location location)
179     : Statement(STATEMENT_ERROR, location)
180   { }
181
182  protected:
183   int
184   do_traverse(Traverse*)
185   { return TRAVERSE_CONTINUE; }
186
187   Bstatement*
188   do_get_backend(Translate_context*)
189   { go_unreachable(); }
190
191   void
192   do_dump_statement(Ast_dump_context*) const;
193 };
194
195 // Dump the AST representation for an error statement.
196
197 void
198 Error_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
199 {
200   ast_dump_context->print_indent();
201   ast_dump_context->ostream() << "Error statement" << std::endl;
202 }
203
204 // Make an error statement.
205
206 Statement*
207 Statement::make_error_statement(Location location)
208 {
209   return new Error_statement(location);
210 }
211
212 // Class Variable_declaration_statement.
213
214 Variable_declaration_statement::Variable_declaration_statement(
215     Named_object* var)
216   : Statement(STATEMENT_VARIABLE_DECLARATION, var->var_value()->location()),
217     var_(var)
218 {
219 }
220
221 // We don't actually traverse the variable here; it was traversed
222 // while traversing the Block.
223
224 int
225 Variable_declaration_statement::do_traverse(Traverse*)
226 {
227   return TRAVERSE_CONTINUE;
228 }
229
230 // Traverse the assignments in a variable declaration.  Note that this
231 // traversal is different from the usual traversal.
232
233 bool
234 Variable_declaration_statement::do_traverse_assignments(
235     Traverse_assignments* tassign)
236 {
237   tassign->initialize_variable(this->var_);
238   return true;
239 }
240
241 // Lower the variable's initialization expression.
242
243 Statement*
244 Variable_declaration_statement::do_lower(Gogo* gogo, Named_object* function,
245                                          Block*, Statement_inserter* inserter)
246 {
247   this->var_->var_value()->lower_init_expression(gogo, function, inserter);
248   return this;
249 }
250
251 // Convert a variable declaration to the backend representation.
252
253 Bstatement*
254 Variable_declaration_statement::do_get_backend(Translate_context* context)
255 {
256   Variable* var = this->var_->var_value();
257   Bvariable* bvar = this->var_->get_backend_variable(context->gogo(),
258                                                      context->function());
259   tree init = var->get_init_tree(context->gogo(), context->function());
260   Bexpression* binit = init == NULL ? NULL : tree_to_expr(init);
261
262   if (!var->is_in_heap())
263     {
264       go_assert(binit != NULL);
265       return context->backend()->init_statement(bvar, binit);
266     }
267
268   // Something takes the address of this variable, so the value is
269   // stored in the heap.  Initialize it to newly allocated memory
270   // space, and assign the initial value to the new space.
271   Location loc = this->location();
272   Named_object* newfn = context->gogo()->lookup_global("new");
273   go_assert(newfn != NULL && newfn->is_function_declaration());
274   Expression* func = Expression::make_func_reference(newfn, NULL, loc);
275   Expression_list* params = new Expression_list();
276   params->push_back(Expression::make_type(var->type(), loc));
277   Expression* call = Expression::make_call(func, params, false, loc);
278   context->gogo()->lower_expression(context->function(), NULL, &call);
279   Temporary_statement* temp = Statement::make_temporary(NULL, call, loc);
280   Bstatement* btemp = temp->get_backend(context);
281
282   Bstatement* set = NULL;
283   if (binit != NULL)
284     {
285       Expression* e = Expression::make_temporary_reference(temp, loc);
286       e = Expression::make_unary(OPERATOR_MULT, e, loc);
287       Bexpression* be = tree_to_expr(e->get_tree(context));
288       set = context->backend()->assignment_statement(be, binit, loc);
289     }
290
291   Expression* ref = Expression::make_temporary_reference(temp, loc);
292   Bexpression* bref = tree_to_expr(ref->get_tree(context));
293   Bstatement* sinit = context->backend()->init_statement(bvar, bref);
294
295   std::vector<Bstatement*> stats;
296   stats.reserve(3);
297   stats.push_back(btemp);
298   if (set != NULL)
299     stats.push_back(set);
300   stats.push_back(sinit);
301   return context->backend()->statement_list(stats);
302 }
303
304 // Dump the AST representation for a variable declaration.
305
306 void
307 Variable_declaration_statement::do_dump_statement(
308     Ast_dump_context* ast_dump_context) const
309 {
310   ast_dump_context->print_indent();
311
312   go_assert(var_->is_variable());
313   ast_dump_context->ostream() << "var " << this->var_->name() <<  " ";
314   Variable* var = this->var_->var_value();
315   if (var->has_type())
316     {
317       ast_dump_context->dump_type(var->type());
318       ast_dump_context->ostream() << " ";
319     }
320   if (var->init() != NULL)
321     {
322       ast_dump_context->ostream() <<  "= ";
323       ast_dump_context->dump_expression(var->init());
324     }
325   ast_dump_context->ostream() << std::endl;
326 }
327
328 // Make a variable declaration.
329
330 Statement*
331 Statement::make_variable_declaration(Named_object* var)
332 {
333   return new Variable_declaration_statement(var);
334 }
335
336 // Class Temporary_statement.
337
338 // Return the type of the temporary variable.
339
340 Type*
341 Temporary_statement::type() const
342 {
343   return this->type_ != NULL ? this->type_ : this->init_->type();
344 }
345
346 // Traversal.
347
348 int
349 Temporary_statement::do_traverse(Traverse* traverse)
350 {
351   if (this->type_ != NULL
352       && this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
353     return TRAVERSE_EXIT;
354   if (this->init_ == NULL)
355     return TRAVERSE_CONTINUE;
356   else
357     return this->traverse_expression(traverse, &this->init_);
358 }
359
360 // Traverse assignments.
361
362 bool
363 Temporary_statement::do_traverse_assignments(Traverse_assignments* tassign)
364 {
365   if (this->init_ == NULL)
366     return false;
367   tassign->value(&this->init_, true, true);
368   return true;
369 }
370
371 // Determine types.
372
373 void
374 Temporary_statement::do_determine_types()
375 {
376   if (this->type_ != NULL && this->type_->is_abstract())
377     this->type_ = this->type_->make_non_abstract_type();
378
379   if (this->init_ != NULL)
380     {
381       if (this->type_ == NULL)
382         this->init_->determine_type_no_context();
383       else
384         {
385           Type_context context(this->type_, false);
386           this->init_->determine_type(&context);
387         }
388     }
389
390   if (this->type_ == NULL)
391     {
392       this->type_ = this->init_->type();
393       go_assert(!this->type_->is_abstract());
394     }
395 }
396
397 // Check types.
398
399 void
400 Temporary_statement::do_check_types(Gogo*)
401 {
402   if (this->type_ != NULL && this->init_ != NULL)
403     {
404       std::string reason;
405       bool ok;
406       if (this->are_hidden_fields_ok_)
407         ok = Type::are_assignable_hidden_ok(this->type_, this->init_->type(),
408                                             &reason);
409       else
410         ok = Type::are_assignable(this->type_, this->init_->type(), &reason);
411       if (!ok)
412         {
413           if (reason.empty())
414             error_at(this->location(), "incompatible types in assignment");
415           else
416             error_at(this->location(), "incompatible types in assignment (%s)",
417                      reason.c_str());
418           this->set_is_error();
419         }
420     }
421 }
422
423 // Convert to backend representation.
424
425 Bstatement*
426 Temporary_statement::do_get_backend(Translate_context* context)
427 {
428   go_assert(this->bvariable_ == NULL);
429
430   // FIXME: Permitting FUNCTION to be NULL here is a temporary measure
431   // until we have a better representation of the init function.
432   Named_object* function = context->function();
433   Bfunction* bfunction;
434   if (function == NULL)
435     bfunction = NULL;
436   else
437     bfunction = tree_to_function(function->func_value()->get_decl());
438
439   Btype* btype = this->type()->get_backend(context->gogo());
440
441   Bexpression* binit;
442   if (this->init_ == NULL)
443     binit = NULL;
444   else if (this->type_ == NULL)
445     binit = tree_to_expr(this->init_->get_tree(context));
446   else
447     {
448       Expression* init = Expression::make_cast(this->type_, this->init_,
449                                                this->location());
450       context->gogo()->lower_expression(context->function(), NULL, &init);
451       binit = tree_to_expr(init->get_tree(context));
452     }
453
454   Bstatement* statement;
455   this->bvariable_ =
456     context->backend()->temporary_variable(bfunction, context->bblock(),
457                                            btype, binit,
458                                            this->is_address_taken_,
459                                            this->location(), &statement);
460   return statement;
461 }
462
463 // Return the backend variable.
464
465 Bvariable*
466 Temporary_statement::get_backend_variable(Translate_context* context) const
467 {
468   if (this->bvariable_ == NULL)
469     {
470       go_assert(saw_errors());
471       return context->backend()->error_variable();
472     }
473   return this->bvariable_;
474 }
475
476 // Dump the AST represemtation for a temporary statement
477
478 void
479 Temporary_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
480 {
481   ast_dump_context->print_indent();
482   ast_dump_context->dump_temp_variable_name(this);
483   if (this->type_ != NULL)
484     {
485       ast_dump_context->ostream() << " ";
486       ast_dump_context->dump_type(this->type_);
487     }
488   if (this->init_ != NULL)
489     {
490       ast_dump_context->ostream() << " = ";
491       ast_dump_context->dump_expression(this->init_);
492     }
493   ast_dump_context->ostream() << std::endl;
494 }
495
496 // Make and initialize a temporary variable in BLOCK.
497
498 Temporary_statement*
499 Statement::make_temporary(Type* type, Expression* init,
500                           Location location)
501 {
502   return new Temporary_statement(type, init, location);
503 }
504
505 // An assignment statement.
506
507 class Assignment_statement : public Statement
508 {
509  public:
510   Assignment_statement(Expression* lhs, Expression* rhs,
511                        Location location)
512     : Statement(STATEMENT_ASSIGNMENT, location),
513       lhs_(lhs), rhs_(rhs), are_hidden_fields_ok_(false)
514   { }
515
516   // Note that it is OK for this assignment statement to set hidden
517   // fields.
518   void
519   set_hidden_fields_are_ok()
520   { this->are_hidden_fields_ok_ = true; }
521
522  protected:
523   int
524   do_traverse(Traverse* traverse);
525
526   bool
527   do_traverse_assignments(Traverse_assignments*);
528
529   void
530   do_determine_types();
531
532   void
533   do_check_types(Gogo*);
534
535   Bstatement*
536   do_get_backend(Translate_context*);
537
538   void
539   do_dump_statement(Ast_dump_context*) const;
540
541  private:
542   // Left hand side--the lvalue.
543   Expression* lhs_;
544   // Right hand side--the rvalue.
545   Expression* rhs_;
546   // True if this statement may set hidden fields in the assignment
547   // statement.  This is used for generated method stubs.
548   bool are_hidden_fields_ok_;
549 };
550
551 // Traversal.
552
553 int
554 Assignment_statement::do_traverse(Traverse* traverse)
555 {
556   if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
557     return TRAVERSE_EXIT;
558   return this->traverse_expression(traverse, &this->rhs_);
559 }
560
561 bool
562 Assignment_statement::do_traverse_assignments(Traverse_assignments* tassign)
563 {
564   tassign->assignment(&this->lhs_, &this->rhs_);
565   return true;
566 }
567
568 // Set types for the assignment.
569
570 void
571 Assignment_statement::do_determine_types()
572 {
573   this->lhs_->determine_type_no_context();
574   Type_context context(this->lhs_->type(), false);
575   this->rhs_->determine_type(&context);
576 }
577
578 // Check types for an assignment.
579
580 void
581 Assignment_statement::do_check_types(Gogo*)
582 {
583   // The left hand side must be either addressable, a map index
584   // expression, or the blank identifier.
585   if (!this->lhs_->is_addressable()
586       && this->lhs_->map_index_expression() == NULL
587       && !this->lhs_->is_sink_expression())
588     {
589       if (!this->lhs_->type()->is_error())
590         this->report_error(_("invalid left hand side of assignment"));
591       return;
592     }
593
594   Type* lhs_type = this->lhs_->type();
595   Type* rhs_type = this->rhs_->type();
596   std::string reason;
597   bool ok;
598   if (this->are_hidden_fields_ok_)
599     ok = Type::are_assignable_hidden_ok(lhs_type, rhs_type, &reason);
600   else
601     ok = Type::are_assignable(lhs_type, rhs_type, &reason);
602   if (!ok)
603     {
604       if (reason.empty())
605         error_at(this->location(), "incompatible types in assignment");
606       else
607         error_at(this->location(), "incompatible types in assignment (%s)",
608                  reason.c_str());
609       this->set_is_error();
610     }
611
612   if (lhs_type->is_error() || rhs_type->is_error())
613     this->set_is_error();
614 }
615
616 // Convert an assignment statement to the backend representation.
617
618 Bstatement*
619 Assignment_statement::do_get_backend(Translate_context* context)
620 {
621   tree rhs_tree = this->rhs_->get_tree(context);
622   if (this->lhs_->is_sink_expression())
623     return context->backend()->expression_statement(tree_to_expr(rhs_tree));
624   tree lhs_tree = this->lhs_->get_tree(context);
625   rhs_tree = Expression::convert_for_assignment(context, this->lhs_->type(),
626                                                 this->rhs_->type(), rhs_tree,
627                                                 this->location());
628   return context->backend()->assignment_statement(tree_to_expr(lhs_tree),
629                                                   tree_to_expr(rhs_tree),
630                                                   this->location());
631 }
632
633 // Dump the AST representation for an assignment statement.
634
635 void
636 Assignment_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
637     const
638 {
639   ast_dump_context->print_indent();
640   ast_dump_context->dump_expression(this->lhs_);
641   ast_dump_context->ostream() << " = " ;
642   ast_dump_context->dump_expression(this->rhs_);
643   ast_dump_context->ostream() << std::endl;
644 }
645
646 // Make an assignment statement.
647
648 Statement*
649 Statement::make_assignment(Expression* lhs, Expression* rhs,
650                            Location location)
651 {
652   return new Assignment_statement(lhs, rhs, location);
653 }
654
655 // The Move_subexpressions class is used to move all top-level
656 // subexpressions of an expression.  This is used for things like
657 // index expressions in which we must evaluate the index value before
658 // it can be changed by a multiple assignment.
659
660 class Move_subexpressions : public Traverse
661 {
662  public:
663   Move_subexpressions(int skip, Block* block)
664     : Traverse(traverse_expressions),
665       skip_(skip), block_(block)
666   { }
667
668  protected:
669   int
670   expression(Expression**);
671
672  private:
673   // The number of subexpressions to skip moving.  This is used to
674   // avoid moving the array itself, as we only need to move the index.
675   int skip_;
676   // The block where new temporary variables should be added.
677   Block* block_;
678 };
679
680 int
681 Move_subexpressions::expression(Expression** pexpr)
682 {
683   if (this->skip_ > 0)
684     --this->skip_;
685   else if ((*pexpr)->temporary_reference_expression() == NULL)
686     {
687       Location loc = (*pexpr)->location();
688       Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
689       this->block_->add_statement(temp);
690       *pexpr = Expression::make_temporary_reference(temp, loc);
691     }
692   // We only need to move top-level subexpressions.
693   return TRAVERSE_SKIP_COMPONENTS;
694 }
695
696 // The Move_ordered_evals class is used to find any subexpressions of
697 // an expression that have an evaluation order dependency.  It creates
698 // temporary variables to hold them.
699
700 class Move_ordered_evals : public Traverse
701 {
702  public:
703   Move_ordered_evals(Block* block)
704     : Traverse(traverse_expressions),
705       block_(block)
706   { }
707
708  protected:
709   int
710   expression(Expression**);
711
712  private:
713   // The block where new temporary variables should be added.
714   Block* block_;
715 };
716
717 int
718 Move_ordered_evals::expression(Expression** pexpr)
719 {
720   // We have to look at subexpressions first.
721   if ((*pexpr)->traverse_subexpressions(this) == TRAVERSE_EXIT)
722     return TRAVERSE_EXIT;
723
724   int i;
725   if ((*pexpr)->must_eval_subexpressions_in_order(&i))
726     {
727       Move_subexpressions ms(i, this->block_);
728       if ((*pexpr)->traverse_subexpressions(&ms) == TRAVERSE_EXIT)
729         return TRAVERSE_EXIT;
730     }
731
732   if ((*pexpr)->must_eval_in_order())
733     {
734       Location loc = (*pexpr)->location();
735       Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
736       this->block_->add_statement(temp);
737       *pexpr = Expression::make_temporary_reference(temp, loc);
738     }
739   return TRAVERSE_SKIP_COMPONENTS;
740 }
741
742 // An assignment operation statement.
743
744 class Assignment_operation_statement : public Statement
745 {
746  public:
747   Assignment_operation_statement(Operator op, Expression* lhs, Expression* rhs,
748                                  Location location)
749     : Statement(STATEMENT_ASSIGNMENT_OPERATION, location),
750       op_(op), lhs_(lhs), rhs_(rhs)
751   { }
752
753  protected:
754   int
755   do_traverse(Traverse*);
756
757   bool
758   do_traverse_assignments(Traverse_assignments*)
759   { go_unreachable(); }
760
761   Statement*
762   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
763
764   Bstatement*
765   do_get_backend(Translate_context*)
766   { go_unreachable(); }
767
768   void
769   do_dump_statement(Ast_dump_context*) const;
770
771  private:
772   // The operator (OPERATOR_PLUSEQ, etc.).
773   Operator op_;
774   // Left hand side.
775   Expression* lhs_;
776   // Right hand side.
777   Expression* rhs_;
778 };
779
780 // Traversal.
781
782 int
783 Assignment_operation_statement::do_traverse(Traverse* traverse)
784 {
785   if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
786     return TRAVERSE_EXIT;
787   return this->traverse_expression(traverse, &this->rhs_);
788 }
789
790 // Lower an assignment operation statement to a regular assignment
791 // statement.
792
793 Statement*
794 Assignment_operation_statement::do_lower(Gogo*, Named_object*,
795                                          Block* enclosing, Statement_inserter*)
796 {
797   Location loc = this->location();
798
799   // We have to evaluate the left hand side expression only once.  We
800   // do this by moving out any expression with side effects.
801   Block* b = new Block(enclosing, loc);
802   Move_ordered_evals moe(b);
803   this->lhs_->traverse_subexpressions(&moe);
804
805   Expression* lval = this->lhs_->copy();
806
807   Operator op;
808   switch (this->op_)
809     {
810     case OPERATOR_PLUSEQ:
811       op = OPERATOR_PLUS;
812       break;
813     case OPERATOR_MINUSEQ:
814       op = OPERATOR_MINUS;
815       break;
816     case OPERATOR_OREQ:
817       op = OPERATOR_OR;
818       break;
819     case OPERATOR_XOREQ:
820       op = OPERATOR_XOR;
821       break;
822     case OPERATOR_MULTEQ:
823       op = OPERATOR_MULT;
824       break;
825     case OPERATOR_DIVEQ:
826       op = OPERATOR_DIV;
827       break;
828     case OPERATOR_MODEQ:
829       op = OPERATOR_MOD;
830       break;
831     case OPERATOR_LSHIFTEQ:
832       op = OPERATOR_LSHIFT;
833       break;
834     case OPERATOR_RSHIFTEQ:
835       op = OPERATOR_RSHIFT;
836       break;
837     case OPERATOR_ANDEQ:
838       op = OPERATOR_AND;
839       break;
840     case OPERATOR_BITCLEAREQ:
841       op = OPERATOR_BITCLEAR;
842       break;
843     default:
844       go_unreachable();
845     }
846
847   Expression* binop = Expression::make_binary(op, lval, this->rhs_, loc);
848   Statement* s = Statement::make_assignment(this->lhs_, binop, loc);
849   if (b->statements()->empty())
850     {
851       delete b;
852       return s;
853     }
854   else
855     {
856       b->add_statement(s);
857       return Statement::make_block_statement(b, loc);
858     }
859 }
860
861 // Dump the AST representation for an assignment operation statement
862
863 void
864 Assignment_operation_statement::do_dump_statement(
865     Ast_dump_context* ast_dump_context) const
866 {
867   ast_dump_context->print_indent();
868   ast_dump_context->dump_expression(this->lhs_);
869   ast_dump_context->dump_operator(this->op_);
870   ast_dump_context->dump_expression(this->rhs_);
871   ast_dump_context->ostream() << std::endl;
872 }
873
874 // Make an assignment operation statement.
875
876 Statement*
877 Statement::make_assignment_operation(Operator op, Expression* lhs,
878                                      Expression* rhs, Location location)
879 {
880   return new Assignment_operation_statement(op, lhs, rhs, location);
881 }
882
883 // A tuple assignment statement.  This differs from an assignment
884 // statement in that the right-hand-side expressions are evaluated in
885 // parallel.
886
887 class Tuple_assignment_statement : public Statement
888 {
889  public:
890   Tuple_assignment_statement(Expression_list* lhs, Expression_list* rhs,
891                              Location location)
892     : Statement(STATEMENT_TUPLE_ASSIGNMENT, location),
893       lhs_(lhs), rhs_(rhs), are_hidden_fields_ok_(false)
894   { }
895
896   // Note that it is OK for this assignment statement to set hidden
897   // fields.
898   void
899   set_hidden_fields_are_ok()
900   { this->are_hidden_fields_ok_ = true; }
901
902  protected:
903   int
904   do_traverse(Traverse* traverse);
905
906   bool
907   do_traverse_assignments(Traverse_assignments*)
908   { go_unreachable(); }
909
910   Statement*
911   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
912
913   Bstatement*
914   do_get_backend(Translate_context*)
915   { go_unreachable(); }
916
917   void
918   do_dump_statement(Ast_dump_context*) const;
919
920  private:
921   // Left hand side--a list of lvalues.
922   Expression_list* lhs_;
923   // Right hand side--a list of rvalues.
924   Expression_list* rhs_;
925   // True if this statement may set hidden fields in the assignment
926   // statement.  This is used for generated method stubs.
927   bool are_hidden_fields_ok_;
928 };
929
930 // Traversal.
931
932 int
933 Tuple_assignment_statement::do_traverse(Traverse* traverse)
934 {
935   if (this->traverse_expression_list(traverse, this->lhs_) == TRAVERSE_EXIT)
936     return TRAVERSE_EXIT;
937   return this->traverse_expression_list(traverse, this->rhs_);
938 }
939
940 // Lower a tuple assignment.  We use temporary variables to split it
941 // up into a set of single assignments.
942
943 Statement*
944 Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
945                                      Statement_inserter*)
946 {
947   Location loc = this->location();
948
949   Block* b = new Block(enclosing, loc);
950
951   // First move out any subexpressions on the left hand side.  The
952   // right hand side will be evaluated in the required order anyhow.
953   Move_ordered_evals moe(b);
954   for (Expression_list::iterator plhs = this->lhs_->begin();
955        plhs != this->lhs_->end();
956        ++plhs)
957     Expression::traverse(&*plhs, &moe);
958
959   std::vector<Temporary_statement*> temps;
960   temps.reserve(this->lhs_->size());
961
962   Expression_list::const_iterator prhs = this->rhs_->begin();
963   for (Expression_list::const_iterator plhs = this->lhs_->begin();
964        plhs != this->lhs_->end();
965        ++plhs, ++prhs)
966     {
967       go_assert(prhs != this->rhs_->end());
968
969       if ((*plhs)->is_error_expression()
970           || (*plhs)->type()->is_error()
971           || (*prhs)->is_error_expression()
972           || (*prhs)->type()->is_error())
973         continue;
974
975       if ((*plhs)->is_sink_expression())
976         {
977           b->add_statement(Statement::make_statement(*prhs, true));
978           continue;
979         }
980
981       Temporary_statement* temp = Statement::make_temporary((*plhs)->type(),
982                                                             *prhs, loc);
983       if (this->are_hidden_fields_ok_)
984         temp->set_hidden_fields_are_ok();
985       b->add_statement(temp);
986       temps.push_back(temp);
987
988     }
989   go_assert(prhs == this->rhs_->end());
990
991   prhs = this->rhs_->begin();
992   std::vector<Temporary_statement*>::const_iterator ptemp = temps.begin();
993   for (Expression_list::const_iterator plhs = this->lhs_->begin();
994        plhs != this->lhs_->end();
995        ++plhs, ++prhs)
996     {
997       if ((*plhs)->is_error_expression()
998           || (*plhs)->type()->is_error()
999           || (*prhs)->is_error_expression()
1000           || (*prhs)->type()->is_error())
1001         continue;
1002
1003       if ((*plhs)->is_sink_expression())
1004         continue;
1005
1006       Expression* ref = Expression::make_temporary_reference(*ptemp, loc);
1007       Statement* s = Statement::make_assignment(*plhs, ref, loc);
1008       if (this->are_hidden_fields_ok_)
1009         {
1010           Assignment_statement* as = static_cast<Assignment_statement*>(s);
1011           as->set_hidden_fields_are_ok();
1012         }
1013       b->add_statement(s);
1014       ++ptemp;
1015     }
1016   go_assert(ptemp == temps.end() || saw_errors());
1017
1018   return Statement::make_block_statement(b, loc);
1019 }
1020
1021 // Dump the AST representation for a tuple assignment statement.
1022
1023 void
1024 Tuple_assignment_statement::do_dump_statement(
1025     Ast_dump_context* ast_dump_context) const
1026 {
1027   ast_dump_context->print_indent();
1028   ast_dump_context->dump_expression_list(this->lhs_);
1029   ast_dump_context->ostream() << " = ";
1030   ast_dump_context->dump_expression_list(this->rhs_);
1031   ast_dump_context->ostream()  << std::endl;
1032 }
1033
1034 // Make a tuple assignment statement.
1035
1036 Statement*
1037 Statement::make_tuple_assignment(Expression_list* lhs, Expression_list* rhs,
1038                                  Location location)
1039 {
1040   return new Tuple_assignment_statement(lhs, rhs, location);
1041 }
1042
1043 // A tuple assignment from a map index expression.
1044 //   v, ok = m[k]
1045
1046 class Tuple_map_assignment_statement : public Statement
1047 {
1048 public:
1049   Tuple_map_assignment_statement(Expression* val, Expression* present,
1050                                  Expression* map_index,
1051                                  Location location)
1052     : Statement(STATEMENT_TUPLE_MAP_ASSIGNMENT, location),
1053       val_(val), present_(present), map_index_(map_index)
1054   { }
1055
1056  protected:
1057   int
1058   do_traverse(Traverse* traverse);
1059
1060   bool
1061   do_traverse_assignments(Traverse_assignments*)
1062   { go_unreachable(); }
1063
1064   Statement*
1065   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1066
1067   Bstatement*
1068   do_get_backend(Translate_context*)
1069   { go_unreachable(); }
1070
1071   void
1072   do_dump_statement(Ast_dump_context*) const;
1073
1074  private:
1075   // Lvalue which receives the value from the map.
1076   Expression* val_;
1077   // Lvalue which receives whether the key value was present.
1078   Expression* present_;
1079   // The map index expression.
1080   Expression* map_index_;
1081 };
1082
1083 // Traversal.
1084
1085 int
1086 Tuple_map_assignment_statement::do_traverse(Traverse* traverse)
1087 {
1088   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
1089       || this->traverse_expression(traverse, &this->present_) == TRAVERSE_EXIT)
1090     return TRAVERSE_EXIT;
1091   return this->traverse_expression(traverse, &this->map_index_);
1092 }
1093
1094 // Lower a tuple map assignment.
1095
1096 Statement*
1097 Tuple_map_assignment_statement::do_lower(Gogo*, Named_object*,
1098                                          Block* enclosing, Statement_inserter*)
1099 {
1100   Location loc = this->location();
1101
1102   Map_index_expression* map_index = this->map_index_->map_index_expression();
1103   if (map_index == NULL)
1104     {
1105       this->report_error(_("expected map index on right hand side"));
1106       return Statement::make_error_statement(loc);
1107     }
1108   Map_type* map_type = map_index->get_map_type();
1109   if (map_type == NULL)
1110     return Statement::make_error_statement(loc);
1111
1112   Block* b = new Block(enclosing, loc);
1113
1114   // Move out any subexpressions to make sure that functions are
1115   // called in the required order.
1116   Move_ordered_evals moe(b);
1117   this->val_->traverse_subexpressions(&moe);
1118   this->present_->traverse_subexpressions(&moe);
1119
1120   // Copy the key value into a temporary so that we can take its
1121   // address without pushing the value onto the heap.
1122
1123   // var key_temp KEY_TYPE = MAP_INDEX
1124   Temporary_statement* key_temp =
1125     Statement::make_temporary(map_type->key_type(), map_index->index(), loc);
1126   b->add_statement(key_temp);
1127
1128   // var val_temp VAL_TYPE
1129   Temporary_statement* val_temp =
1130     Statement::make_temporary(map_type->val_type(), NULL, loc);
1131   b->add_statement(val_temp);
1132
1133   // var present_temp bool
1134   Temporary_statement* present_temp =
1135     Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
1136   b->add_statement(present_temp);
1137
1138   // present_temp = mapaccess2(DESCRIPTOR, MAP, &key_temp, &val_temp)
1139   Expression* a1 = Expression::make_type_descriptor(map_type, loc);
1140   Expression* a2 = map_index->map();
1141   Temporary_reference_expression* ref =
1142     Expression::make_temporary_reference(key_temp, loc);
1143   Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc);
1144   ref = Expression::make_temporary_reference(val_temp, loc);
1145   Expression* a4 = Expression::make_unary(OPERATOR_AND, ref, loc);
1146   Expression* call = Runtime::make_call(Runtime::MAPACCESS2, loc, 4,
1147                                         a1, a2, a3, a4);
1148
1149   ref = Expression::make_temporary_reference(present_temp, loc);
1150   ref->set_is_lvalue();
1151   Statement* s = Statement::make_assignment(ref, call, loc);
1152   b->add_statement(s);
1153
1154   // val = val_temp
1155   ref = Expression::make_temporary_reference(val_temp, loc);
1156   s = Statement::make_assignment(this->val_, ref, loc);
1157   b->add_statement(s);
1158
1159   // present = present_temp
1160   ref = Expression::make_temporary_reference(present_temp, loc);
1161   s = Statement::make_assignment(this->present_, ref, loc);
1162   b->add_statement(s);
1163
1164   return Statement::make_block_statement(b, loc);
1165 }
1166
1167 // Dump the AST representation for a tuple map assignment statement.
1168
1169 void
1170 Tuple_map_assignment_statement::do_dump_statement(
1171     Ast_dump_context* ast_dump_context) const
1172 {
1173   ast_dump_context->print_indent();
1174   ast_dump_context->dump_expression(this->val_);
1175   ast_dump_context->ostream() << ", ";
1176   ast_dump_context->dump_expression(this->present_);
1177   ast_dump_context->ostream() << " = ";
1178   ast_dump_context->dump_expression(this->map_index_);
1179   ast_dump_context->ostream() << std::endl;
1180 }
1181
1182 // Make a map assignment statement which returns a pair of values.
1183
1184 Statement*
1185 Statement::make_tuple_map_assignment(Expression* val, Expression* present,
1186                                      Expression* map_index,
1187                                      Location location)
1188 {
1189   return new Tuple_map_assignment_statement(val, present, map_index, location);
1190 }
1191
1192 // Assign a pair of entries to a map.
1193 //   m[k] = v, p
1194
1195 class Map_assignment_statement : public Statement
1196 {
1197  public:
1198   Map_assignment_statement(Expression* map_index,
1199                            Expression* val, Expression* should_set,
1200                            Location location)
1201     : Statement(STATEMENT_MAP_ASSIGNMENT, location),
1202       map_index_(map_index), val_(val), should_set_(should_set)
1203   { }
1204
1205  protected:
1206   int
1207   do_traverse(Traverse* traverse);
1208
1209   bool
1210   do_traverse_assignments(Traverse_assignments*)
1211   { go_unreachable(); }
1212
1213   Statement*
1214   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1215
1216   Bstatement*
1217   do_get_backend(Translate_context*)
1218   { go_unreachable(); }
1219
1220   void
1221   do_dump_statement(Ast_dump_context*) const;
1222
1223  private:
1224   // A reference to the map index which should be set or deleted.
1225   Expression* map_index_;
1226   // The value to add to the map.
1227   Expression* val_;
1228   // Whether or not to add the value.
1229   Expression* should_set_;
1230 };
1231
1232 // Traverse a map assignment.
1233
1234 int
1235 Map_assignment_statement::do_traverse(Traverse* traverse)
1236 {
1237   if (this->traverse_expression(traverse, &this->map_index_) == TRAVERSE_EXIT
1238       || this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
1239     return TRAVERSE_EXIT;
1240   return this->traverse_expression(traverse, &this->should_set_);
1241 }
1242
1243 // Lower a map assignment to a function call.
1244
1245 Statement*
1246 Map_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
1247                                    Statement_inserter*)
1248 {
1249   Location loc = this->location();
1250
1251   Map_index_expression* map_index = this->map_index_->map_index_expression();
1252   if (map_index == NULL)
1253     {
1254       this->report_error(_("expected map index on left hand side"));
1255       return Statement::make_error_statement(loc);
1256     }
1257   Map_type* map_type = map_index->get_map_type();
1258   if (map_type == NULL)
1259     return Statement::make_error_statement(loc);
1260
1261   Block* b = new Block(enclosing, loc);
1262
1263   // Evaluate the map first to get order of evaluation right.
1264   // map_temp := m // we are evaluating m[k] = v, p
1265   Temporary_statement* map_temp = Statement::make_temporary(map_type,
1266                                                             map_index->map(),
1267                                                             loc);
1268   b->add_statement(map_temp);
1269
1270   // var key_temp MAP_KEY_TYPE = k
1271   Temporary_statement* key_temp =
1272     Statement::make_temporary(map_type->key_type(), map_index->index(), loc);
1273   b->add_statement(key_temp);
1274
1275   // var val_temp MAP_VAL_TYPE = v
1276   Temporary_statement* val_temp =
1277     Statement::make_temporary(map_type->val_type(), this->val_, loc);
1278   b->add_statement(val_temp);
1279
1280   // var insert_temp bool = p
1281   Temporary_statement* insert_temp =
1282     Statement::make_temporary(Type::lookup_bool_type(), this->should_set_,
1283                               loc);
1284   b->add_statement(insert_temp);
1285
1286   // mapassign2(map_temp, &key_temp, &val_temp, p)
1287   Expression* p1 = Expression::make_temporary_reference(map_temp, loc);
1288   Expression* ref = Expression::make_temporary_reference(key_temp, loc);
1289   Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
1290   ref = Expression::make_temporary_reference(val_temp, loc);
1291   Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
1292   Expression* p4 = Expression::make_temporary_reference(insert_temp, loc);
1293   Expression* call = Runtime::make_call(Runtime::MAPASSIGN2, loc, 4,
1294                                         p1, p2, p3, p4);
1295   Statement* s = Statement::make_statement(call, true);
1296   b->add_statement(s);
1297
1298   return Statement::make_block_statement(b, loc);
1299 }
1300
1301 // Dump the AST representation for a map assignment statement.
1302
1303 void
1304 Map_assignment_statement::do_dump_statement(
1305     Ast_dump_context* ast_dump_context) const
1306 {
1307   ast_dump_context->print_indent();
1308   ast_dump_context->dump_expression(this->map_index_);
1309   ast_dump_context->ostream() << " = ";
1310   ast_dump_context->dump_expression(this->val_);
1311   ast_dump_context->ostream() << ", ";
1312   ast_dump_context->dump_expression(this->should_set_);
1313   ast_dump_context->ostream() << std::endl;
1314 }
1315
1316 // Make a statement which assigns a pair of entries to a map.
1317
1318 Statement*
1319 Statement::make_map_assignment(Expression* map_index,
1320                                Expression* val, Expression* should_set,
1321                                Location location)
1322 {
1323   return new Map_assignment_statement(map_index, val, should_set, location);
1324 }
1325
1326 // A tuple assignment from a receive statement.
1327
1328 class Tuple_receive_assignment_statement : public Statement
1329 {
1330  public:
1331   Tuple_receive_assignment_statement(Expression* val, Expression* closed,
1332                                      Expression* channel, Location location)
1333     : Statement(STATEMENT_TUPLE_RECEIVE_ASSIGNMENT, location),
1334       val_(val), closed_(closed), channel_(channel)
1335   { }
1336
1337  protected:
1338   int
1339   do_traverse(Traverse* traverse);
1340
1341   bool
1342   do_traverse_assignments(Traverse_assignments*)
1343   { go_unreachable(); }
1344
1345   Statement*
1346   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1347
1348   Bstatement*
1349   do_get_backend(Translate_context*)
1350   { go_unreachable(); }
1351
1352   void
1353   do_dump_statement(Ast_dump_context*) const;
1354
1355  private:
1356   // Lvalue which receives the value from the channel.
1357   Expression* val_;
1358   // Lvalue which receives whether the channel is closed.
1359   Expression* closed_;
1360   // The channel on which we receive the value.
1361   Expression* channel_;
1362 };
1363
1364 // Traversal.
1365
1366 int
1367 Tuple_receive_assignment_statement::do_traverse(Traverse* traverse)
1368 {
1369   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
1370       || this->traverse_expression(traverse, &this->closed_) == TRAVERSE_EXIT)
1371     return TRAVERSE_EXIT;
1372   return this->traverse_expression(traverse, &this->channel_);
1373 }
1374
1375 // Lower to a function call.
1376
1377 Statement*
1378 Tuple_receive_assignment_statement::do_lower(Gogo*, Named_object*,
1379                                              Block* enclosing,
1380                                              Statement_inserter*)
1381 {
1382   Location loc = this->location();
1383
1384   Channel_type* channel_type = this->channel_->type()->channel_type();
1385   if (channel_type == NULL)
1386     {
1387       this->report_error(_("expected channel"));
1388       return Statement::make_error_statement(loc);
1389     }
1390   if (!channel_type->may_receive())
1391     {
1392       this->report_error(_("invalid receive on send-only channel"));
1393       return Statement::make_error_statement(loc);
1394     }
1395
1396   Block* b = new Block(enclosing, loc);
1397
1398   // Make sure that any subexpressions on the left hand side are
1399   // evaluated in the right order.
1400   Move_ordered_evals moe(b);
1401   this->val_->traverse_subexpressions(&moe);
1402   this->closed_->traverse_subexpressions(&moe);
1403
1404   // var val_temp ELEMENT_TYPE
1405   Temporary_statement* val_temp =
1406     Statement::make_temporary(channel_type->element_type(), NULL, loc);
1407   b->add_statement(val_temp);
1408
1409   // var closed_temp bool
1410   Temporary_statement* closed_temp =
1411     Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
1412   b->add_statement(closed_temp);
1413
1414   // closed_temp = chanrecv2(type, channel, &val_temp)
1415   Expression* td = Expression::make_type_descriptor(this->channel_->type(),
1416                                                     loc);
1417   Temporary_reference_expression* ref =
1418     Expression::make_temporary_reference(val_temp, loc);
1419   Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
1420   Expression* call = Runtime::make_call(Runtime::CHANRECV2,
1421                                         loc, 3, td, this->channel_, p2);
1422   ref = Expression::make_temporary_reference(closed_temp, loc);
1423   ref->set_is_lvalue();
1424   Statement* s = Statement::make_assignment(ref, call, loc);
1425   b->add_statement(s);
1426
1427   // val = val_temp
1428   ref = Expression::make_temporary_reference(val_temp, loc);
1429   s = Statement::make_assignment(this->val_, ref, loc);
1430   b->add_statement(s);
1431
1432   // closed = closed_temp
1433   ref = Expression::make_temporary_reference(closed_temp, loc);
1434   s = Statement::make_assignment(this->closed_, ref, loc);
1435   b->add_statement(s);
1436
1437   return Statement::make_block_statement(b, loc);
1438 }
1439
1440 // Dump the AST representation for a tuple receive statement.
1441
1442 void
1443 Tuple_receive_assignment_statement::do_dump_statement(
1444     Ast_dump_context* ast_dump_context) const
1445 {
1446   ast_dump_context->print_indent();
1447   ast_dump_context->dump_expression(this->val_);
1448   ast_dump_context->ostream() << ", ";
1449   ast_dump_context->dump_expression(this->closed_);
1450   ast_dump_context->ostream() << " <- ";
1451   ast_dump_context->dump_expression(this->channel_);
1452   ast_dump_context->ostream() << std::endl;
1453 }
1454
1455 // Make a nonblocking receive statement.
1456
1457 Statement*
1458 Statement::make_tuple_receive_assignment(Expression* val, Expression* closed,
1459                                          Expression* channel,
1460                                          Location location)
1461 {
1462   return new Tuple_receive_assignment_statement(val, closed, channel,
1463                                                 location);
1464 }
1465
1466 // An assignment to a pair of values from a type guard.  This is a
1467 // conditional type guard.  v, ok = i.(type).
1468
1469 class Tuple_type_guard_assignment_statement : public Statement
1470 {
1471  public:
1472   Tuple_type_guard_assignment_statement(Expression* val, Expression* ok,
1473                                         Expression* expr, Type* type,
1474                                         Location location)
1475     : Statement(STATEMENT_TUPLE_TYPE_GUARD_ASSIGNMENT, location),
1476       val_(val), ok_(ok), expr_(expr), type_(type)
1477   { }
1478
1479  protected:
1480   int
1481   do_traverse(Traverse*);
1482
1483   bool
1484   do_traverse_assignments(Traverse_assignments*)
1485   { go_unreachable(); }
1486
1487   Statement*
1488   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1489
1490   Bstatement*
1491   do_get_backend(Translate_context*)
1492   { go_unreachable(); }
1493
1494   void
1495   do_dump_statement(Ast_dump_context*) const;
1496
1497  private:
1498   Call_expression*
1499   lower_to_type(Runtime::Function);
1500
1501   void
1502   lower_to_object_type(Block*, Runtime::Function);
1503
1504   // The variable which recieves the converted value.
1505   Expression* val_;
1506   // The variable which receives the indication of success.
1507   Expression* ok_;
1508   // The expression being converted.
1509   Expression* expr_;
1510   // The type to which the expression is being converted.
1511   Type* type_;
1512 };
1513
1514 // Traverse a type guard tuple assignment.
1515
1516 int
1517 Tuple_type_guard_assignment_statement::do_traverse(Traverse* traverse)
1518 {
1519   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
1520       || this->traverse_expression(traverse, &this->ok_) == TRAVERSE_EXIT
1521       || this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
1522     return TRAVERSE_EXIT;
1523   return this->traverse_expression(traverse, &this->expr_);
1524 }
1525
1526 // Lower to a function call.
1527
1528 Statement*
1529 Tuple_type_guard_assignment_statement::do_lower(Gogo*, Named_object*,
1530                                                 Block* enclosing,
1531                                                 Statement_inserter*)
1532 {
1533   Location loc = this->location();
1534
1535   Type* expr_type = this->expr_->type();
1536   if (expr_type->interface_type() == NULL)
1537     {
1538       if (!expr_type->is_error() && !this->type_->is_error())
1539         this->report_error(_("type assertion only valid for interface types"));
1540       return Statement::make_error_statement(loc);
1541     }
1542
1543   Block* b = new Block(enclosing, loc);
1544
1545   // Make sure that any subexpressions on the left hand side are
1546   // evaluated in the right order.
1547   Move_ordered_evals moe(b);
1548   this->val_->traverse_subexpressions(&moe);
1549   this->ok_->traverse_subexpressions(&moe);
1550
1551   bool expr_is_empty = expr_type->interface_type()->is_empty();
1552   Call_expression* call;
1553   if (this->type_->interface_type() != NULL)
1554     {
1555       if (this->type_->interface_type()->is_empty())
1556         call = Runtime::make_call((expr_is_empty
1557                                    ? Runtime::IFACEE2E2
1558                                    : Runtime::IFACEI2E2),
1559                                   loc, 1, this->expr_);
1560       else
1561         call = this->lower_to_type(expr_is_empty
1562                                    ? Runtime::IFACEE2I2
1563                                    : Runtime::IFACEI2I2);
1564     }
1565   else if (this->type_->points_to() != NULL)
1566     call = this->lower_to_type(expr_is_empty
1567                                ? Runtime::IFACEE2T2P
1568                                : Runtime::IFACEI2T2P);
1569   else
1570     {
1571       this->lower_to_object_type(b,
1572                                  (expr_is_empty
1573                                   ? Runtime::IFACEE2T2
1574                                   : Runtime::IFACEI2T2));
1575       call = NULL;
1576     }
1577
1578   if (call != NULL)
1579     {
1580       Expression* res = Expression::make_call_result(call, 0);
1581       res = Expression::make_unsafe_cast(this->type_, res, loc);
1582       Statement* s = Statement::make_assignment(this->val_, res, loc);
1583       b->add_statement(s);
1584
1585       res = Expression::make_call_result(call, 1);
1586       s = Statement::make_assignment(this->ok_, res, loc);
1587       b->add_statement(s);
1588     }
1589
1590   return Statement::make_block_statement(b, loc);
1591 }
1592
1593 // Lower a conversion to a non-empty interface type or a pointer type.
1594
1595 Call_expression*
1596 Tuple_type_guard_assignment_statement::lower_to_type(Runtime::Function code)
1597 {
1598   Location loc = this->location();
1599   return Runtime::make_call(code, loc, 2,
1600                             Expression::make_type_descriptor(this->type_, loc),
1601                             this->expr_);
1602 }
1603
1604 // Lower a conversion to a non-interface non-pointer type.
1605
1606 void
1607 Tuple_type_guard_assignment_statement::lower_to_object_type(
1608     Block* b,
1609     Runtime::Function code)
1610 {
1611   Location loc = this->location();
1612
1613   // var val_temp TYPE
1614   Temporary_statement* val_temp = Statement::make_temporary(this->type_,
1615                                                             NULL, loc);
1616   b->add_statement(val_temp);
1617
1618   // ok = CODE(type_descriptor, expr, &val_temp)
1619   Expression* p1 = Expression::make_type_descriptor(this->type_, loc);
1620   Expression* ref = Expression::make_temporary_reference(val_temp, loc);
1621   Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
1622   Expression* call = Runtime::make_call(code, loc, 3, p1, this->expr_, p3);
1623   Statement* s = Statement::make_assignment(this->ok_, call, loc);
1624   b->add_statement(s);
1625
1626   // val = val_temp
1627   ref = Expression::make_temporary_reference(val_temp, loc);
1628   s = Statement::make_assignment(this->val_, ref, loc);
1629   b->add_statement(s);
1630 }
1631
1632 // Dump the AST representation for a tuple type guard statement.
1633
1634 void
1635 Tuple_type_guard_assignment_statement::do_dump_statement(
1636     Ast_dump_context* ast_dump_context) const
1637 {
1638   ast_dump_context->print_indent();
1639   ast_dump_context->dump_expression(this->val_);
1640   ast_dump_context->ostream() << ", ";
1641   ast_dump_context->dump_expression(this->ok_);
1642   ast_dump_context->ostream() << " = ";
1643   ast_dump_context->dump_expression(this->expr_);
1644   ast_dump_context->ostream() << " . ";
1645   ast_dump_context->dump_type(this->type_);
1646   ast_dump_context->ostream()  << std::endl;
1647 }
1648
1649 // Make an assignment from a type guard to a pair of variables.
1650
1651 Statement*
1652 Statement::make_tuple_type_guard_assignment(Expression* val, Expression* ok,
1653                                             Expression* expr, Type* type,
1654                                             Location location)
1655 {
1656   return new Tuple_type_guard_assignment_statement(val, ok, expr, type,
1657                                                    location);
1658 }
1659
1660 // An expression statement.
1661
1662 class Expression_statement : public Statement
1663 {
1664  public:
1665   Expression_statement(Expression* expr, bool is_ignored)
1666     : Statement(STATEMENT_EXPRESSION, expr->location()),
1667       expr_(expr), is_ignored_(is_ignored)
1668   { }
1669
1670   Expression*
1671   expr()
1672   { return this->expr_; }
1673
1674  protected:
1675   int
1676   do_traverse(Traverse* traverse)
1677   { return this->traverse_expression(traverse, &this->expr_); }
1678
1679   void
1680   do_determine_types()
1681   { this->expr_->determine_type_no_context(); }
1682
1683   void
1684   do_check_types(Gogo*);
1685
1686   bool
1687   do_may_fall_through() const;
1688
1689   Bstatement*
1690   do_get_backend(Translate_context* context);
1691
1692   void
1693   do_dump_statement(Ast_dump_context*) const;
1694
1695  private:
1696   Expression* expr_;
1697   // Whether the value of this expression is being explicitly ignored.
1698   bool is_ignored_;
1699 };
1700
1701 // Check the types of an expression statement.  The only check we do
1702 // is to possibly give an error about discarding the value of the
1703 // expression.
1704
1705 void
1706 Expression_statement::do_check_types(Gogo*)
1707 {
1708   if (!this->is_ignored_)
1709     this->expr_->discarding_value();
1710 }
1711
1712 // An expression statement may fall through unless it is a call to a
1713 // function which does not return.
1714
1715 bool
1716 Expression_statement::do_may_fall_through() const
1717 {
1718   const Call_expression* call = this->expr_->call_expression();
1719   if (call != NULL)
1720     {
1721       const Expression* fn = call->fn();
1722       const Func_expression* fe = fn->func_expression();
1723       if (fe != NULL)
1724         {
1725           const Named_object* no = fe->named_object();
1726
1727           Function_type* fntype;
1728           if (no->is_function())
1729             fntype = no->func_value()->type();
1730           else if (no->is_function_declaration())
1731             fntype = no->func_declaration_value()->type();
1732           else
1733             fntype = NULL;
1734
1735           // The builtin function panic does not return.
1736           if (fntype != NULL && fntype->is_builtin() && no->name() == "panic")
1737             return false;
1738         }
1739     }
1740   return true;
1741 }
1742
1743 // Convert to backend representation.
1744
1745 Bstatement*
1746 Expression_statement::do_get_backend(Translate_context* context)
1747 {
1748   tree expr_tree = this->expr_->get_tree(context);
1749   return context->backend()->expression_statement(tree_to_expr(expr_tree));
1750 }
1751
1752 // Dump the AST representation for an expression statement
1753
1754 void
1755 Expression_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
1756     const
1757 {
1758   ast_dump_context->print_indent();
1759   ast_dump_context->dump_expression(expr_);
1760   ast_dump_context->ostream() << std::endl;
1761 }
1762
1763 // Make an expression statement from an Expression.
1764
1765 Statement*
1766 Statement::make_statement(Expression* expr, bool is_ignored)
1767 {
1768   return new Expression_statement(expr, is_ignored);
1769 }
1770
1771 // A block statement--a list of statements which may include variable
1772 // definitions.
1773
1774 class Block_statement : public Statement
1775 {
1776  public:
1777   Block_statement(Block* block, Location location)
1778     : Statement(STATEMENT_BLOCK, location),
1779       block_(block)
1780   { }
1781
1782  protected:
1783   int
1784   do_traverse(Traverse* traverse)
1785   { return this->block_->traverse(traverse); }
1786
1787   void
1788   do_determine_types()
1789   { this->block_->determine_types(); }
1790
1791   bool
1792   do_may_fall_through() const
1793   { return this->block_->may_fall_through(); }
1794
1795   Bstatement*
1796   do_get_backend(Translate_context* context);
1797
1798   void
1799   do_dump_statement(Ast_dump_context*) const;
1800
1801  private:
1802   Block* block_;
1803 };
1804
1805 // Convert a block to the backend representation of a statement.
1806
1807 Bstatement*
1808 Block_statement::do_get_backend(Translate_context* context)
1809 {
1810   Bblock* bblock = this->block_->get_backend(context);
1811   return context->backend()->block_statement(bblock);
1812 }
1813
1814 // Dump the AST for a block statement
1815
1816 void
1817 Block_statement::do_dump_statement(Ast_dump_context*) const
1818 {
1819   // block statement braces are dumped when traversing.
1820 }
1821
1822 // Make a block statement.
1823
1824 Statement*
1825 Statement::make_block_statement(Block* block, Location location)
1826 {
1827   return new Block_statement(block, location);
1828 }
1829
1830 // An increment or decrement statement.
1831
1832 class Inc_dec_statement : public Statement
1833 {
1834  public:
1835   Inc_dec_statement(bool is_inc, Expression* expr)
1836     : Statement(STATEMENT_INCDEC, expr->location()),
1837       expr_(expr), is_inc_(is_inc)
1838   { }
1839
1840  protected:
1841   int
1842   do_traverse(Traverse* traverse)
1843   { return this->traverse_expression(traverse, &this->expr_); }
1844
1845   bool
1846   do_traverse_assignments(Traverse_assignments*)
1847   { go_unreachable(); }
1848
1849   Statement*
1850   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1851
1852   Bstatement*
1853   do_get_backend(Translate_context*)
1854   { go_unreachable(); }
1855
1856   void
1857   do_dump_statement(Ast_dump_context*) const;
1858
1859  private:
1860   // The l-value to increment or decrement.
1861   Expression* expr_;
1862   // Whether to increment or decrement.
1863   bool is_inc_;
1864 };
1865
1866 // Lower to += or -=.
1867
1868 Statement*
1869 Inc_dec_statement::do_lower(Gogo*, Named_object*, Block*, Statement_inserter*)
1870 {
1871   Location loc = this->location();
1872
1873   mpz_t oval;
1874   mpz_init_set_ui(oval, 1UL);
1875   Expression* oexpr = Expression::make_integer(&oval, NULL, loc);
1876   mpz_clear(oval);
1877
1878   Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ;
1879   return Statement::make_assignment_operation(op, this->expr_, oexpr, loc);
1880 }
1881
1882 // Dump the AST representation for a inc/dec statement.
1883
1884 void
1885 Inc_dec_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
1886 {
1887   ast_dump_context->print_indent();
1888   ast_dump_context->dump_expression(expr_);
1889   ast_dump_context->ostream() << (is_inc_? "++": "--") << std::endl;
1890 }
1891
1892 // Make an increment statement.
1893
1894 Statement*
1895 Statement::make_inc_statement(Expression* expr)
1896 {
1897   return new Inc_dec_statement(true, expr);
1898 }
1899
1900 // Make a decrement statement.
1901
1902 Statement*
1903 Statement::make_dec_statement(Expression* expr)
1904 {
1905   return new Inc_dec_statement(false, expr);
1906 }
1907
1908 // Class Thunk_statement.  This is the base class for go and defer
1909 // statements.
1910
1911 // Constructor.
1912
1913 Thunk_statement::Thunk_statement(Statement_classification classification,
1914                                  Call_expression* call,
1915                                  Location location)
1916     : Statement(classification, location),
1917       call_(call), struct_type_(NULL)
1918 {
1919 }
1920
1921 // Return whether this is a simple statement which does not require a
1922 // thunk.
1923
1924 bool
1925 Thunk_statement::is_simple(Function_type* fntype) const
1926 {
1927   // We need a thunk to call a method, or to pass a variable number of
1928   // arguments.
1929   if (fntype->is_method() || fntype->is_varargs())
1930     return false;
1931
1932   // A defer statement requires a thunk to set up for whether the
1933   // function can call recover.
1934   if (this->classification() == STATEMENT_DEFER)
1935     return false;
1936
1937   // We can only permit a single parameter of pointer type.
1938   const Typed_identifier_list* parameters = fntype->parameters();
1939   if (parameters != NULL
1940       && (parameters->size() > 1
1941           || (parameters->size() == 1
1942               && parameters->begin()->type()->points_to() == NULL)))
1943     return false;
1944
1945   // If the function returns multiple values, or returns a type other
1946   // than integer, floating point, or pointer, then it may get a
1947   // hidden first parameter, in which case we need the more
1948   // complicated approach.  This is true even though we are going to
1949   // ignore the return value.
1950   const Typed_identifier_list* results = fntype->results();
1951   if (results != NULL
1952       && (results->size() > 1
1953           || (results->size() == 1
1954               && !results->begin()->type()->is_basic_type()
1955               && results->begin()->type()->points_to() == NULL)))
1956     return false;
1957
1958   // If this calls something which is not a simple function, then we
1959   // need a thunk.
1960   Expression* fn = this->call_->call_expression()->fn();
1961   if (fn->interface_field_reference_expression() != NULL)
1962     return false;
1963
1964   return true;
1965 }
1966
1967 // Traverse a thunk statement.
1968
1969 int
1970 Thunk_statement::do_traverse(Traverse* traverse)
1971 {
1972   return this->traverse_expression(traverse, &this->call_);
1973 }
1974
1975 // We implement traverse_assignment for a thunk statement because it
1976 // effectively copies the function call.
1977
1978 bool
1979 Thunk_statement::do_traverse_assignments(Traverse_assignments* tassign)
1980 {
1981   Expression* fn = this->call_->call_expression()->fn();
1982   Expression* fn2 = fn;
1983   tassign->value(&fn2, true, false);
1984   return true;
1985 }
1986
1987 // Determine types in a thunk statement.
1988
1989 void
1990 Thunk_statement::do_determine_types()
1991 {
1992   this->call_->determine_type_no_context();
1993
1994   // Now that we know the types of the call, build the struct used to
1995   // pass parameters.
1996   Call_expression* ce = this->call_->call_expression();
1997   if (ce == NULL)
1998     return;
1999   Function_type* fntype = ce->get_function_type();
2000   if (fntype != NULL && !this->is_simple(fntype))
2001     this->struct_type_ = this->build_struct(fntype);
2002 }
2003
2004 // Check types in a thunk statement.
2005
2006 void
2007 Thunk_statement::do_check_types(Gogo*)
2008 {
2009   Call_expression* ce = this->call_->call_expression();
2010   if (ce == NULL)
2011     {
2012       if (!this->call_->is_error_expression())
2013         this->report_error("expected call expression");
2014       return;
2015     }
2016 }
2017
2018 // The Traverse class used to find and simplify thunk statements.
2019
2020 class Simplify_thunk_traverse : public Traverse
2021 {
2022  public:
2023   Simplify_thunk_traverse(Gogo* gogo)
2024     : Traverse(traverse_functions | traverse_blocks),
2025       gogo_(gogo), function_(NULL)
2026   { }
2027
2028   int
2029   function(Named_object*);
2030
2031   int
2032   block(Block*);
2033
2034  private:
2035   // General IR.
2036   Gogo* gogo_;
2037   // The function we are traversing.
2038   Named_object* function_;
2039 };
2040
2041 // Keep track of the current function while looking for thunks.
2042
2043 int
2044 Simplify_thunk_traverse::function(Named_object* no)
2045 {
2046   go_assert(this->function_ == NULL);
2047   this->function_ = no;
2048   int t = no->func_value()->traverse(this);
2049   this->function_ = NULL;
2050   if (t == TRAVERSE_EXIT)
2051     return t;
2052   return TRAVERSE_SKIP_COMPONENTS;
2053 }
2054
2055 // Look for thunks in a block.
2056
2057 int
2058 Simplify_thunk_traverse::block(Block* b)
2059 {
2060   // The parser ensures that thunk statements always appear at the end
2061   // of a block.
2062   if (b->statements()->size() < 1)
2063     return TRAVERSE_CONTINUE;
2064   Thunk_statement* stat = b->statements()->back()->thunk_statement();
2065   if (stat == NULL)
2066     return TRAVERSE_CONTINUE;
2067   if (stat->simplify_statement(this->gogo_, this->function_, b))
2068     return TRAVERSE_SKIP_COMPONENTS;
2069   return TRAVERSE_CONTINUE;
2070 }
2071
2072 // Simplify all thunk statements.
2073
2074 void
2075 Gogo::simplify_thunk_statements()
2076 {
2077   Simplify_thunk_traverse thunk_traverse(this);
2078   this->traverse(&thunk_traverse);
2079 }
2080
2081 // Return true if the thunk function is a constant, which means that
2082 // it does not need to be passed to the thunk routine.
2083
2084 bool
2085 Thunk_statement::is_constant_function() const
2086 {
2087   Call_expression* ce = this->call_->call_expression();
2088   Function_type* fntype = ce->get_function_type();
2089   if (fntype == NULL)
2090     {
2091       go_assert(saw_errors());
2092       return false;
2093     }
2094   if (fntype->is_builtin())
2095     return true;
2096   Expression* fn = ce->fn();
2097   if (fn->func_expression() != NULL)
2098     return fn->func_expression()->closure() == NULL;
2099   if (fn->interface_field_reference_expression() != NULL)
2100     return true;
2101   return false;
2102 }
2103
2104 // Simplify complex thunk statements into simple ones.  A complicated
2105 // thunk statement is one which takes anything other than zero
2106 // parameters or a single pointer parameter.  We rewrite it into code
2107 // which allocates a struct, stores the parameter values into the
2108 // struct, and does a simple go or defer statement which passes the
2109 // struct to a thunk.  The thunk does the real call.
2110
2111 bool
2112 Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
2113                                     Block* block)
2114 {
2115   if (this->classification() == STATEMENT_ERROR)
2116     return false;
2117   if (this->call_->is_error_expression())
2118     return false;
2119
2120   if (this->classification() == STATEMENT_DEFER)
2121     {
2122       // Make sure that the defer stack exists for the function.  We
2123       // will use when converting this statement to the backend
2124       // representation, but we want it to exist when we start
2125       // converting the function.
2126       function->func_value()->defer_stack(this->location());
2127     }
2128
2129   Call_expression* ce = this->call_->call_expression();
2130   Function_type* fntype = ce->get_function_type();
2131   if (fntype == NULL)
2132     {
2133       go_assert(saw_errors());
2134       this->set_is_error();
2135       return false;
2136     }
2137   if (this->is_simple(fntype))
2138     return false;
2139
2140   Expression* fn = ce->fn();
2141   Interface_field_reference_expression* interface_method =
2142     fn->interface_field_reference_expression();
2143
2144   Location location = this->location();
2145
2146   std::string thunk_name = Gogo::thunk_name();
2147
2148   // Build the thunk.
2149   this->build_thunk(gogo, thunk_name);
2150
2151   // Generate code to call the thunk.
2152
2153   // Get the values to store into the struct which is the single
2154   // argument to the thunk.
2155
2156   Expression_list* vals = new Expression_list();
2157   if (!this->is_constant_function())
2158     vals->push_back(fn);
2159
2160   if (interface_method != NULL)
2161     vals->push_back(interface_method->expr());
2162
2163   if (ce->args() != NULL)
2164     {
2165       for (Expression_list::const_iterator p = ce->args()->begin();
2166            p != ce->args()->end();
2167            ++p)
2168         vals->push_back(*p);
2169     }
2170
2171   // Build the struct.
2172   Expression* constructor =
2173     Expression::make_struct_composite_literal(this->struct_type_, vals,
2174                                               location);
2175
2176   // Allocate the initialized struct on the heap.
2177   constructor = Expression::make_heap_composite(constructor, location);
2178
2179   // Look up the thunk.
2180   Named_object* named_thunk = gogo->lookup(thunk_name, NULL);
2181   go_assert(named_thunk != NULL && named_thunk->is_function());
2182
2183   // Build the call.
2184   Expression* func = Expression::make_func_reference(named_thunk, NULL,
2185                                                      location);
2186   Expression_list* params = new Expression_list();
2187   params->push_back(constructor);
2188   Call_expression* call = Expression::make_call(func, params, false, location);
2189
2190   // Build the simple go or defer statement.
2191   Statement* s;
2192   if (this->classification() == STATEMENT_GO)
2193     s = Statement::make_go_statement(call, location);
2194   else if (this->classification() == STATEMENT_DEFER)
2195     s = Statement::make_defer_statement(call, location);
2196   else
2197     go_unreachable();
2198
2199   // The current block should end with the go statement.
2200   go_assert(block->statements()->size() >= 1);
2201   go_assert(block->statements()->back() == this);
2202   block->replace_statement(block->statements()->size() - 1, s);
2203
2204   // We already ran the determine_types pass, so we need to run it now
2205   // for the new statement.
2206   s->determine_types();
2207
2208   // Sanity check.
2209   gogo->check_types_in_block(block);
2210
2211   // Return true to tell the block not to keep looking at statements.
2212   return true;
2213 }
2214
2215 // Set the name to use for thunk parameter N.
2216
2217 void
2218 Thunk_statement::thunk_field_param(int n, char* buf, size_t buflen)
2219 {
2220   snprintf(buf, buflen, "a%d", n);
2221 }
2222
2223 // Build a new struct type to hold the parameters for a complicated
2224 // thunk statement.  FNTYPE is the type of the function call.
2225
2226 Struct_type*
2227 Thunk_statement::build_struct(Function_type* fntype)
2228 {
2229   Location location = this->location();
2230
2231   Struct_field_list* fields = new Struct_field_list();
2232
2233   Call_expression* ce = this->call_->call_expression();
2234   Expression* fn = ce->fn();
2235
2236   if (!this->is_constant_function())
2237     {
2238       // The function to call.
2239       fields->push_back(Struct_field(Typed_identifier("fn", fntype,
2240                                                       location)));
2241     }
2242
2243   // If this thunk statement calls a method on an interface, we pass
2244   // the interface object to the thunk.
2245   Interface_field_reference_expression* interface_method =
2246     fn->interface_field_reference_expression();
2247   if (interface_method != NULL)
2248     {
2249       Typed_identifier tid("object", interface_method->expr()->type(),
2250                            location);
2251       fields->push_back(Struct_field(tid));
2252     }
2253
2254   // The predeclared recover function has no argument.  However, we
2255   // add an argument when building recover thunks.  Handle that here.
2256   if (ce->is_recover_call())
2257     {
2258       fields->push_back(Struct_field(Typed_identifier("can_recover",
2259                                                       Type::lookup_bool_type(),
2260                                                       location)));
2261     }
2262
2263   const Expression_list* args = ce->args();
2264   if (args != NULL)
2265     {
2266       int i = 0;
2267       for (Expression_list::const_iterator p = args->begin();
2268            p != args->end();
2269            ++p, ++i)
2270         {
2271           char buf[50];
2272           this->thunk_field_param(i, buf, sizeof buf);
2273           fields->push_back(Struct_field(Typed_identifier(buf, (*p)->type(),
2274                                                           location)));
2275         }
2276     }
2277
2278   return Type::make_struct_type(fields, location);
2279 }
2280
2281 // Build the thunk we are going to call.  This is a brand new, albeit
2282 // artificial, function.
2283
2284 void
2285 Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
2286 {
2287   Location location = this->location();
2288
2289   Call_expression* ce = this->call_->call_expression();
2290
2291   bool may_call_recover = false;
2292   if (this->classification() == STATEMENT_DEFER)
2293     {
2294       Func_expression* fn = ce->fn()->func_expression();
2295       if (fn == NULL)
2296         may_call_recover = true;
2297       else
2298         {
2299           const Named_object* no = fn->named_object();
2300           if (!no->is_function())
2301             may_call_recover = true;
2302           else
2303             may_call_recover = no->func_value()->calls_recover();
2304         }
2305     }
2306
2307   // Build the type of the thunk.  The thunk takes a single parameter,
2308   // which is a pointer to the special structure we build.
2309   const char* const parameter_name = "__go_thunk_parameter";
2310   Typed_identifier_list* thunk_parameters = new Typed_identifier_list();
2311   Type* pointer_to_struct_type = Type::make_pointer_type(this->struct_type_);
2312   thunk_parameters->push_back(Typed_identifier(parameter_name,
2313                                                pointer_to_struct_type,
2314                                                location));
2315
2316   Typed_identifier_list* thunk_results = NULL;
2317   if (may_call_recover)
2318     {
2319       // When deferring a function which may call recover, add a
2320       // return value, to disable tail call optimizations which will
2321       // break the way we check whether recover is permitted.
2322       thunk_results = new Typed_identifier_list();
2323       thunk_results->push_back(Typed_identifier("", Type::lookup_bool_type(),
2324                                                 location));
2325     }
2326
2327   Function_type* thunk_type = Type::make_function_type(NULL, thunk_parameters,
2328                                                        thunk_results,
2329                                                        location);
2330
2331   // Start building the thunk.
2332   Named_object* function = gogo->start_function(thunk_name, thunk_type, true,
2333                                                 location);
2334
2335   gogo->start_block(location);
2336
2337   // For a defer statement, start with a call to
2338   // __go_set_defer_retaddr.  */
2339   Label* retaddr_label = NULL;
2340   if (may_call_recover)
2341     {
2342       retaddr_label = gogo->add_label_reference("retaddr", location, false);
2343       Expression* arg = Expression::make_label_addr(retaddr_label, location);
2344       Expression* call = Runtime::make_call(Runtime::SET_DEFER_RETADDR,
2345                                             location, 1, arg);
2346
2347       // This is a hack to prevent the middle-end from deleting the
2348       // label.
2349       gogo->start_block(location);
2350       gogo->add_statement(Statement::make_goto_statement(retaddr_label,
2351                                                          location));
2352       Block* then_block = gogo->finish_block(location);
2353       then_block->determine_types();
2354
2355       Statement* s = Statement::make_if_statement(call, then_block, NULL,
2356                                                   location);
2357       s->determine_types();
2358       gogo->add_statement(s);
2359     }
2360
2361   // Get a reference to the parameter.
2362   Named_object* named_parameter = gogo->lookup(parameter_name, NULL);
2363   go_assert(named_parameter != NULL && named_parameter->is_variable());
2364
2365   // Build the call.  Note that the field names are the same as the
2366   // ones used in build_struct.
2367   Expression* thunk_parameter = Expression::make_var_reference(named_parameter,
2368                                                                location);
2369   thunk_parameter = Expression::make_unary(OPERATOR_MULT, thunk_parameter,
2370                                            location);
2371
2372   Interface_field_reference_expression* interface_method =
2373     ce->fn()->interface_field_reference_expression();
2374
2375   Expression* func_to_call;
2376   unsigned int next_index;
2377   if (this->is_constant_function())
2378     {
2379       func_to_call = ce->fn();
2380       next_index = 0;
2381     }
2382   else
2383     {
2384       func_to_call = Expression::make_field_reference(thunk_parameter,
2385                                                       0, location);
2386       next_index = 1;
2387     }
2388
2389   if (interface_method != NULL)
2390     {
2391       // The main program passes the interface object.
2392       go_assert(next_index == 0);
2393       Expression* r = Expression::make_field_reference(thunk_parameter, 0,
2394                                                        location);
2395       const std::string& name(interface_method->name());
2396       func_to_call = Expression::make_interface_field_reference(r, name,
2397                                                                 location);
2398       next_index = 1;
2399     }
2400
2401   Expression_list* call_params = new Expression_list();
2402   const Struct_field_list* fields = this->struct_type_->fields();
2403   Struct_field_list::const_iterator p = fields->begin();
2404   for (unsigned int i = 0; i < next_index; ++i)
2405     ++p;
2406   bool is_recover_call = ce->is_recover_call();
2407   Expression* recover_arg = NULL;
2408   for (; p != fields->end(); ++p, ++next_index)
2409     {
2410       Expression* thunk_param = Expression::make_var_reference(named_parameter,
2411                                                                location);
2412       thunk_param = Expression::make_unary(OPERATOR_MULT, thunk_param,
2413                                            location);
2414       Expression* param = Expression::make_field_reference(thunk_param,
2415                                                            next_index,
2416                                                            location);
2417       if (!is_recover_call)
2418         call_params->push_back(param);
2419       else
2420         {
2421           go_assert(call_params->empty());
2422           recover_arg = param;
2423         }
2424     }
2425
2426   if (call_params->empty())
2427     {
2428       delete call_params;
2429       call_params = NULL;
2430     }
2431
2432   Call_expression* call = Expression::make_call(func_to_call, call_params,
2433                                                 false, location);
2434
2435   // This call expression was already lowered before entering the
2436   // thunk statement.  Don't try to lower varargs again, as that will
2437   // cause confusion for, e.g., method calls which already have a
2438   // receiver parameter.
2439   call->set_varargs_are_lowered();
2440
2441   Statement* call_statement = Statement::make_statement(call, true);
2442
2443   gogo->add_statement(call_statement);
2444
2445   // If this is a defer statement, the label comes immediately after
2446   // the call.
2447   if (may_call_recover)
2448     {
2449       gogo->add_label_definition("retaddr", location);
2450
2451       Expression_list* vals = new Expression_list();
2452       vals->push_back(Expression::make_boolean(false, location));
2453       gogo->add_statement(Statement::make_return_statement(vals, location));
2454     }
2455
2456   Block* b = gogo->finish_block(location);
2457
2458   gogo->add_block(b, location);
2459
2460   gogo->lower_block(function, b);
2461
2462   // We already ran the determine_types pass, so we need to run it
2463   // just for the call statement now.  The other types are known.
2464   call_statement->determine_types();
2465
2466   if (may_call_recover || recover_arg != NULL)
2467     {
2468       // Dig up the call expression, which may have been changed
2469       // during lowering.
2470       go_assert(call_statement->classification() == STATEMENT_EXPRESSION);
2471       Expression_statement* es =
2472         static_cast<Expression_statement*>(call_statement);
2473       Call_expression* ce = es->expr()->call_expression();
2474       go_assert(ce != NULL);
2475       if (may_call_recover)
2476         ce->set_is_deferred();
2477       if (recover_arg != NULL)
2478         ce->set_recover_arg(recover_arg);
2479     }
2480
2481   // That is all the thunk has to do.
2482   gogo->finish_function(location);
2483 }
2484
2485 // Get the function and argument expressions.
2486
2487 bool
2488 Thunk_statement::get_fn_and_arg(Expression** pfn, Expression** parg)
2489 {
2490   if (this->call_->is_error_expression())
2491     return false;
2492
2493   Call_expression* ce = this->call_->call_expression();
2494
2495   *pfn = ce->fn();
2496
2497   const Expression_list* args = ce->args();
2498   if (args == NULL || args->empty())
2499     *parg = Expression::make_nil(this->location());
2500   else
2501     {
2502       go_assert(args->size() == 1);
2503       *parg = args->front();
2504     }
2505
2506   return true;
2507 }
2508
2509 // Class Go_statement.
2510
2511 Bstatement*
2512 Go_statement::do_get_backend(Translate_context* context)
2513 {
2514   Expression* fn;
2515   Expression* arg;
2516   if (!this->get_fn_and_arg(&fn, &arg))
2517     return context->backend()->error_statement();
2518
2519   Expression* call = Runtime::make_call(Runtime::GO, this->location(), 2,
2520                                         fn, arg);
2521   tree call_tree = call->get_tree(context);
2522   Bexpression* call_bexpr = tree_to_expr(call_tree);
2523   return context->backend()->expression_statement(call_bexpr);
2524 }
2525
2526 // Dump the AST representation for go statement.
2527
2528 void
2529 Go_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2530 {
2531   ast_dump_context->print_indent();
2532   ast_dump_context->ostream() << "go ";
2533   ast_dump_context->dump_expression(this->call());
2534   ast_dump_context->ostream() << std::endl;
2535 }
2536
2537 // Make a go statement.
2538
2539 Statement*
2540 Statement::make_go_statement(Call_expression* call, Location location)
2541 {
2542   return new Go_statement(call, location);
2543 }
2544
2545 // Class Defer_statement.
2546
2547 Bstatement*
2548 Defer_statement::do_get_backend(Translate_context* context)
2549 {
2550   Expression* fn;
2551   Expression* arg;
2552   if (!this->get_fn_and_arg(&fn, &arg))
2553     return context->backend()->error_statement();
2554
2555   Location loc = this->location();
2556   Expression* ds = context->function()->func_value()->defer_stack(loc);
2557
2558   Expression* call = Runtime::make_call(Runtime::DEFER, loc, 3,
2559                                         ds, fn, arg);
2560   tree call_tree = call->get_tree(context);
2561   Bexpression* call_bexpr = tree_to_expr(call_tree);
2562   return context->backend()->expression_statement(call_bexpr);
2563 }
2564
2565 // Dump the AST representation for defer statement.
2566
2567 void
2568 Defer_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2569 {
2570   ast_dump_context->print_indent();
2571   ast_dump_context->ostream() << "defer ";
2572   ast_dump_context->dump_expression(this->call());
2573   ast_dump_context->ostream() << std::endl;
2574 }
2575
2576 // Make a defer statement.
2577
2578 Statement*
2579 Statement::make_defer_statement(Call_expression* call,
2580                                 Location location)
2581 {
2582   return new Defer_statement(call, location);
2583 }
2584
2585 // Class Return_statement.
2586
2587 // Traverse assignments.  We treat each return value as a top level
2588 // RHS in an expression.
2589
2590 bool
2591 Return_statement::do_traverse_assignments(Traverse_assignments* tassign)
2592 {
2593   Expression_list* vals = this->vals_;
2594   if (vals != NULL)
2595     {
2596       for (Expression_list::iterator p = vals->begin();
2597            p != vals->end();
2598            ++p)
2599         tassign->value(&*p, true, true);
2600     }
2601   return true;
2602 }
2603
2604 // Lower a return statement.  If we are returning a function call
2605 // which returns multiple values which match the current function,
2606 // split up the call's results.  If the return statement lists
2607 // explicit values, implement this statement by assigning the values
2608 // to the result variables and change this statement to a naked
2609 // return.  This lets panic/recover work correctly.
2610
2611 Statement*
2612 Return_statement::do_lower(Gogo*, Named_object* function, Block* enclosing,
2613                            Statement_inserter*)
2614 {
2615   if (this->is_lowered_)
2616     return this;
2617
2618   Expression_list* vals = this->vals_;
2619   this->vals_ = NULL;
2620   this->is_lowered_ = true;
2621
2622   Location loc = this->location();
2623
2624   size_t vals_count = vals == NULL ? 0 : vals->size();
2625   Function::Results* results = function->func_value()->result_variables();
2626   size_t results_count = results == NULL ? 0 : results->size();
2627
2628   if (vals_count == 0)
2629     {
2630       if (results_count > 0 && !function->func_value()->results_are_named())
2631         {
2632           this->report_error(_("not enough arguments to return"));
2633           return this;
2634         }
2635       return this;
2636     }
2637
2638   if (results_count == 0)
2639     {
2640       this->report_error(_("return with value in function "
2641                            "with no return type"));
2642       return this;
2643     }
2644
2645   // If the current function has multiple return values, and we are
2646   // returning a single call expression, split up the call expression.
2647   if (results_count > 1
2648       && vals->size() == 1
2649       && vals->front()->call_expression() != NULL)
2650     {
2651       Call_expression* call = vals->front()->call_expression();
2652       delete vals;
2653       vals = new Expression_list;
2654       for (size_t i = 0; i < results_count; ++i)
2655         vals->push_back(Expression::make_call_result(call, i));
2656       vals_count = results_count;
2657     }
2658
2659   if (vals_count < results_count)
2660     {
2661       this->report_error(_("not enough arguments to return"));
2662       return this;
2663     }
2664
2665   if (vals_count > results_count)
2666     {
2667       this->report_error(_("too many values in return statement"));
2668       return this;
2669     }
2670
2671   Block* b = new Block(enclosing, loc);
2672
2673   Expression_list* lhs = new Expression_list();
2674   Expression_list* rhs = new Expression_list();
2675
2676   Expression_list::const_iterator pe = vals->begin();
2677   int i = 1;
2678   for (Function::Results::const_iterator pr = results->begin();
2679        pr != results->end();
2680        ++pr, ++pe, ++i)
2681     {
2682       Named_object* rv = *pr;
2683       Expression* e = *pe;
2684
2685       // Check types now so that we give a good error message.  The
2686       // result type is known.  We determine the expression type
2687       // early.
2688
2689       Type *rvtype = rv->result_var_value()->type();
2690       Type_context type_context(rvtype, false);
2691       e->determine_type(&type_context);
2692
2693       std::string reason;
2694       bool ok;
2695       if (this->are_hidden_fields_ok_)
2696         ok = Type::are_assignable_hidden_ok(rvtype, e->type(), &reason);
2697       else
2698         ok = Type::are_assignable(rvtype, e->type(), &reason);
2699       if (ok)
2700         {
2701           Expression* ve = Expression::make_var_reference(rv, e->location());
2702           lhs->push_back(ve);
2703           rhs->push_back(e);
2704         }
2705       else
2706         {
2707           if (reason.empty())
2708             error_at(e->location(), "incompatible type for return value %d", i);
2709           else
2710             error_at(e->location(),
2711                      "incompatible type for return value %d (%s)",
2712                      i, reason.c_str());
2713         }
2714     }
2715   go_assert(lhs->size() == rhs->size());
2716
2717   if (lhs->empty())
2718     ;
2719   else if (lhs->size() == 1)
2720     {
2721       Statement* s = Statement::make_assignment(lhs->front(), rhs->front(),
2722                                                 loc);
2723       if (this->are_hidden_fields_ok_)
2724         {
2725           Assignment_statement* as = static_cast<Assignment_statement*>(s);
2726           as->set_hidden_fields_are_ok();
2727         }
2728       b->add_statement(s);
2729       delete lhs;
2730       delete rhs;
2731     }
2732   else
2733     {
2734       Statement* s = Statement::make_tuple_assignment(lhs, rhs, loc);
2735       if (this->are_hidden_fields_ok_)
2736         {
2737           Tuple_assignment_statement* tas =
2738             static_cast<Tuple_assignment_statement*>(s);
2739           tas->set_hidden_fields_are_ok();
2740         }
2741       b->add_statement(s);
2742     }
2743
2744   b->add_statement(this);
2745
2746   delete vals;
2747
2748   return Statement::make_block_statement(b, loc);
2749 }
2750
2751 // Convert a return statement to the backend representation.
2752
2753 Bstatement*
2754 Return_statement::do_get_backend(Translate_context* context)
2755 {
2756   Location loc = this->location();
2757
2758   Function* function = context->function()->func_value();
2759   tree fndecl = function->get_decl();
2760
2761   Function::Results* results = function->result_variables();
2762   std::vector<Bexpression*> retvals;
2763   if (results != NULL && !results->empty())
2764     {
2765       retvals.reserve(results->size());
2766       for (Function::Results::const_iterator p = results->begin();
2767            p != results->end();
2768            p++)
2769         {
2770           Expression* vr = Expression::make_var_reference(*p, loc);
2771           retvals.push_back(tree_to_expr(vr->get_tree(context)));
2772         }
2773     }
2774
2775   return context->backend()->return_statement(tree_to_function(fndecl),
2776                                               retvals, loc);
2777 }
2778
2779 // Dump the AST representation for a return statement.
2780
2781 void
2782 Return_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2783 {
2784   ast_dump_context->print_indent();
2785   ast_dump_context->ostream() << "return " ;
2786   ast_dump_context->dump_expression_list(this->vals_);
2787   ast_dump_context->ostream() << std::endl;
2788 }
2789
2790 // Make a return statement.
2791
2792 Return_statement*
2793 Statement::make_return_statement(Expression_list* vals,
2794                                  Location location)
2795 {
2796   return new Return_statement(vals, location);
2797 }
2798
2799 // A break or continue statement.
2800
2801 class Bc_statement : public Statement
2802 {
2803  public:
2804   Bc_statement(bool is_break, Unnamed_label* label, Location location)
2805     : Statement(STATEMENT_BREAK_OR_CONTINUE, location),
2806       label_(label), is_break_(is_break)
2807   { }
2808
2809   bool
2810   is_break() const
2811   { return this->is_break_; }
2812
2813  protected:
2814   int
2815   do_traverse(Traverse*)
2816   { return TRAVERSE_CONTINUE; }
2817
2818   bool
2819   do_may_fall_through() const
2820   { return false; }
2821
2822   Bstatement*
2823   do_get_backend(Translate_context* context)
2824   { return this->label_->get_goto(context, this->location()); }
2825
2826   void
2827   do_dump_statement(Ast_dump_context*) const;
2828
2829  private:
2830   // The label that this branches to.
2831   Unnamed_label* label_;
2832   // True if this is "break", false if it is "continue".
2833   bool is_break_;
2834 };
2835
2836 // Dump the AST representation for a break/continue statement
2837
2838 void
2839 Bc_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2840 {
2841   ast_dump_context->print_indent();
2842   ast_dump_context->ostream() << (this->is_break_ ? "break" : "continue");
2843   if (this->label_ != NULL)
2844     {
2845       ast_dump_context->ostream() << " ";
2846       ast_dump_context->dump_label_name(this->label_);
2847     }
2848   ast_dump_context->ostream() << std::endl;
2849 }
2850
2851 // Make a break statement.
2852
2853 Statement*
2854 Statement::make_break_statement(Unnamed_label* label, Location location)
2855 {
2856   return new Bc_statement(true, label, location);
2857 }
2858
2859 // Make a continue statement.
2860
2861 Statement*
2862 Statement::make_continue_statement(Unnamed_label* label,
2863                                    Location location)
2864 {
2865   return new Bc_statement(false, label, location);
2866 }
2867
2868 // A goto statement.
2869
2870 class Goto_statement : public Statement
2871 {
2872  public:
2873   Goto_statement(Label* label, Location location)
2874     : Statement(STATEMENT_GOTO, location),
2875       label_(label)
2876   { }
2877
2878  protected:
2879   int
2880   do_traverse(Traverse*)
2881   { return TRAVERSE_CONTINUE; }
2882
2883   void
2884   do_check_types(Gogo*);
2885
2886   bool
2887   do_may_fall_through() const
2888   { return false; }
2889
2890   Bstatement*
2891   do_get_backend(Translate_context*);
2892
2893   void
2894   do_dump_statement(Ast_dump_context*) const;
2895
2896  private:
2897   Label* label_;
2898 };
2899
2900 // Check types for a label.  There aren't any types per se, but we use
2901 // this to give an error if the label was never defined.
2902
2903 void
2904 Goto_statement::do_check_types(Gogo*)
2905 {
2906   if (!this->label_->is_defined())
2907     {
2908       error_at(this->location(), "reference to undefined label %qs",
2909                Gogo::message_name(this->label_->name()).c_str());
2910       this->set_is_error();
2911     }
2912 }
2913
2914 // Convert the goto statement to the backend representation.
2915
2916 Bstatement*
2917 Goto_statement::do_get_backend(Translate_context* context)
2918 {
2919   Blabel* blabel = this->label_->get_backend_label(context);
2920   return context->backend()->goto_statement(blabel, this->location());
2921 }
2922
2923 // Dump the AST representation for a goto statement.
2924
2925 void
2926 Goto_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2927 {
2928   ast_dump_context->print_indent();
2929   ast_dump_context->ostream() << "goto " << this->label_->name() << std::endl;
2930 }
2931
2932 // Make a goto statement.
2933
2934 Statement*
2935 Statement::make_goto_statement(Label* label, Location location)
2936 {
2937   return new Goto_statement(label, location);
2938 }
2939
2940 // A goto statement to an unnamed label.
2941
2942 class Goto_unnamed_statement : public Statement
2943 {
2944  public:
2945   Goto_unnamed_statement(Unnamed_label* label, Location location)
2946     : Statement(STATEMENT_GOTO_UNNAMED, location),
2947       label_(label)
2948   { }
2949
2950  protected:
2951   int
2952   do_traverse(Traverse*)
2953   { return TRAVERSE_CONTINUE; }
2954
2955   bool
2956   do_may_fall_through() const
2957   { return false; }
2958
2959   Bstatement*
2960   do_get_backend(Translate_context* context)
2961   { return this->label_->get_goto(context, this->location()); }
2962
2963   void
2964   do_dump_statement(Ast_dump_context*) const;
2965
2966  private:
2967   Unnamed_label* label_;
2968 };
2969
2970 // Dump the AST representation for an unnamed goto statement
2971
2972 void
2973 Goto_unnamed_statement::do_dump_statement(
2974     Ast_dump_context* ast_dump_context) const
2975 {
2976   ast_dump_context->print_indent();
2977   ast_dump_context->ostream() << "goto ";
2978   ast_dump_context->dump_label_name(this->label_);
2979   ast_dump_context->ostream() << std::endl;
2980 }
2981
2982 // Make a goto statement to an unnamed label.
2983
2984 Statement*
2985 Statement::make_goto_unnamed_statement(Unnamed_label* label,
2986                                        Location location)
2987 {
2988   return new Goto_unnamed_statement(label, location);
2989 }
2990
2991 // Class Label_statement.
2992
2993 // Traversal.
2994
2995 int
2996 Label_statement::do_traverse(Traverse*)
2997 {
2998   return TRAVERSE_CONTINUE;
2999 }
3000
3001 // Return the backend representation of the statement defining this
3002 // label.
3003
3004 Bstatement*
3005 Label_statement::do_get_backend(Translate_context* context)
3006 {
3007   Blabel* blabel = this->label_->get_backend_label(context);
3008   return context->backend()->label_definition_statement(blabel);
3009 }
3010
3011 // Dump the AST for a label definition statement.
3012
3013 void
3014 Label_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3015 {
3016   ast_dump_context->print_indent();
3017   ast_dump_context->ostream() << this->label_->name() << ":" << std::endl;
3018 }
3019
3020 // Make a label statement.
3021
3022 Statement*
3023 Statement::make_label_statement(Label* label, Location location)
3024 {
3025   return new Label_statement(label, location);
3026 }
3027
3028 // An unnamed label statement.
3029
3030 class Unnamed_label_statement : public Statement
3031 {
3032  public:
3033   Unnamed_label_statement(Unnamed_label* label)
3034     : Statement(STATEMENT_UNNAMED_LABEL, label->location()),
3035       label_(label)
3036   { }
3037
3038  protected:
3039   int
3040   do_traverse(Traverse*)
3041   { return TRAVERSE_CONTINUE; }
3042
3043   Bstatement*
3044   do_get_backend(Translate_context* context)
3045   { return this->label_->get_definition(context); }
3046
3047   void
3048   do_dump_statement(Ast_dump_context*) const;
3049
3050  private:
3051   // The label.
3052   Unnamed_label* label_;
3053 };
3054
3055 // Dump the AST representation for an unnamed label definition statement.
3056
3057 void
3058 Unnamed_label_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
3059     const
3060 {
3061   ast_dump_context->print_indent();
3062   ast_dump_context->dump_label_name(this->label_);
3063   ast_dump_context->ostream() << ":" << std::endl;
3064 }
3065
3066 // Make an unnamed label statement.
3067
3068 Statement*
3069 Statement::make_unnamed_label_statement(Unnamed_label* label)
3070 {
3071   return new Unnamed_label_statement(label);
3072 }
3073
3074 // An if statement.
3075
3076 class If_statement : public Statement
3077 {
3078  public:
3079   If_statement(Expression* cond, Block* then_block, Block* else_block,
3080                Location location)
3081     : Statement(STATEMENT_IF, location),
3082       cond_(cond), then_block_(then_block), else_block_(else_block)
3083   { }
3084
3085  protected:
3086   int
3087   do_traverse(Traverse*);
3088
3089   void
3090   do_determine_types();
3091
3092   void
3093   do_check_types(Gogo*);
3094
3095   bool
3096   do_may_fall_through() const;
3097
3098   Bstatement*
3099   do_get_backend(Translate_context*);
3100
3101   void
3102   do_dump_statement(Ast_dump_context*) const;
3103
3104  private:
3105   Expression* cond_;
3106   Block* then_block_;
3107   Block* else_block_;
3108 };
3109
3110 // Traversal.
3111
3112 int
3113 If_statement::do_traverse(Traverse* traverse)
3114 {
3115   if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT
3116       || this->then_block_->traverse(traverse) == TRAVERSE_EXIT)
3117     return TRAVERSE_EXIT;
3118   if (this->else_block_ != NULL)
3119     {
3120       if (this->else_block_->traverse(traverse) == TRAVERSE_EXIT)
3121         return TRAVERSE_EXIT;
3122     }
3123   return TRAVERSE_CONTINUE;
3124 }
3125
3126 void
3127 If_statement::do_determine_types()
3128 {
3129   Type_context context(Type::lookup_bool_type(), false);
3130   this->cond_->determine_type(&context);
3131   this->then_block_->determine_types();
3132   if (this->else_block_ != NULL)
3133     this->else_block_->determine_types();
3134 }
3135
3136 // Check types.
3137
3138 void
3139 If_statement::do_check_types(Gogo*)
3140 {
3141   Type* type = this->cond_->type();
3142   if (type->is_error())
3143     this->set_is_error();
3144   else if (!type->is_boolean_type())
3145     this->report_error(_("expected boolean expression"));
3146 }
3147
3148 // Whether the overall statement may fall through.
3149
3150 bool
3151 If_statement::do_may_fall_through() const
3152 {
3153   return (this->else_block_ == NULL
3154           || this->then_block_->may_fall_through()
3155           || this->else_block_->may_fall_through());
3156 }
3157
3158 // Get the backend representation.
3159
3160 Bstatement*
3161 If_statement::do_get_backend(Translate_context* context)
3162 {
3163   go_assert(this->cond_->type()->is_boolean_type()
3164              || this->cond_->type()->is_error());
3165   tree cond_tree = this->cond_->get_tree(context);
3166   Bexpression* cond_expr = tree_to_expr(cond_tree);
3167   Bblock* then_block = this->then_block_->get_backend(context);
3168   Bblock* else_block = (this->else_block_ == NULL
3169                         ? NULL
3170                         : this->else_block_->get_backend(context));
3171   return context->backend()->if_statement(cond_expr, then_block,
3172                                           else_block, this->location());
3173 }
3174
3175 // Dump the AST representation for an if statement
3176
3177 void
3178 If_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3179 {
3180   ast_dump_context->print_indent();
3181   ast_dump_context->ostream() << "if ";
3182   ast_dump_context->dump_expression(this->cond_);
3183   ast_dump_context->ostream() << std::endl;
3184   if (ast_dump_context->dump_subblocks())
3185     {
3186       ast_dump_context->dump_block(this->then_block_);
3187       if (this->else_block_ != NULL)
3188         {
3189           ast_dump_context->print_indent();
3190           ast_dump_context->ostream() << "else" << std::endl;
3191           ast_dump_context->dump_block(this->else_block_);
3192         }
3193     }
3194 }
3195
3196 // Make an if statement.
3197
3198 Statement*
3199 Statement::make_if_statement(Expression* cond, Block* then_block,
3200                              Block* else_block, Location location)
3201 {
3202   return new If_statement(cond, then_block, else_block, location);
3203 }
3204
3205 // Class Case_clauses::Hash_integer_value.
3206
3207 class Case_clauses::Hash_integer_value
3208 {
3209  public:
3210   size_t
3211   operator()(Expression*) const;
3212 };
3213
3214 size_t
3215 Case_clauses::Hash_integer_value::operator()(Expression* pe) const
3216 {
3217   Numeric_constant nc;
3218   mpz_t ival;
3219   if (!pe->numeric_constant_value(&nc) || !nc.to_int(&ival))
3220     go_unreachable();
3221   size_t ret = mpz_get_ui(ival);
3222   mpz_clear(ival);
3223   return ret;
3224 }
3225
3226 // Class Case_clauses::Eq_integer_value.
3227
3228 class Case_clauses::Eq_integer_value
3229 {
3230  public:
3231   bool
3232   operator()(Expression*, Expression*) const;
3233 };
3234
3235 bool
3236 Case_clauses::Eq_integer_value::operator()(Expression* a, Expression* b) const
3237 {
3238   Numeric_constant anc;
3239   mpz_t aval;
3240   Numeric_constant bnc;
3241   mpz_t bval;
3242   if (!a->numeric_constant_value(&anc)
3243       || !anc.to_int(&aval)
3244       || !b->numeric_constant_value(&bnc)
3245       || !bnc.to_int(&bval))
3246     go_unreachable();
3247   bool ret = mpz_cmp(aval, bval) == 0;
3248   mpz_clear(aval);
3249   mpz_clear(bval);
3250   return ret;
3251 }
3252
3253 // Class Case_clauses::Case_clause.
3254
3255 // Traversal.
3256
3257 int
3258 Case_clauses::Case_clause::traverse(Traverse* traverse)
3259 {
3260   if (this->cases_ != NULL
3261       && (traverse->traverse_mask()
3262           & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
3263     {
3264       if (this->cases_->traverse(traverse) == TRAVERSE_EXIT)
3265         return TRAVERSE_EXIT;
3266     }
3267   if (this->statements_ != NULL)
3268     {
3269       if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
3270         return TRAVERSE_EXIT;
3271     }
3272   return TRAVERSE_CONTINUE;
3273 }
3274
3275 // Check whether all the case expressions are integer constants.
3276
3277 bool
3278 Case_clauses::Case_clause::is_constant() const
3279 {
3280   if (this->cases_ != NULL)
3281     {
3282       for (Expression_list::const_iterator p = this->cases_->begin();
3283            p != this->cases_->end();
3284            ++p)
3285         if (!(*p)->is_constant() || (*p)->type()->integer_type() == NULL)
3286           return false;
3287     }
3288   return true;
3289 }
3290
3291 // Lower a case clause for a nonconstant switch.  VAL_TEMP is the
3292 // value we are switching on; it may be NULL.  If START_LABEL is not
3293 // NULL, it goes at the start of the statements, after the condition
3294 // test.  We branch to FINISH_LABEL at the end of the statements.
3295
3296 void
3297 Case_clauses::Case_clause::lower(Block* b, Temporary_statement* val_temp,
3298                                  Unnamed_label* start_label,
3299                                  Unnamed_label* finish_label) const
3300 {
3301   Location loc = this->location_;
3302   Unnamed_label* next_case_label;
3303   if (this->cases_ == NULL || this->cases_->empty())
3304     {
3305       go_assert(this->is_default_);
3306       next_case_label = NULL;
3307     }
3308   else
3309     {
3310       Expression* cond = NULL;
3311
3312       for (Expression_list::const_iterator p = this->cases_->begin();
3313            p != this->cases_->end();
3314            ++p)
3315         {
3316           Expression* this_cond;
3317           if (val_temp == NULL)
3318             this_cond = *p;
3319           else
3320             {
3321               Expression* ref = Expression::make_temporary_reference(val_temp,
3322                                                                      loc);
3323               this_cond = Expression::make_binary(OPERATOR_EQEQ, ref, *p, loc);
3324             }
3325
3326           if (cond == NULL)
3327             cond = this_cond;
3328           else
3329             cond = Expression::make_binary(OPERATOR_OROR, cond, this_cond, loc);
3330         }
3331
3332       Block* then_block = new Block(b, loc);
3333       next_case_label = new Unnamed_label(Linemap::unknown_location());
3334       Statement* s = Statement::make_goto_unnamed_statement(next_case_label,
3335                                                             loc);
3336       then_block->add_statement(s);
3337
3338       // if !COND { goto NEXT_CASE_LABEL }
3339       cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
3340       s = Statement::make_if_statement(cond, then_block, NULL, loc);
3341       b->add_statement(s);
3342     }
3343
3344   if (start_label != NULL)
3345     b->add_statement(Statement::make_unnamed_label_statement(start_label));
3346
3347   if (this->statements_ != NULL)
3348     b->add_statement(Statement::make_block_statement(this->statements_, loc));
3349
3350   Statement* s = Statement::make_goto_unnamed_statement(finish_label, loc);
3351   b->add_statement(s);
3352
3353   if (next_case_label != NULL)
3354     b->add_statement(Statement::make_unnamed_label_statement(next_case_label));
3355 }
3356
3357 // Determine types.
3358
3359 void
3360 Case_clauses::Case_clause::determine_types(Type* type)
3361 {
3362   if (this->cases_ != NULL)
3363     {
3364       Type_context case_context(type, false);
3365       for (Expression_list::iterator p = this->cases_->begin();
3366            p != this->cases_->end();
3367            ++p)
3368         (*p)->determine_type(&case_context);
3369     }
3370   if (this->statements_ != NULL)
3371     this->statements_->determine_types();
3372 }
3373
3374 // Check types.  Returns false if there was an error.
3375
3376 bool
3377 Case_clauses::Case_clause::check_types(Type* type)
3378 {
3379   if (this->cases_ != NULL)
3380     {
3381       for (Expression_list::iterator p = this->cases_->begin();
3382            p != this->cases_->end();
3383            ++p)
3384         {
3385           if (!Type::are_assignable(type, (*p)->type(), NULL)
3386               && !Type::are_assignable((*p)->type(), type, NULL))
3387             {
3388               error_at((*p)->location(),
3389                        "type mismatch between switch value and case clause");
3390               return false;
3391             }
3392         }
3393     }
3394   return true;
3395 }
3396
3397 // Return true if this clause may fall through to the following
3398 // statements.  Note that this is not the same as whether the case
3399 // uses the "fallthrough" keyword.
3400
3401 bool
3402 Case_clauses::Case_clause::may_fall_through() const
3403 {
3404   if (this->statements_ == NULL)
3405     return true;
3406   return this->statements_->may_fall_through();
3407 }
3408
3409 // Convert the case values and statements to the backend
3410 // representation.  BREAK_LABEL is the label which break statements
3411 // should branch to.  CASE_CONSTANTS is used to detect duplicate
3412 // constants.  *CASES should be passed as an empty vector; the values
3413 // for this case will be added to it.  If this is the default case,
3414 // *CASES will remain empty.  This returns the statement to execute if
3415 // one of these cases is selected.
3416
3417 Bstatement*
3418 Case_clauses::Case_clause::get_backend(Translate_context* context,
3419                                        Unnamed_label* break_label,
3420                                        Case_constants* case_constants,
3421                                        std::vector<Bexpression*>* cases) const
3422 {
3423   if (this->cases_ != NULL)
3424     {
3425       go_assert(!this->is_default_);
3426       for (Expression_list::const_iterator p = this->cases_->begin();
3427            p != this->cases_->end();
3428            ++p)
3429         {
3430           Expression* e = *p;
3431           if (e->classification() != Expression::EXPRESSION_INTEGER)
3432             {
3433               Numeric_constant nc;
3434               mpz_t ival;
3435               if (!(*p)->numeric_constant_value(&nc) || !nc.to_int(&ival))
3436                 {
3437                   // Something went wrong.  This can happen with a
3438                   // negative constant and an unsigned switch value.
3439                   go_assert(saw_errors());
3440                   continue;
3441                 }
3442               go_assert(nc.type() != NULL);
3443               e = Expression::make_integer(&ival, nc.type(), e->location());
3444               mpz_clear(ival);
3445             }
3446
3447           std::pair<Case_constants::iterator, bool> ins =
3448             case_constants->insert(e);
3449           if (!ins.second)
3450             {
3451               // Value was already present.
3452               error_at(this->location_, "duplicate case in switch");
3453               e = Expression::make_error(this->location_);
3454             }
3455
3456           tree case_tree = e->get_tree(context);
3457           Bexpression* case_expr = tree_to_expr(case_tree);
3458           cases->push_back(case_expr);
3459         }
3460     }
3461
3462   Bstatement* statements;
3463   if (this->statements_ == NULL)
3464     statements = NULL;
3465   else
3466     {
3467       Bblock* bblock = this->statements_->get_backend(context);
3468       statements = context->backend()->block_statement(bblock);
3469     }
3470
3471   Bstatement* break_stat;
3472   if (this->is_fallthrough_)
3473     break_stat = NULL;
3474   else
3475     break_stat = break_label->get_goto(context, this->location_);
3476
3477   if (statements == NULL)
3478     return break_stat;
3479   else if (break_stat == NULL)
3480     return statements;
3481   else
3482     return context->backend()->compound_statement(statements, break_stat);
3483 }
3484
3485 // Dump the AST representation for a case clause
3486
3487 void
3488 Case_clauses::Case_clause::dump_clause(Ast_dump_context* ast_dump_context)
3489     const
3490 {
3491   ast_dump_context->print_indent();
3492   if (this->is_default_)
3493     {
3494       ast_dump_context->ostream() << "default:";
3495     }
3496   else
3497     {
3498       ast_dump_context->ostream() << "case ";
3499       ast_dump_context->dump_expression_list(this->cases_);
3500       ast_dump_context->ostream() << ":" ;
3501     }
3502   ast_dump_context->dump_block(this->statements_);
3503   if (this->is_fallthrough_)
3504     {
3505       ast_dump_context->print_indent();
3506       ast_dump_context->ostream() <<  " (fallthrough)" << std::endl;
3507     }
3508 }
3509
3510 // Class Case_clauses.
3511
3512 // Traversal.
3513
3514 int
3515 Case_clauses::traverse(Traverse* traverse)
3516 {
3517   for (Clauses::iterator p = this->clauses_.begin();
3518        p != this->clauses_.end();
3519        ++p)
3520     {
3521       if (p->traverse(traverse) == TRAVERSE_EXIT)
3522         return TRAVERSE_EXIT;
3523     }
3524   return TRAVERSE_CONTINUE;
3525 }
3526
3527 // Check whether all the case expressions are constant.
3528
3529 bool
3530 Case_clauses::is_constant() const
3531 {
3532   for (Clauses::const_iterator p = this->clauses_.begin();
3533        p != this->clauses_.end();
3534        ++p)
3535     if (!p->is_constant())
3536       return false;
3537   return true;
3538 }
3539
3540 // Lower case clauses for a nonconstant switch.
3541
3542 void
3543 Case_clauses::lower(Block* b, Temporary_statement* val_temp,
3544                     Unnamed_label* break_label) const
3545 {
3546   // The default case.
3547   const Case_clause* default_case = NULL;
3548
3549   // The label for the fallthrough of the previous case.
3550   Unnamed_label* last_fallthrough_label = NULL;
3551
3552   // The label for the start of the default case.  This is used if the
3553   // case before the default case falls through.
3554   Unnamed_label* default_start_label = NULL;
3555
3556   // The label for the end of the default case.  This normally winds
3557   // up as BREAK_LABEL, but it will be different if the default case
3558   // falls through.
3559   Unnamed_label* default_finish_label = NULL;
3560
3561   for (Clauses::const_iterator p = this->clauses_.begin();
3562        p != this->clauses_.end();
3563        ++p)
3564     {
3565       // The label to use for the start of the statements for this
3566       // case.  This is NULL unless the previous case falls through.
3567       Unnamed_label* start_label = last_fallthrough_label;
3568
3569       // The label to jump to after the end of the statements for this
3570       // case.
3571       Unnamed_label* finish_label = break_label;
3572
3573       last_fallthrough_label = NULL;
3574       if (p->is_fallthrough() && p + 1 != this->clauses_.end())
3575         {
3576           finish_label = new Unnamed_label(p->location());
3577           last_fallthrough_label = finish_label;
3578         }
3579
3580       if (!p->is_default())
3581         p->lower(b, val_temp, start_label, finish_label);
3582       else
3583         {
3584           // We have to move the default case to the end, so that we