OSDN Git Service

compiler: Fix crash in go/defer of some builtin functions.
[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   if (!this->call_->discarding_value())
2010     return;
2011   Call_expression* ce = this->call_->call_expression();
2012   if (ce == NULL)
2013     {
2014       if (!this->call_->is_error_expression())
2015         this->report_error("expected call expression");
2016       return;
2017     }
2018 }
2019
2020 // The Traverse class used to find and simplify thunk statements.
2021
2022 class Simplify_thunk_traverse : public Traverse
2023 {
2024  public:
2025   Simplify_thunk_traverse(Gogo* gogo)
2026     : Traverse(traverse_functions | traverse_blocks),
2027       gogo_(gogo), function_(NULL)
2028   { }
2029
2030   int
2031   function(Named_object*);
2032
2033   int
2034   block(Block*);
2035
2036  private:
2037   // General IR.
2038   Gogo* gogo_;
2039   // The function we are traversing.
2040   Named_object* function_;
2041 };
2042
2043 // Keep track of the current function while looking for thunks.
2044
2045 int
2046 Simplify_thunk_traverse::function(Named_object* no)
2047 {
2048   go_assert(this->function_ == NULL);
2049   this->function_ = no;
2050   int t = no->func_value()->traverse(this);
2051   this->function_ = NULL;
2052   if (t == TRAVERSE_EXIT)
2053     return t;
2054   return TRAVERSE_SKIP_COMPONENTS;
2055 }
2056
2057 // Look for thunks in a block.
2058
2059 int
2060 Simplify_thunk_traverse::block(Block* b)
2061 {
2062   // The parser ensures that thunk statements always appear at the end
2063   // of a block.
2064   if (b->statements()->size() < 1)
2065     return TRAVERSE_CONTINUE;
2066   Thunk_statement* stat = b->statements()->back()->thunk_statement();
2067   if (stat == NULL)
2068     return TRAVERSE_CONTINUE;
2069   if (stat->simplify_statement(this->gogo_, this->function_, b))
2070     return TRAVERSE_SKIP_COMPONENTS;
2071   return TRAVERSE_CONTINUE;
2072 }
2073
2074 // Simplify all thunk statements.
2075
2076 void
2077 Gogo::simplify_thunk_statements()
2078 {
2079   Simplify_thunk_traverse thunk_traverse(this);
2080   this->traverse(&thunk_traverse);
2081 }
2082
2083 // Return true if the thunk function is a constant, which means that
2084 // it does not need to be passed to the thunk routine.
2085
2086 bool
2087 Thunk_statement::is_constant_function() const
2088 {
2089   Call_expression* ce = this->call_->call_expression();
2090   Function_type* fntype = ce->get_function_type();
2091   if (fntype == NULL)
2092     {
2093       go_assert(saw_errors());
2094       return false;
2095     }
2096   if (fntype->is_builtin())
2097     return true;
2098   Expression* fn = ce->fn();
2099   if (fn->func_expression() != NULL)
2100     return fn->func_expression()->closure() == NULL;
2101   if (fn->interface_field_reference_expression() != NULL)
2102     return true;
2103   return false;
2104 }
2105
2106 // Simplify complex thunk statements into simple ones.  A complicated
2107 // thunk statement is one which takes anything other than zero
2108 // parameters or a single pointer parameter.  We rewrite it into code
2109 // which allocates a struct, stores the parameter values into the
2110 // struct, and does a simple go or defer statement which passes the
2111 // struct to a thunk.  The thunk does the real call.
2112
2113 bool
2114 Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
2115                                     Block* block)
2116 {
2117   if (this->classification() == STATEMENT_ERROR)
2118     return false;
2119   if (this->call_->is_error_expression())
2120     return false;
2121
2122   if (this->classification() == STATEMENT_DEFER)
2123     {
2124       // Make sure that the defer stack exists for the function.  We
2125       // will use when converting this statement to the backend
2126       // representation, but we want it to exist when we start
2127       // converting the function.
2128       function->func_value()->defer_stack(this->location());
2129     }
2130
2131   Call_expression* ce = this->call_->call_expression();
2132   Function_type* fntype = ce->get_function_type();
2133   if (fntype == NULL)
2134     {
2135       go_assert(saw_errors());
2136       this->set_is_error();
2137       return false;
2138     }
2139   if (this->is_simple(fntype))
2140     return false;
2141
2142   Expression* fn = ce->fn();
2143   Interface_field_reference_expression* interface_method =
2144     fn->interface_field_reference_expression();
2145
2146   Location location = this->location();
2147
2148   std::string thunk_name = Gogo::thunk_name();
2149
2150   // Build the thunk.
2151   this->build_thunk(gogo, thunk_name);
2152
2153   // Generate code to call the thunk.
2154
2155   // Get the values to store into the struct which is the single
2156   // argument to the thunk.
2157
2158   Expression_list* vals = new Expression_list();
2159   if (!this->is_constant_function())
2160     vals->push_back(fn);
2161
2162   if (interface_method != NULL)
2163     vals->push_back(interface_method->expr());
2164
2165   if (ce->args() != NULL)
2166     {
2167       for (Expression_list::const_iterator p = ce->args()->begin();
2168            p != ce->args()->end();
2169            ++p)
2170         vals->push_back(*p);
2171     }
2172
2173   // Build the struct.
2174   Expression* constructor =
2175     Expression::make_struct_composite_literal(this->struct_type_, vals,
2176                                               location);
2177
2178   // Allocate the initialized struct on the heap.
2179   constructor = Expression::make_heap_composite(constructor, location);
2180
2181   // Look up the thunk.
2182   Named_object* named_thunk = gogo->lookup(thunk_name, NULL);
2183   go_assert(named_thunk != NULL && named_thunk->is_function());
2184
2185   // Build the call.
2186   Expression* func = Expression::make_func_reference(named_thunk, NULL,
2187                                                      location);
2188   Expression_list* params = new Expression_list();
2189   params->push_back(constructor);
2190   Call_expression* call = Expression::make_call(func, params, false, location);
2191
2192   // Build the simple go or defer statement.
2193   Statement* s;
2194   if (this->classification() == STATEMENT_GO)
2195     s = Statement::make_go_statement(call, location);
2196   else if (this->classification() == STATEMENT_DEFER)
2197     s = Statement::make_defer_statement(call, location);
2198   else
2199     go_unreachable();
2200
2201   // The current block should end with the go statement.
2202   go_assert(block->statements()->size() >= 1);
2203   go_assert(block->statements()->back() == this);
2204   block->replace_statement(block->statements()->size() - 1, s);
2205
2206   // We already ran the determine_types pass, so we need to run it now
2207   // for the new statement.
2208   s->determine_types();
2209
2210   // Sanity check.
2211   gogo->check_types_in_block(block);
2212
2213   // Return true to tell the block not to keep looking at statements.
2214   return true;
2215 }
2216
2217 // Set the name to use for thunk parameter N.
2218
2219 void
2220 Thunk_statement::thunk_field_param(int n, char* buf, size_t buflen)
2221 {
2222   snprintf(buf, buflen, "a%d", n);
2223 }
2224
2225 // Build a new struct type to hold the parameters for a complicated
2226 // thunk statement.  FNTYPE is the type of the function call.
2227
2228 Struct_type*
2229 Thunk_statement::build_struct(Function_type* fntype)
2230 {
2231   Location location = this->location();
2232
2233   Struct_field_list* fields = new Struct_field_list();
2234
2235   Call_expression* ce = this->call_->call_expression();
2236   Expression* fn = ce->fn();
2237
2238   if (!this->is_constant_function())
2239     {
2240       // The function to call.
2241       fields->push_back(Struct_field(Typed_identifier("fn", fntype,
2242                                                       location)));
2243     }
2244
2245   // If this thunk statement calls a method on an interface, we pass
2246   // the interface object to the thunk.
2247   Interface_field_reference_expression* interface_method =
2248     fn->interface_field_reference_expression();
2249   if (interface_method != NULL)
2250     {
2251       Typed_identifier tid("object", interface_method->expr()->type(),
2252                            location);
2253       fields->push_back(Struct_field(tid));
2254     }
2255
2256   // The predeclared recover function has no argument.  However, we
2257   // add an argument when building recover thunks.  Handle that here.
2258   if (ce->is_recover_call())
2259     {
2260       fields->push_back(Struct_field(Typed_identifier("can_recover",
2261                                                       Type::lookup_bool_type(),
2262                                                       location)));
2263     }
2264
2265   const Expression_list* args = ce->args();
2266   if (args != NULL)
2267     {
2268       int i = 0;
2269       for (Expression_list::const_iterator p = args->begin();
2270            p != args->end();
2271            ++p, ++i)
2272         {
2273           char buf[50];
2274           this->thunk_field_param(i, buf, sizeof buf);
2275           fields->push_back(Struct_field(Typed_identifier(buf, (*p)->type(),
2276                                                           location)));
2277         }
2278     }
2279
2280   return Type::make_struct_type(fields, location);
2281 }
2282
2283 // Build the thunk we are going to call.  This is a brand new, albeit
2284 // artificial, function.
2285
2286 void
2287 Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
2288 {
2289   Location location = this->location();
2290
2291   Call_expression* ce = this->call_->call_expression();
2292
2293   bool may_call_recover = false;
2294   if (this->classification() == STATEMENT_DEFER)
2295     {
2296       Func_expression* fn = ce->fn()->func_expression();
2297       if (fn == NULL)
2298         may_call_recover = true;
2299       else
2300         {
2301           const Named_object* no = fn->named_object();
2302           if (!no->is_function())
2303             may_call_recover = true;
2304           else
2305             may_call_recover = no->func_value()->calls_recover();
2306         }
2307     }
2308
2309   // Build the type of the thunk.  The thunk takes a single parameter,
2310   // which is a pointer to the special structure we build.
2311   const char* const parameter_name = "__go_thunk_parameter";
2312   Typed_identifier_list* thunk_parameters = new Typed_identifier_list();
2313   Type* pointer_to_struct_type = Type::make_pointer_type(this->struct_type_);
2314   thunk_parameters->push_back(Typed_identifier(parameter_name,
2315                                                pointer_to_struct_type,
2316                                                location));
2317
2318   Typed_identifier_list* thunk_results = NULL;
2319   if (may_call_recover)
2320     {
2321       // When deferring a function which may call recover, add a
2322       // return value, to disable tail call optimizations which will
2323       // break the way we check whether recover is permitted.
2324       thunk_results = new Typed_identifier_list();
2325       thunk_results->push_back(Typed_identifier("", Type::lookup_bool_type(),
2326                                                 location));
2327     }
2328
2329   Function_type* thunk_type = Type::make_function_type(NULL, thunk_parameters,
2330                                                        thunk_results,
2331                                                        location);
2332
2333   // Start building the thunk.
2334   Named_object* function = gogo->start_function(thunk_name, thunk_type, true,
2335                                                 location);
2336
2337   gogo->start_block(location);
2338
2339   // For a defer statement, start with a call to
2340   // __go_set_defer_retaddr.  */
2341   Label* retaddr_label = NULL;
2342   if (may_call_recover)
2343     {
2344       retaddr_label = gogo->add_label_reference("retaddr", location, false);
2345       Expression* arg = Expression::make_label_addr(retaddr_label, location);
2346       Expression* call = Runtime::make_call(Runtime::SET_DEFER_RETADDR,
2347                                             location, 1, arg);
2348
2349       // This is a hack to prevent the middle-end from deleting the
2350       // label.
2351       gogo->start_block(location);
2352       gogo->add_statement(Statement::make_goto_statement(retaddr_label,
2353                                                          location));
2354       Block* then_block = gogo->finish_block(location);
2355       then_block->determine_types();
2356
2357       Statement* s = Statement::make_if_statement(call, then_block, NULL,
2358                                                   location);
2359       s->determine_types();
2360       gogo->add_statement(s);
2361     }
2362
2363   // Get a reference to the parameter.
2364   Named_object* named_parameter = gogo->lookup(parameter_name, NULL);
2365   go_assert(named_parameter != NULL && named_parameter->is_variable());
2366
2367   // Build the call.  Note that the field names are the same as the
2368   // ones used in build_struct.
2369   Expression* thunk_parameter = Expression::make_var_reference(named_parameter,
2370                                                                location);
2371   thunk_parameter = Expression::make_unary(OPERATOR_MULT, thunk_parameter,
2372                                            location);
2373
2374   Interface_field_reference_expression* interface_method =
2375     ce->fn()->interface_field_reference_expression();
2376
2377   Expression* func_to_call;
2378   unsigned int next_index;
2379   if (this->is_constant_function())
2380     {
2381       func_to_call = ce->fn();
2382       next_index = 0;
2383     }
2384   else
2385     {
2386       func_to_call = Expression::make_field_reference(thunk_parameter,
2387                                                       0, location);
2388       next_index = 1;
2389     }
2390
2391   if (interface_method != NULL)
2392     {
2393       // The main program passes the interface object.
2394       go_assert(next_index == 0);
2395       Expression* r = Expression::make_field_reference(thunk_parameter, 0,
2396                                                        location);
2397       const std::string& name(interface_method->name());
2398       func_to_call = Expression::make_interface_field_reference(r, name,
2399                                                                 location);
2400       next_index = 1;
2401     }
2402
2403   Expression_list* call_params = new Expression_list();
2404   const Struct_field_list* fields = this->struct_type_->fields();
2405   Struct_field_list::const_iterator p = fields->begin();
2406   for (unsigned int i = 0; i < next_index; ++i)
2407     ++p;
2408   bool is_recover_call = ce->is_recover_call();
2409   Expression* recover_arg = NULL;
2410   for (; p != fields->end(); ++p, ++next_index)
2411     {
2412       Expression* thunk_param = Expression::make_var_reference(named_parameter,
2413                                                                location);
2414       thunk_param = Expression::make_unary(OPERATOR_MULT, thunk_param,
2415                                            location);
2416       Expression* param = Expression::make_field_reference(thunk_param,
2417                                                            next_index,
2418                                                            location);
2419       if (!is_recover_call)
2420         call_params->push_back(param);
2421       else
2422         {
2423           go_assert(call_params->empty());
2424           recover_arg = param;
2425         }
2426     }
2427
2428   if (call_params->empty())
2429     {
2430       delete call_params;
2431       call_params = NULL;
2432     }
2433
2434   Call_expression* call = Expression::make_call(func_to_call, call_params,
2435                                                 false, location);
2436
2437   // This call expression was already lowered before entering the
2438   // thunk statement.  Don't try to lower varargs again, as that will
2439   // cause confusion for, e.g., method calls which already have a
2440   // receiver parameter.
2441   call->set_varargs_are_lowered();
2442
2443   Statement* call_statement = Statement::make_statement(call, true);
2444
2445   gogo->add_statement(call_statement);
2446
2447   // If this is a defer statement, the label comes immediately after
2448   // the call.
2449   if (may_call_recover)
2450     {
2451       gogo->add_label_definition("retaddr", location);
2452
2453       Expression_list* vals = new Expression_list();
2454       vals->push_back(Expression::make_boolean(false, location));
2455       gogo->add_statement(Statement::make_return_statement(vals, location));
2456     }
2457
2458   Block* b = gogo->finish_block(location);
2459
2460   gogo->add_block(b, location);
2461
2462   gogo->lower_block(function, b);
2463
2464   // We already ran the determine_types pass, so we need to run it
2465   // just for the call statement now.  The other types are known.
2466   call_statement->determine_types();
2467
2468   if (may_call_recover || recover_arg != NULL)
2469     {
2470       // Dig up the call expression, which may have been changed
2471       // during lowering.
2472       go_assert(call_statement->classification() == STATEMENT_EXPRESSION);
2473       Expression_statement* es =
2474         static_cast<Expression_statement*>(call_statement);
2475       Call_expression* ce = es->expr()->call_expression();
2476       if (ce == NULL)
2477         go_assert(saw_errors());
2478       else
2479         {
2480           if (may_call_recover)
2481             ce->set_is_deferred();
2482           if (recover_arg != NULL)
2483             ce->set_recover_arg(recover_arg);
2484         }
2485     }
2486
2487   // That is all the thunk has to do.
2488   gogo->finish_function(location);
2489 }
2490
2491 // Get the function and argument expressions.
2492
2493 bool
2494 Thunk_statement::get_fn_and_arg(Expression** pfn, Expression** parg)
2495 {
2496   if (this->call_->is_error_expression())
2497     return false;
2498
2499   Call_expression* ce = this->call_->call_expression();
2500
2501   *pfn = ce->fn();
2502
2503   const Expression_list* args = ce->args();
2504   if (args == NULL || args->empty())
2505     *parg = Expression::make_nil(this->location());
2506   else
2507     {
2508       go_assert(args->size() == 1);
2509       *parg = args->front();
2510     }
2511
2512   return true;
2513 }
2514
2515 // Class Go_statement.
2516
2517 Bstatement*
2518 Go_statement::do_get_backend(Translate_context* context)
2519 {
2520   Expression* fn;
2521   Expression* arg;
2522   if (!this->get_fn_and_arg(&fn, &arg))
2523     return context->backend()->error_statement();
2524
2525   Expression* call = Runtime::make_call(Runtime::GO, this->location(), 2,
2526                                         fn, arg);
2527   tree call_tree = call->get_tree(context);
2528   Bexpression* call_bexpr = tree_to_expr(call_tree);
2529   return context->backend()->expression_statement(call_bexpr);
2530 }
2531
2532 // Dump the AST representation for go statement.
2533
2534 void
2535 Go_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2536 {
2537   ast_dump_context->print_indent();
2538   ast_dump_context->ostream() << "go ";
2539   ast_dump_context->dump_expression(this->call());
2540   ast_dump_context->ostream() << std::endl;
2541 }
2542
2543 // Make a go statement.
2544
2545 Statement*
2546 Statement::make_go_statement(Call_expression* call, Location location)
2547 {
2548   return new Go_statement(call, location);
2549 }
2550
2551 // Class Defer_statement.
2552
2553 Bstatement*
2554 Defer_statement::do_get_backend(Translate_context* context)
2555 {
2556   Expression* fn;
2557   Expression* arg;
2558   if (!this->get_fn_and_arg(&fn, &arg))
2559     return context->backend()->error_statement();
2560
2561   Location loc = this->location();
2562   Expression* ds = context->function()->func_value()->defer_stack(loc);
2563
2564   Expression* call = Runtime::make_call(Runtime::DEFER, loc, 3,
2565                                         ds, fn, arg);
2566   tree call_tree = call->get_tree(context);
2567   Bexpression* call_bexpr = tree_to_expr(call_tree);
2568   return context->backend()->expression_statement(call_bexpr);
2569 }
2570
2571 // Dump the AST representation for defer statement.
2572
2573 void
2574 Defer_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2575 {
2576   ast_dump_context->print_indent();
2577   ast_dump_context->ostream() << "defer ";
2578   ast_dump_context->dump_expression(this->call());
2579   ast_dump_context->ostream() << std::endl;
2580 }
2581
2582 // Make a defer statement.
2583
2584 Statement*
2585 Statement::make_defer_statement(Call_expression* call,
2586                                 Location location)
2587 {
2588   return new Defer_statement(call, location);
2589 }
2590
2591 // Class Return_statement.
2592
2593 // Traverse assignments.  We treat each return value as a top level
2594 // RHS in an expression.
2595
2596 bool
2597 Return_statement::do_traverse_assignments(Traverse_assignments* tassign)
2598 {
2599   Expression_list* vals = this->vals_;
2600   if (vals != NULL)
2601     {
2602       for (Expression_list::iterator p = vals->begin();
2603            p != vals->end();
2604            ++p)
2605         tassign->value(&*p, true, true);
2606     }
2607   return true;
2608 }
2609
2610 // Lower a return statement.  If we are returning a function call
2611 // which returns multiple values which match the current function,
2612 // split up the call's results.  If the return statement lists
2613 // explicit values, implement this statement by assigning the values
2614 // to the result variables and change this statement to a naked
2615 // return.  This lets panic/recover work correctly.
2616
2617 Statement*
2618 Return_statement::do_lower(Gogo*, Named_object* function, Block* enclosing,
2619                            Statement_inserter*)
2620 {
2621   if (this->is_lowered_)
2622     return this;
2623
2624   Expression_list* vals = this->vals_;
2625   this->vals_ = NULL;
2626   this->is_lowered_ = true;
2627
2628   Location loc = this->location();
2629
2630   size_t vals_count = vals == NULL ? 0 : vals->size();
2631   Function::Results* results = function->func_value()->result_variables();
2632   size_t results_count = results == NULL ? 0 : results->size();
2633
2634   if (vals_count == 0)
2635     {
2636       if (results_count > 0 && !function->func_value()->results_are_named())
2637         {
2638           this->report_error(_("not enough arguments to return"));
2639           return this;
2640         }
2641       return this;
2642     }
2643
2644   if (results_count == 0)
2645     {
2646       this->report_error(_("return with value in function "
2647                            "with no return type"));
2648       return this;
2649     }
2650
2651   // If the current function has multiple return values, and we are
2652   // returning a single call expression, split up the call expression.
2653   if (results_count > 1
2654       && vals->size() == 1
2655       && vals->front()->call_expression() != NULL)
2656     {
2657       Call_expression* call = vals->front()->call_expression();
2658       delete vals;
2659       vals = new Expression_list;
2660       for (size_t i = 0; i < results_count; ++i)
2661         vals->push_back(Expression::make_call_result(call, i));
2662       vals_count = results_count;
2663     }
2664
2665   if (vals_count < results_count)
2666     {
2667       this->report_error(_("not enough arguments to return"));
2668       return this;
2669     }
2670
2671   if (vals_count > results_count)
2672     {
2673       this->report_error(_("too many values in return statement"));
2674       return this;
2675     }
2676
2677   Block* b = new Block(enclosing, loc);
2678
2679   Expression_list* lhs = new Expression_list();
2680   Expression_list* rhs = new Expression_list();
2681
2682   Expression_list::const_iterator pe = vals->begin();
2683   int i = 1;
2684   for (Function::Results::const_iterator pr = results->begin();
2685        pr != results->end();
2686        ++pr, ++pe, ++i)
2687     {
2688       Named_object* rv = *pr;
2689       Expression* e = *pe;
2690
2691       // Check types now so that we give a good error message.  The
2692       // result type is known.  We determine the expression type
2693       // early.
2694
2695       Type *rvtype = rv->result_var_value()->type();
2696       Type_context type_context(rvtype, false);
2697       e->determine_type(&type_context);
2698
2699       std::string reason;
2700       bool ok;
2701       if (this->are_hidden_fields_ok_)
2702         ok = Type::are_assignable_hidden_ok(rvtype, e->type(), &reason);
2703       else
2704         ok = Type::are_assignable(rvtype, e->type(), &reason);
2705       if (ok)
2706         {
2707           Expression* ve = Expression::make_var_reference(rv, e->location());
2708           lhs->push_back(ve);
2709           rhs->push_back(e);
2710         }
2711       else
2712         {
2713           if (reason.empty())
2714             error_at(e->location(), "incompatible type for return value %d", i);
2715           else
2716             error_at(e->location(),
2717                      "incompatible type for return value %d (%s)",
2718                      i, reason.c_str());
2719         }
2720     }
2721   go_assert(lhs->size() == rhs->size());
2722
2723   if (lhs->empty())
2724     ;
2725   else if (lhs->size() == 1)
2726     {
2727       Statement* s = Statement::make_assignment(lhs->front(), rhs->front(),
2728                                                 loc);
2729       if (this->are_hidden_fields_ok_)
2730         {
2731           Assignment_statement* as = static_cast<Assignment_statement*>(s);
2732           as->set_hidden_fields_are_ok();
2733         }
2734       b->add_statement(s);
2735       delete lhs;
2736       delete rhs;
2737     }
2738   else
2739     {
2740       Statement* s = Statement::make_tuple_assignment(lhs, rhs, loc);
2741       if (this->are_hidden_fields_ok_)
2742         {
2743           Tuple_assignment_statement* tas =
2744             static_cast<Tuple_assignment_statement*>(s);
2745           tas->set_hidden_fields_are_ok();
2746         }
2747       b->add_statement(s);
2748     }
2749
2750   b->add_statement(this);
2751
2752   delete vals;
2753
2754   return Statement::make_block_statement(b, loc);
2755 }
2756
2757 // Convert a return statement to the backend representation.
2758
2759 Bstatement*
2760 Return_statement::do_get_backend(Translate_context* context)
2761 {
2762   Location loc = this->location();
2763
2764   Function* function = context->function()->func_value();
2765   tree fndecl = function->get_decl();
2766
2767   Function::Results* results = function->result_variables();
2768   std::vector<Bexpression*> retvals;
2769   if (results != NULL && !results->empty())
2770     {
2771       retvals.reserve(results->size());
2772       for (Function::Results::const_iterator p = results->begin();
2773            p != results->end();
2774            p++)
2775         {
2776           Expression* vr = Expression::make_var_reference(*p, loc);
2777           retvals.push_back(tree_to_expr(vr->get_tree(context)));
2778         }
2779     }
2780
2781   return context->backend()->return_statement(tree_to_function(fndecl),
2782                                               retvals, loc);
2783 }
2784
2785 // Dump the AST representation for a return statement.
2786
2787 void
2788 Return_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2789 {
2790   ast_dump_context->print_indent();
2791   ast_dump_context->ostream() << "return " ;
2792   ast_dump_context->dump_expression_list(this->vals_);
2793   ast_dump_context->ostream() << std::endl;
2794 }
2795
2796 // Make a return statement.
2797
2798 Return_statement*
2799 Statement::make_return_statement(Expression_list* vals,
2800                                  Location location)
2801 {
2802   return new Return_statement(vals, location);
2803 }
2804
2805 // A break or continue statement.
2806
2807 class Bc_statement : public Statement
2808 {
2809  public:
2810   Bc_statement(bool is_break, Unnamed_label* label, Location location)
2811     : Statement(STATEMENT_BREAK_OR_CONTINUE, location),
2812       label_(label), is_break_(is_break)
2813   { }
2814
2815   bool
2816   is_break() const
2817   { return this->is_break_; }
2818
2819  protected:
2820   int
2821   do_traverse(Traverse*)
2822   { return TRAVERSE_CONTINUE; }
2823
2824   bool
2825   do_may_fall_through() const
2826   { return false; }
2827
2828   Bstatement*
2829   do_get_backend(Translate_context* context)
2830   { return this->label_->get_goto(context, this->location()); }
2831
2832   void
2833   do_dump_statement(Ast_dump_context*) const;
2834
2835  private:
2836   // The label that this branches to.
2837   Unnamed_label* label_;
2838   // True if this is "break", false if it is "continue".
2839   bool is_break_;
2840 };
2841
2842 // Dump the AST representation for a break/continue statement
2843
2844 void
2845 Bc_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2846 {
2847   ast_dump_context->print_indent();
2848   ast_dump_context->ostream() << (this->is_break_ ? "break" : "continue");
2849   if (this->label_ != NULL)
2850     {
2851       ast_dump_context->ostream() << " ";
2852       ast_dump_context->dump_label_name(this->label_);
2853     }
2854   ast_dump_context->ostream() << std::endl;
2855 }
2856
2857 // Make a break statement.
2858
2859 Statement*
2860 Statement::make_break_statement(Unnamed_label* label, Location location)
2861 {
2862   return new Bc_statement(true, label, location);
2863 }
2864
2865 // Make a continue statement.
2866
2867 Statement*
2868 Statement::make_continue_statement(Unnamed_label* label,
2869                                    Location location)
2870 {
2871   return new Bc_statement(false, label, location);
2872 }
2873
2874 // A goto statement.
2875
2876 class Goto_statement : public Statement
2877 {
2878  public:
2879   Goto_statement(Label* label, Location location)
2880     : Statement(STATEMENT_GOTO, location),
2881       label_(label)
2882   { }
2883
2884  protected:
2885   int
2886   do_traverse(Traverse*)
2887   { return TRAVERSE_CONTINUE; }
2888
2889   void
2890   do_check_types(Gogo*);
2891
2892   bool
2893   do_may_fall_through() const
2894   { return false; }
2895
2896   Bstatement*
2897   do_get_backend(Translate_context*);
2898
2899   void
2900   do_dump_statement(Ast_dump_context*) const;
2901
2902  private:
2903   Label* label_;
2904 };
2905
2906 // Check types for a label.  There aren't any types per se, but we use
2907 // this to give an error if the label was never defined.
2908
2909 void
2910 Goto_statement::do_check_types(Gogo*)
2911 {
2912   if (!this->label_->is_defined())
2913     {
2914       error_at(this->location(), "reference to undefined label %qs",
2915                Gogo::message_name(this->label_->name()).c_str());
2916       this->set_is_error();
2917     }
2918 }
2919
2920 // Convert the goto statement to the backend representation.
2921
2922 Bstatement*
2923 Goto_statement::do_get_backend(Translate_context* context)
2924 {
2925   Blabel* blabel = this->label_->get_backend_label(context);
2926   return context->backend()->goto_statement(blabel, this->location());
2927 }
2928
2929 // Dump the AST representation for a goto statement.
2930
2931 void
2932 Goto_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2933 {
2934   ast_dump_context->print_indent();
2935   ast_dump_context->ostream() << "goto " << this->label_->name() << std::endl;
2936 }
2937
2938 // Make a goto statement.
2939
2940 Statement*
2941 Statement::make_goto_statement(Label* label, Location location)
2942 {
2943   return new Goto_statement(label, location);
2944 }
2945
2946 // A goto statement to an unnamed label.
2947
2948 class Goto_unnamed_statement : public Statement
2949 {
2950  public:
2951   Goto_unnamed_statement(Unnamed_label* label, Location location)
2952     : Statement(STATEMENT_GOTO_UNNAMED, location),
2953       label_(label)
2954   { }
2955
2956  protected:
2957   int
2958   do_traverse(Traverse*)
2959   { return TRAVERSE_CONTINUE; }
2960
2961   bool
2962   do_may_fall_through() const
2963   { return false; }
2964
2965   Bstatement*
2966   do_get_backend(Translate_context* context)
2967   { return this->label_->get_goto(context, this->location()); }
2968
2969   void
2970   do_dump_statement(Ast_dump_context*) const;
2971
2972  private:
2973   Unnamed_label* label_;
2974 };
2975
2976 // Dump the AST representation for an unnamed goto statement
2977
2978 void
2979 Goto_unnamed_statement::do_dump_statement(
2980     Ast_dump_context* ast_dump_context) const
2981 {
2982   ast_dump_context->print_indent();
2983   ast_dump_context->ostream() << "goto ";
2984   ast_dump_context->dump_label_name(this->label_);
2985   ast_dump_context->ostream() << std::endl;
2986 }
2987
2988 // Make a goto statement to an unnamed label.
2989
2990 Statement*
2991 Statement::make_goto_unnamed_statement(Unnamed_label* label,
2992                                        Location location)
2993 {
2994   return new Goto_unnamed_statement(label, location);
2995 }
2996
2997 // Class Label_statement.
2998
2999 // Traversal.
3000
3001 int
3002 Label_statement::do_traverse(Traverse*)
3003 {
3004   return TRAVERSE_CONTINUE;
3005 }
3006
3007 // Return the backend representation of the statement defining this
3008 // label.
3009
3010 Bstatement*
3011 Label_statement::do_get_backend(Translate_context* context)
3012 {
3013   Blabel* blabel = this->label_->get_backend_label(context);
3014   return context->backend()->label_definition_statement(blabel);
3015 }
3016
3017 // Dump the AST for a label definition statement.
3018
3019 void
3020 Label_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3021 {
3022   ast_dump_context->print_indent();
3023   ast_dump_context->ostream() << this->label_->name() << ":" << std::endl;
3024 }
3025
3026 // Make a label statement.
3027
3028 Statement*
3029 Statement::make_label_statement(Label* label, Location location)
3030 {
3031   return new Label_statement(label, location);
3032 }
3033
3034 // An unnamed label statement.
3035
3036 class Unnamed_label_statement : public Statement
3037 {
3038  public:
3039   Unnamed_label_statement(Unnamed_label* label)
3040     : Statement(STATEMENT_UNNAMED_LABEL, label->location()),
3041       label_(label)
3042   { }
3043
3044  protected:
3045   int
3046   do_traverse(Traverse*)
3047   { return TRAVERSE_CONTINUE; }
3048
3049   Bstatement*
3050   do_get_backend(Translate_context* context)
3051   { return this->label_->get_definition(context); }
3052
3053   void
3054   do_dump_statement(Ast_dump_context*) const;
3055
3056  private:
3057   // The label.
3058   Unnamed_label* label_;
3059 };
3060
3061 // Dump the AST representation for an unnamed label definition statement.
3062
3063 void
3064 Unnamed_label_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
3065     const
3066 {
3067   ast_dump_context->print_indent();
3068   ast_dump_context->dump_label_name(this->label_);
3069   ast_dump_context->ostream() << ":" << std::endl;
3070 }
3071
3072 // Make an unnamed label statement.
3073
3074 Statement*
3075 Statement::make_unnamed_label_statement(Unnamed_label* label)
3076 {
3077   return new Unnamed_label_statement(label);
3078 }
3079
3080 // An if statement.
3081
3082 class If_statement : public Statement
3083 {
3084  public:
3085   If_statement(Expression* cond, Block* then_block, Block* else_block,
3086                Location location)
3087     : Statement(STATEMENT_IF, location),
3088       cond_(cond), then_block_(then_block), else_block_(else_block)
3089   { }
3090
3091  protected:
3092   int
3093   do_traverse(Traverse*);
3094
3095   void
3096   do_determine_types();
3097
3098   void
3099   do_check_types(Gogo*);
3100
3101   bool
3102   do_may_fall_through() const;
3103
3104   Bstatement*
3105   do_get_backend(Translate_context*);
3106
3107   void
3108   do_dump_statement(Ast_dump_context*) const;
3109
3110  private:
3111   Expression* cond_;
3112   Block* then_block_;
3113   Block* else_block_;
3114 };
3115
3116 // Traversal.
3117
3118 int
3119 If_statement::do_traverse(Traverse* traverse)
3120 {
3121   if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT
3122       || this->then_block_->traverse(traverse) == TRAVERSE_EXIT)
3123     return TRAVERSE_EXIT;
3124   if (this->else_block_ != NULL)
3125     {
3126       if (this->else_block_->traverse(traverse) == TRAVERSE_EXIT)
3127         return TRAVERSE_EXIT;
3128     }
3129   return TRAVERSE_CONTINUE;
3130 }
3131
3132 void
3133 If_statement::do_determine_types()
3134 {
3135   Type_context context(Type::lookup_bool_type(), false);
3136   this->cond_->determine_type(&context);
3137   this->then_block_->determine_types();
3138   if (this->else_block_ != NULL)
3139     this->else_block_->determine_types();
3140 }
3141
3142 // Check types.
3143
3144 void
3145 If_statement::do_check_types(Gogo*)
3146 {
3147   Type* type = this->cond_->type();
3148   if (type->is_error())
3149     this->set_is_error();
3150   else if (!type->is_boolean_type())
3151     this->report_error(_("expected boolean expression"));
3152 }
3153
3154 // Whether the overall statement may fall through.
3155
3156 bool
3157 If_statement::do_may_fall_through() const
3158 {
3159   return (this->else_block_ == NULL
3160           || this->then_block_->may_fall_through()
3161           || this->else_block_->may_fall_through());
3162 }
3163
3164 // Get the backend representation.
3165
3166 Bstatement*
3167 If_statement::do_get_backend(Translate_context* context)
3168 {
3169   go_assert(this->cond_->type()->is_boolean_type()
3170              || this->cond_->type()->is_error());
3171   tree cond_tree = this->cond_->get_tree(context);
3172   Bexpression* cond_expr = tree_to_expr(cond_tree);
3173   Bblock* then_block = this->then_block_->get_backend(context);
3174   Bblock* else_block = (this->else_block_ == NULL
3175                         ? NULL
3176                         : this->else_block_->get_backend(context));
3177   return context->backend()->if_statement(cond_expr, then_block,
3178                                           else_block, this->location());
3179 }
3180
3181 // Dump the AST representation for an if statement
3182
3183 void
3184 If_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3185 {
3186   ast_dump_context->print_indent();
3187   ast_dump_context->ostream() << "if ";
3188   ast_dump_context->dump_expression(this->cond_);
3189   ast_dump_context->ostream() << std::endl;
3190   if (ast_dump_context->dump_subblocks())
3191     {
3192       ast_dump_context->dump_block(this->then_block_);
3193       if (this->else_block_ != NULL)
3194         {
3195           ast_dump_context->print_indent();
3196           ast_dump_context->ostream() << "else" << std::endl;
3197           ast_dump_context->dump_block(this->else_block_);
3198         }
3199     }
3200 }
3201
3202 // Make an if statement.
3203
3204 Statement*
3205 Statement::make_if_statement(Expression* cond, Block* then_block,
3206                              Block* else_block, Location location)
3207 {
3208   return new If_statement(cond, then_block, else_block, location);
3209 }
3210
3211 // Class Case_clauses::Hash_integer_value.
3212
3213 class Case_clauses::Hash_integer_value
3214 {
3215  public:
3216   size_t
3217   operator()(Expression*) const;
3218 };
3219
3220 size_t
3221 Case_clauses::Hash_integer_value::operator()(Expression* pe) const
3222 {
3223   Numeric_constant nc;
3224   mpz_t ival;
3225   if (!pe->numeric_constant_value(&nc) || !nc.to_int(&ival))
3226     go_unreachable();
3227   size_t ret = mpz_get_ui(ival);
3228   mpz_clear(ival);
3229   return ret;
3230 }
3231
3232 // Class Case_clauses::Eq_integer_value.
3233
3234 class Case_clauses::Eq_integer_value
3235 {
3236  public:
3237   bool
3238   operator()(Expression*, Expression*) const;
3239 };
3240
3241 bool
3242 Case_clauses::Eq_integer_value::operator()(Expression* a, Expression* b) const
3243 {
3244   Numeric_constant anc;
3245   mpz_t aval;
3246   Numeric_constant bnc;
3247   mpz_t bval;
3248   if (!a->numeric_constant_value(&anc)
3249       || !anc.to_int(&aval)
3250       || !b->numeric_constant_value(&bnc)
3251       || !bnc.to_int(&bval))
3252     go_unreachable();
3253   bool ret = mpz_cmp(aval, bval) == 0;
3254   mpz_clear(aval);
3255   mpz_clear(bval);
3256   return ret;
3257 }
3258
3259 // Class Case_clauses::Case_clause.
3260
3261 // Traversal.
3262
3263 int
3264 Case_clauses::Case_clause::traverse(Traverse* traverse)
3265 {
3266   if (this->cases_ != NULL
3267       && (traverse->traverse_mask()
3268           & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
3269     {
3270       if (this->cases_->traverse(traverse) == TRAVERSE_EXIT)
3271         return TRAVERSE_EXIT;
3272     }
3273   if (this->statements_ != NULL)
3274     {
3275       if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
3276         return TRAVERSE_EXIT;
3277     }
3278   return TRAVERSE_CONTINUE;
3279 }
3280
3281 // Check whether all the case expressions are integer constants.
3282
3283 bool
3284 Case_clauses::Case_clause::is_constant() const
3285 {
3286   if (this->cases_ != NULL)
3287     {
3288       for (Expression_list::const_iterator p = this->cases_->begin();
3289            p != this->cases_->end();
3290            ++p)
3291         if (!(*p)->is_constant() || (*p)->type()->integer_type() == NULL)
3292           return false;
3293     }
3294   return true;
3295 }
3296
3297 // Lower a case clause for a nonconstant switch.  VAL_TEMP is the
3298 // value we are switching on; it may be NULL.  If START_LABEL is not
3299 // NULL, it goes at the start of the statements, after the condition
3300 // test.  We branch to FINISH_LABEL at the end of the statements.
3301
3302 void
3303 Case_clauses::Case_clause::lower(Block* b, Temporary_statement* val_temp,
3304                                  Unnamed_label* start_label,
3305                                  Unnamed_label* finish_label) const
3306 {
3307   Location loc = this->location_;
3308   Unnamed_label* next_case_label;
3309   if (this->cases_ == NULL || this->cases_->empty())
3310     {
3311       go_assert(this->is_default_);
3312       next_case_label = NULL;
3313     }
3314   else
3315     {
3316       Expression* cond = NULL;
3317
3318       for (Expression_list::const_iterator p = this->cases_->begin();
3319            p != this->cases_->end();
3320            ++p)
3321         {
3322           Expression* ref = Expression::make_temporary_reference(val_temp,
3323                                                                  loc);
3324           Expression* this_cond = Expression::make_binary(OPERATOR_EQEQ, ref,
3325                                                           *p, loc);
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