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