Line data Source code
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 "go-diagnostics.h"
11 : #include "types.h"
12 : #include "expressions.h"
13 : #include "gogo.h"
14 : #include "export.h"
15 : #include "import.h"
16 : #include "runtime.h"
17 : #include "backend.h"
18 : #include "statements.h"
19 : #include "ast-dump.h"
20 :
21 : // Class Statement.
22 :
23 7691188 : Statement::Statement(Statement_classification classification,
24 7691188 : Location location)
25 7691188 : : classification_(classification), location_(location)
26 : {
27 7691188 : }
28 :
29 0 : Statement::~Statement()
30 : {
31 0 : }
32 :
33 : // Traverse the tree. The work of walking the components is handled
34 : // by the subclasses.
35 :
36 : int
37 93723028 : Statement::traverse(Block* block, size_t* pindex, Traverse* traverse)
38 : {
39 93723028 : if (this->classification_ == STATEMENT_ERROR)
40 : return TRAVERSE_CONTINUE;
41 :
42 93720219 : unsigned int traverse_mask = traverse->traverse_mask();
43 :
44 93720219 : if ((traverse_mask & Traverse::traverse_statements) != 0)
45 : {
46 56917113 : int t = traverse->statement(block, pindex, this);
47 56917113 : if (t == TRAVERSE_EXIT)
48 : return TRAVERSE_EXIT;
49 56897926 : else if (t == TRAVERSE_SKIP_COMPONENTS)
50 : return TRAVERSE_CONTINUE;
51 : }
52 :
53 : // No point in checking traverse_mask here--a statement may contain
54 : // other blocks or statements, and if we got here we always want to
55 : // walk them.
56 79650773 : return this->do_traverse(traverse);
57 : }
58 :
59 : // Traverse the contents of a statement.
60 :
61 : int
62 24055790 : Statement::traverse_contents(Traverse* traverse)
63 : {
64 24055790 : return this->do_traverse(traverse);
65 : }
66 :
67 : // Traverse an expression in a statement. This is a helper function
68 : // for child classes.
69 :
70 : int
71 70848662 : Statement::traverse_expression(Traverse* traverse, Expression** expr)
72 : {
73 70848662 : if ((traverse->traverse_mask()
74 70848662 : & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
75 : return TRAVERSE_CONTINUE;
76 51025910 : return Expression::traverse(expr, traverse);
77 : }
78 :
79 : // Traverse an expression list in a statement. This is a helper
80 : // function for child classes.
81 :
82 : int
83 7563434 : Statement::traverse_expression_list(Traverse* traverse,
84 : Expression_list* expr_list)
85 : {
86 7563434 : if (expr_list == NULL)
87 : return TRAVERSE_CONTINUE;
88 1522244 : if ((traverse->traverse_mask()
89 1522244 : & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
90 : return TRAVERSE_CONTINUE;
91 1522244 : return expr_list->traverse(traverse);
92 : }
93 :
94 : // Traverse a type in a statement. This is a helper function for
95 : // child classes.
96 :
97 : int
98 11450829 : Statement::traverse_type(Traverse* traverse, Type* type)
99 : {
100 11450829 : if ((traverse->traverse_mask()
101 11450829 : & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
102 : return TRAVERSE_CONTINUE;
103 8076536 : return Type::traverse(type, traverse);
104 : }
105 :
106 : // Set type information for unnamed constants. This is really done by
107 : // the child class.
108 :
109 : void
110 5804307 : Statement::determine_types(Gogo* gogo)
111 : {
112 5804307 : this->do_determine_types(gogo);
113 5804307 : }
114 :
115 : // Read a statement from export data.
116 :
117 : Statement*
118 69326 : Statement::import_statement(Import_function_body* ifb, Location loc)
119 : {
120 69326 : if (ifb->match_c_string("{"))
121 : {
122 21059 : bool is_lowered_for_statement;
123 21059 : Block* block = Block_statement::do_import(ifb, loc,
124 : &is_lowered_for_statement);
125 21059 : if (block == NULL)
126 0 : return Statement::make_error_statement(loc);
127 21059 : Block_statement* s = Statement::make_block_statement(block, loc);
128 21059 : if (is_lowered_for_statement)
129 0 : s->set_is_lowered_for_statement();
130 21059 : return s;
131 : }
132 48267 : else if (ifb->match_c_string("return"))
133 : {
134 : // After lowering return statements have no expressions. The
135 : // return expressions are assigned to result parameters.
136 12579 : ifb->advance(6);
137 12579 : return Statement::make_return_statement(ifb->function(), NULL, loc);
138 : }
139 35688 : else if (ifb->match_c_string("var $t"))
140 2661 : return Temporary_statement::do_import(ifb, loc);
141 33027 : else if (ifb->match_c_string("var "))
142 3280 : return Variable_declaration_statement::do_import(ifb, loc);
143 29747 : else if (ifb->match_c_string("if "))
144 5427 : return If_statement::do_import(ifb, loc);
145 24320 : else if (ifb->match_c_string(":"))
146 1434 : return Label_statement::do_import(ifb, loc);
147 22886 : else if (ifb->match_c_string("goto "))
148 1523 : return Goto_statement::do_import(ifb, loc);
149 :
150 21363 : Expression* lhs = Expression::import_expression(ifb, loc);
151 :
152 21363 : if (ifb->match_c_string(" //"))
153 4246 : return Statement::make_statement(lhs, true);
154 :
155 17117 : ifb->require_c_string(" = ");
156 17117 : Expression* rhs = Expression::import_expression(ifb, loc);
157 17117 : return Statement::make_assignment(lhs, rhs, loc);
158 : }
159 :
160 : // If this is a thunk statement, return it.
161 :
162 : Thunk_statement*
163 2146944 : Statement::thunk_statement()
164 : {
165 2146944 : Thunk_statement* ret = this->convert<Thunk_statement, STATEMENT_GO>();
166 2141907 : if (ret == NULL)
167 2141907 : ret = this->convert<Thunk_statement, STATEMENT_DEFER>();
168 2146944 : return ret;
169 : }
170 :
171 : // Convert a Statement to the backend representation. This is really
172 : // done by the child class.
173 :
174 : Bstatement*
175 7173369 : Statement::get_backend(Translate_context* context)
176 : {
177 7173369 : if (this->classification_ == STATEMENT_ERROR)
178 580 : return context->backend()->error_statement();
179 7172789 : return this->do_get_backend(context);
180 : }
181 :
182 : // Dump AST representation for a statement to a dump context.
183 :
184 : void
185 0 : Statement::dump_statement(Ast_dump_context* ast_dump_context) const
186 : {
187 0 : this->do_dump_statement(ast_dump_context);
188 0 : }
189 :
190 : // Note that this statement is erroneous. This is called by children
191 : // when they discover an error.
192 :
193 : void
194 284 : Statement::set_is_error()
195 : {
196 284 : this->classification_ = STATEMENT_ERROR;
197 284 : }
198 :
199 : // For children to call to report an error conveniently.
200 :
201 : void
202 28 : Statement::report_error(const char* msg)
203 : {
204 28 : go_error_at(this->location_, "%s", msg);
205 28 : this->set_is_error();
206 28 : }
207 :
208 : // An error statement, used to avoid crashing after we report an
209 : // error.
210 :
211 : class Error_statement : public Statement
212 : {
213 : public:
214 362 : Error_statement(Location location)
215 724 : : Statement(STATEMENT_ERROR, location)
216 : { }
217 :
218 : protected:
219 : int
220 362 : do_traverse(Traverse*)
221 362 : { return TRAVERSE_CONTINUE; }
222 :
223 : Bstatement*
224 0 : do_get_backend(Translate_context*)
225 0 : { go_unreachable(); }
226 :
227 : void
228 : do_dump_statement(Ast_dump_context*) const;
229 : };
230 :
231 : //
232 : // Helper to tack on available source position information
233 : // at the end of a statement.
234 : //
235 : static std::string
236 0 : dsuffix(Location location)
237 : {
238 0 : std::string lstr = Linemap::location_to_string(location);
239 0 : if (lstr == "")
240 0 : return lstr;
241 0 : std::string rval(" // ");
242 0 : rval += lstr;
243 0 : return rval;
244 0 : }
245 :
246 : // Dump the AST representation for an error statement.
247 :
248 : void
249 0 : Error_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
250 : {
251 0 : ast_dump_context->print_indent();
252 0 : ast_dump_context->ostream() << "Error statement" << std::endl;
253 0 : }
254 :
255 : // Make an error statement.
256 :
257 : Statement*
258 362 : Statement::make_error_statement(Location location)
259 : {
260 362 : return new Error_statement(location);
261 : }
262 :
263 : // Class Variable_declaration_statement.
264 :
265 383755 : Variable_declaration_statement::Variable_declaration_statement(
266 383755 : Named_object* var)
267 : : Statement(STATEMENT_VARIABLE_DECLARATION, var->var_value()->location()),
268 383755 : var_(var)
269 : {
270 383755 : }
271 :
272 : // We don't actually traverse the variable here; it was traversed
273 : // while traversing the Block.
274 :
275 : int
276 8686700 : Variable_declaration_statement::do_traverse(Traverse*)
277 : {
278 8686700 : return TRAVERSE_CONTINUE;
279 : }
280 :
281 : void
282 419772 : Variable_declaration_statement::do_determine_types(Gogo* gogo)
283 : {
284 419772 : this->var_->var_value()->determine_type(gogo);
285 419772 : }
286 :
287 : // Lower the variable's initialization expression.
288 :
289 : Statement*
290 538538 : Variable_declaration_statement::do_lower(Gogo* gogo, Named_object* function,
291 : Block*, Statement_inserter* inserter)
292 : {
293 538538 : this->var_->var_value()->lower_init_expression(gogo, function, inserter);
294 538538 : return this;
295 : }
296 :
297 : // Flatten the variable's initialization expression.
298 :
299 : Statement*
300 402409 : Variable_declaration_statement::do_flatten(Gogo* gogo, Named_object* function,
301 : Block*, Statement_inserter* inserter)
302 : {
303 402409 : Variable* var = this->var_->var_value();
304 402409 : if (var->type()->is_error_type()
305 402409 : || (var->init() != NULL
306 288428 : && var->init()->is_error_expression()))
307 : {
308 57 : go_assert(saw_errors());
309 57 : return Statement::make_error_statement(this->location());
310 : }
311 402352 : this->var_->var_value()->flatten_init_expression(gogo, function, inserter);
312 402352 : return this;
313 : }
314 :
315 : // Add explicit type conversions.
316 :
317 : void
318 382630 : Variable_declaration_statement::do_add_conversions()
319 : {
320 382630 : Variable* var = this->var_->var_value();
321 382630 : Expression* init = var->init();
322 382630 : if (init == NULL)
323 : return;
324 280746 : Type* lt = var->type();
325 280746 : Type* rt = init->type();
326 280746 : if (!Type::are_identical(lt, rt, 0, NULL)
327 280746 : && lt->interface_type() != NULL)
328 341 : var->set_init(Expression::make_cast(lt, init, this->location()));
329 : }
330 :
331 : // Convert a variable declaration to the backend representation.
332 :
333 : Bstatement*
334 382456 : Variable_declaration_statement::do_get_backend(Translate_context* context)
335 : {
336 382456 : if (this->var_->is_redefinition())
337 2 : return context->backend()->error_statement();
338 382454 : Bfunction* bfunction = context->function()->func_value()->get_decl();
339 382454 : Variable* var = this->var_->var_value();
340 382454 : Bvariable* bvar = this->var_->get_backend_variable(context->gogo(),
341 : context->function());
342 382454 : Bexpression* binit = var->get_init(context->gogo(), context->function());
343 :
344 382454 : if (!var->is_in_heap())
345 : {
346 368506 : go_assert(binit != NULL);
347 368506 : return context->backend()->init_statement(bfunction, bvar, binit);
348 : }
349 :
350 : // Something takes the address of this variable, so the value is
351 : // stored in the heap. Initialize it to newly allocated memory
352 : // space, and assign the initial value to the new space.
353 13948 : Location loc = this->location();
354 13948 : Named_object* newfn = context->gogo()->lookup_global("new");
355 13948 : go_assert(newfn != NULL && newfn->is_function_declaration());
356 13948 : Expression* func = Expression::make_func_reference(newfn, NULL, loc);
357 13948 : Expression_list* params = new Expression_list();
358 13948 : params->push_back(Expression::make_type(var->type(), loc));
359 13948 : Expression* call = Expression::make_call(func, params, false, loc);
360 13948 : context->gogo()->lower_expression(context->function(), NULL, &call);
361 13948 : Temporary_statement* temp = Statement::make_temporary(NULL, call, loc);
362 13948 : Bstatement* btemp = temp->get_backend(context);
363 :
364 13948 : Bstatement* set = NULL;
365 13948 : if (binit != NULL)
366 : {
367 1189 : Expression* e = Expression::make_temporary_reference(temp, loc);
368 1189 : e = Expression::make_dereference(e, Expression::NIL_CHECK_NOT_NEEDED,
369 : loc);
370 1189 : Bexpression* be = e->get_backend(context);
371 1189 : set = context->backend()->assignment_statement(bfunction, be, binit, loc);
372 : }
373 :
374 13948 : Expression* ref = Expression::make_temporary_reference(temp, loc);
375 13948 : Bexpression* bref = ref->get_backend(context);
376 13948 : Bstatement* sinit = context->backend()->init_statement(bfunction, bvar, bref);
377 :
378 13948 : std::vector<Bstatement*> stats;
379 13948 : stats.reserve(3);
380 13948 : stats.push_back(btemp);
381 13948 : if (set != NULL)
382 1189 : stats.push_back(set);
383 13948 : stats.push_back(sinit);
384 13948 : return context->backend()->statement_list(stats);
385 13948 : }
386 :
387 : // Dump the AST representation for a variable declaration.
388 :
389 : void
390 0 : Variable_declaration_statement::do_dump_statement(
391 : Ast_dump_context* ast_dump_context) const
392 : {
393 0 : ast_dump_context->print_indent();
394 :
395 0 : go_assert(var_->is_variable());
396 0 : ast_dump_context->ostream() << "var " << this->var_->name() << " ";
397 0 : Variable* var = this->var_->var_value();
398 0 : if (var->has_type())
399 : {
400 0 : ast_dump_context->dump_type(var->type());
401 0 : ast_dump_context->ostream() << " ";
402 : }
403 0 : if (var->init() != NULL)
404 : {
405 0 : ast_dump_context->ostream() << "= ";
406 0 : ast_dump_context->dump_expression(var->init());
407 : }
408 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
409 0 : }
410 :
411 : // Make a variable declaration.
412 :
413 : Statement*
414 383755 : Statement::make_variable_declaration(Named_object* var)
415 : {
416 383755 : return new Variable_declaration_statement(var);
417 : }
418 :
419 : // Export a variable declaration.
420 :
421 : void
422 4064 : Variable_declaration_statement::do_export_statement(Export_function_body* efb)
423 : {
424 4064 : efb->write_c_string("var ");
425 4064 : efb->write_string(Gogo::unpack_hidden_name(this->var_->name()));
426 4064 : efb->write_c_string(" ");
427 4064 : Variable* var = this->var_->var_value();
428 4064 : Type* type = var->type();
429 4064 : efb->write_type(type);
430 4064 : Expression* init = var->init();
431 4064 : if (init != NULL)
432 : {
433 2885 : efb->write_c_string(" = ");
434 :
435 2885 : go_assert(efb->type_context() == NULL);
436 2885 : efb->set_type_context(type);
437 :
438 2885 : init->export_expression(efb);
439 :
440 2885 : efb->set_type_context(NULL);
441 : }
442 4064 : }
443 :
444 : // Import a variable declaration.
445 :
446 : Statement*
447 3280 : Variable_declaration_statement::do_import(Import_function_body* ifb,
448 : Location loc)
449 : {
450 3280 : ifb->require_c_string("var ");
451 3280 : std::string id = ifb->read_identifier();
452 3280 : ifb->require_c_string(" ");
453 3280 : Type* type = ifb->read_type();
454 3280 : Expression* init = NULL;
455 3280 : if (ifb->match_c_string(" = "))
456 : {
457 2682 : ifb->advance(3);
458 2682 : init = Expression::import_expression(ifb, loc);
459 : }
460 3280 : Variable* var = new Variable(type, init, false, false, false, loc);
461 3280 : var->set_is_used();
462 : // FIXME: The package we are importing does not yet exist, so we
463 : // can't pass the correct package here. It probably doesn't matter.
464 3280 : Named_object* no = ifb->block()->bindings()->add_variable(id, NULL, var);
465 3280 : return Statement::make_variable_declaration(no);
466 3280 : }
467 :
468 : // Class Temporary_statement.
469 :
470 : // Return the type of the temporary variable.
471 :
472 : Type*
473 27299919 : Temporary_statement::type() const
474 : {
475 27299919 : Type* type = this->type_ != NULL ? this->type_ : this->init_->type();
476 :
477 : // Temporary variables cannot have a void type.
478 27299919 : if (type->is_void_type())
479 : {
480 0 : go_assert(saw_errors());
481 0 : return Type::make_error_type();
482 : }
483 : return type;
484 : }
485 :
486 : // Traversal.
487 :
488 : int
489 17308805 : Temporary_statement::do_traverse(Traverse* traverse)
490 : {
491 17308805 : if (this->type_ != NULL
492 17308805 : && this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
493 : return TRAVERSE_EXIT;
494 17308805 : if (this->init_ == NULL)
495 : return TRAVERSE_CONTINUE;
496 : else
497 13618364 : return this->traverse_expression(traverse, &this->init_);
498 : }
499 :
500 : // Determine types.
501 :
502 : void
503 656614 : Temporary_statement::do_determine_types(Gogo* gogo)
504 : {
505 656614 : if (this->type_ != NULL && this->type_->is_abstract())
506 970 : this->type_ = this->type_->make_non_abstract_type();
507 :
508 656614 : if (this->init_ != NULL)
509 : {
510 613556 : if (this->type_ == NULL)
511 363877 : this->init_->determine_type_no_context(gogo);
512 : else
513 : {
514 249679 : Type_context context(this->type_, false);
515 249679 : this->init_->determine_type(gogo, &context);
516 : }
517 : }
518 :
519 656614 : if (this->type_ == NULL)
520 : {
521 363877 : this->type_ = this->init_->type();
522 363877 : go_assert(!this->type_->is_abstract());
523 : }
524 656614 : }
525 :
526 : // Check types.
527 :
528 : void
529 6221 : Temporary_statement::do_check_types(Gogo*)
530 : {
531 6221 : if (this->type_ != NULL && this->init_ != NULL)
532 : {
533 2012 : std::string reason;
534 2012 : if (!Type::are_assignable(this->type_, this->init_->type(), &reason))
535 : {
536 0 : if (reason.empty())
537 0 : go_error_at(this->location(), "incompatible types in assignment");
538 : else
539 0 : go_error_at(this->location(), "incompatible types in assignment (%s)",
540 : reason.c_str());
541 0 : this->set_is_error();
542 : }
543 2012 : }
544 6221 : }
545 :
546 : // Flatten a temporary statement: add another temporary when it might
547 : // be needed for interface conversion.
548 :
549 : Statement*
550 1464241 : Temporary_statement::do_flatten(Gogo*, Named_object*, Block*,
551 : Statement_inserter* inserter)
552 : {
553 1464241 : if (this->type()->is_error_type()
554 1464241 : || (this->init_ != NULL
555 1252625 : && this->init_->is_error_expression()))
556 : {
557 35 : go_assert(saw_errors());
558 35 : return Statement::make_error_statement(this->location());
559 : }
560 :
561 1464206 : if (this->type_ != NULL
562 823513 : && this->init_ != NULL
563 611932 : && !Type::are_identical(this->type_, this->init_->type(),
564 : Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
565 : NULL)
566 18581 : && this->init_->type()->interface_type() != NULL
567 1464206 : && !this->init_->is_multi_eval_safe())
568 : {
569 0 : Temporary_statement *temp =
570 0 : Statement::make_temporary(NULL, this->init_, this->location());
571 0 : inserter->insert(temp);
572 0 : this->init_ = Expression::make_temporary_reference(temp,
573 : this->location());
574 : }
575 1464206 : return this;
576 : }
577 :
578 : // Add explicit type conversions.
579 :
580 : void
581 514598 : Temporary_statement::do_add_conversions()
582 : {
583 514598 : if (this->init_ == NULL)
584 : return;
585 342879 : Type* lt = this->type();
586 342879 : Type* rt = this->init_->type();
587 342879 : if (!Type::are_identical(lt, rt, 0, NULL)
588 342879 : && lt->interface_type() != NULL)
589 20988 : this->init_ = Expression::make_cast(lt, this->init_, this->location());
590 : }
591 :
592 : // Convert to backend representation.
593 :
594 : Bstatement*
595 1904105 : Temporary_statement::do_get_backend(Translate_context* context)
596 : {
597 1904105 : go_assert(this->bvariable_ == NULL);
598 :
599 1904105 : Named_object* function = context->function();
600 1904105 : go_assert(function != NULL);
601 1904105 : Bfunction* bfunction = function->func_value()->get_decl();
602 1904105 : Btype* btype = this->type()->get_backend(context->gogo());
603 :
604 1904105 : Bexpression* binit;
605 1904105 : if (this->init_ == NULL)
606 : binit = NULL;
607 1693091 : else if (this->type_ == NULL)
608 832737 : binit = this->init_->get_backend(context);
609 : else
610 : {
611 860354 : Expression* init = Expression::convert_for_assignment(context->gogo(),
612 : this->type_,
613 : this->init_,
614 : this->location());
615 860354 : binit = init->get_backend(context);
616 : }
617 :
618 1693091 : if (binit != NULL)
619 1693091 : binit = context->backend()->convert_expression(btype, binit,
620 : this->location());
621 :
622 1904105 : unsigned int flags = 0;
623 1904105 : if (this->is_address_taken_)
624 43829 : flags |= Backend::variable_address_is_taken;
625 1904105 : Bstatement* statement;
626 1904105 : this->bvariable_ =
627 1904105 : context->backend()->temporary_variable(bfunction, context->bblock(),
628 : btype, binit, flags,
629 : this->location(), &statement);
630 1904105 : return statement;
631 : }
632 :
633 : // Return the backend variable.
634 :
635 : Bvariable*
636 3817044 : Temporary_statement::get_backend_variable(Translate_context* context) const
637 : {
638 3817044 : if (this->bvariable_ == NULL)
639 : {
640 0 : go_assert(saw_errors());
641 0 : return context->backend()->error_variable();
642 : }
643 : return this->bvariable_;
644 : }
645 :
646 : // Dump the AST represemtation for a temporary statement
647 :
648 : void
649 0 : Temporary_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
650 : {
651 0 : ast_dump_context->print_indent();
652 0 : ast_dump_context->dump_temp_variable_name(this);
653 0 : if (this->type_ != NULL)
654 : {
655 0 : ast_dump_context->ostream() << " ";
656 0 : ast_dump_context->dump_type(this->type_);
657 : }
658 0 : if (this->init_ != NULL)
659 : {
660 0 : ast_dump_context->ostream() << " = ";
661 0 : ast_dump_context->dump_expression(this->init_);
662 : }
663 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
664 0 : }
665 :
666 : // Make and initialize a temporary variable in BLOCK.
667 :
668 : Temporary_statement*
669 1907448 : Statement::make_temporary(Type* type, Expression* init,
670 : Location location)
671 : {
672 1907448 : return new Temporary_statement(type, init, location);
673 : }
674 :
675 : // Export a temporary statement.
676 :
677 : void
678 4501 : Temporary_statement::do_export_statement(Export_function_body* efb)
679 : {
680 4501 : unsigned int idx = efb->record_temporary(this);
681 4501 : char buf[100];
682 4501 : snprintf(buf, sizeof buf, "var $t%u", idx);
683 4501 : efb->write_c_string(buf);
684 4501 : if (this->type_ != NULL)
685 : {
686 3641 : efb->write_c_string(" ");
687 3641 : efb->write_type(this->type_);
688 : }
689 4501 : if (this->init_ != NULL)
690 : {
691 3924 : efb->write_c_string(" = ");
692 :
693 3924 : go_assert(efb->type_context() == NULL);
694 3924 : efb->set_type_context(this->type_);
695 :
696 3924 : this->init_->export_expression(efb);
697 :
698 3924 : efb->set_type_context(NULL);
699 : }
700 4501 : }
701 :
702 : // Import a temporary statement.
703 :
704 : Statement*
705 2661 : Temporary_statement::do_import(Import_function_body* ifb, Location loc)
706 : {
707 2661 : ifb->require_c_string("var ");
708 2661 : std::string id = ifb->read_identifier();
709 2661 : go_assert(id[0] == '$' && id[1] == 't');
710 2661 : const char *p = id.c_str();
711 2661 : char *end;
712 2661 : long idx = strtol(p + 2, &end, 10);
713 2661 : if (*end != '\0' || idx > 0x7fffffff)
714 : {
715 0 : if (!ifb->saw_error())
716 0 : go_error_at(loc,
717 : ("invalid export data for %qs: "
718 : "bad temporary statement index at %lu"),
719 0 : ifb->name().c_str(),
720 0 : static_cast<unsigned long>(ifb->off()));
721 0 : ifb->set_saw_error();
722 0 : return Statement::make_error_statement(loc);
723 : }
724 :
725 2661 : Type* type = NULL;
726 2661 : if (!ifb->match_c_string(" = "))
727 : {
728 2661 : ifb->require_c_string(" ");
729 2661 : type = ifb->read_type();
730 : }
731 2661 : Expression* init = NULL;
732 2661 : if (ifb->match_c_string(" = "))
733 : {
734 2309 : ifb->advance(3);
735 2309 : init = Expression::import_expression(ifb, loc);
736 : }
737 2661 : if (type == NULL && init == NULL)
738 : {
739 0 : if (!ifb->saw_error())
740 0 : go_error_at(loc,
741 : ("invalid export data for %qs: "
742 : "temporary statement has neither type nor init at %lu"),
743 0 : ifb->name().c_str(),
744 0 : static_cast<unsigned long>(ifb->off()));
745 0 : ifb->set_saw_error();
746 : return Statement::make_error_statement(loc);
747 : }
748 :
749 2661 : Temporary_statement* temp = Statement::make_temporary(type, init, loc);
750 :
751 2661 : ifb->record_temporary(temp, static_cast<unsigned int>(idx));
752 :
753 2661 : return temp;
754 2661 : }
755 :
756 : // The Move_subexpressions class is used to move all top-level
757 : // subexpressions of an expression. This is used for things like
758 : // index expressions in which we must evaluate the index value before
759 : // it can be changed by a multiple assignment.
760 :
761 16568 : class Move_subexpressions : public Traverse
762 : {
763 : public:
764 19017 : Move_subexpressions(int skip, Block* block)
765 19017 : : Traverse(traverse_expressions),
766 19017 : skip_(skip), block_(block)
767 : { }
768 :
769 : protected:
770 : int
771 : expression(Expression**);
772 :
773 : private:
774 : // The number of subexpressions to skip moving. This is used to
775 : // avoid moving the array itself, as we only need to move the index.
776 : int skip_;
777 : // The block where new temporary variables should be added.
778 : Block* block_;
779 : };
780 :
781 : int
782 23414 : Move_subexpressions::expression(Expression** pexpr)
783 : {
784 23414 : if (this->skip_ > 0)
785 2017 : --this->skip_;
786 21397 : else if ((*pexpr)->temporary_reference_expression() == NULL
787 21103 : && !(*pexpr)->is_nil_expression()
788 21089 : && !(*pexpr)->is_constant())
789 : {
790 19685 : Location loc = (*pexpr)->location();
791 19685 : Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
792 19685 : this->block_->add_statement(temp);
793 19685 : *pexpr = Expression::make_temporary_reference(temp, loc);
794 : }
795 : // We only need to move top-level subexpressions.
796 23414 : return TRAVERSE_SKIP_COMPONENTS;
797 : }
798 :
799 : // The Move_ordered_evals class is used to find any subexpressions of
800 : // an expression that have an evaluation order dependency. It creates
801 : // temporary variables to hold them.
802 :
803 84127 : class Move_ordered_evals : public Traverse
804 : {
805 : public:
806 202938 : Move_ordered_evals(Block* block)
807 202938 : : Traverse(traverse_expressions),
808 202938 : block_(block)
809 : { }
810 :
811 : protected:
812 : int
813 : expression(Expression**);
814 :
815 : private:
816 : // The block where new temporary variables should be added.
817 : Block* block_;
818 : };
819 :
820 : int
821 277244 : Move_ordered_evals::expression(Expression** pexpr)
822 : {
823 : // We have to look at subexpressions first.
824 277244 : if ((*pexpr)->traverse_subexpressions(this) == TRAVERSE_EXIT)
825 : return TRAVERSE_EXIT;
826 :
827 277244 : int i;
828 277244 : if ((*pexpr)->must_eval_subexpressions_in_order(&i))
829 : {
830 16568 : Move_subexpressions ms(i, this->block_);
831 16568 : if ((*pexpr)->traverse_subexpressions(&ms) == TRAVERSE_EXIT)
832 0 : return TRAVERSE_EXIT;
833 16568 : }
834 :
835 277244 : if ((*pexpr)->must_eval_in_order())
836 : {
837 667 : Call_expression* call = (*pexpr)->call_expression();
838 666 : if (call != NULL && call->is_multi_value_arg())
839 : {
840 : // A call expression which returns multiple results as an argument
841 : // to another call must be handled specially. We can't create a
842 : // temporary because there is no type to give it. Instead, group
843 : // the caller and this multi-valued call argument and use a temporary
844 : // variable to hold them.
845 0 : return TRAVERSE_SKIP_COMPONENTS;
846 : }
847 :
848 667 : Location loc = (*pexpr)->location();
849 667 : Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
850 667 : this->block_->add_statement(temp);
851 667 : *pexpr = Expression::make_temporary_reference(temp, loc);
852 : }
853 : return TRAVERSE_SKIP_COMPONENTS;
854 : }
855 :
856 : // Class Assignment_statement.
857 :
858 : // Traversal.
859 :
860 : int
861 18722813 : Assignment_statement::do_traverse(Traverse* traverse)
862 : {
863 18722813 : if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
864 : return TRAVERSE_EXIT;
865 18656969 : return this->traverse_expression(traverse, &this->rhs_);
866 : }
867 :
868 : // Lower an assignment to a map index expression to a runtime function
869 : // call. Mark some slice assignments as not requiring a write barrier.
870 :
871 : Statement*
872 1388224 : Assignment_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
873 : Statement_inserter*)
874 : {
875 1388224 : Map_index_expression* mie = this->lhs_->map_index_expression();
876 1388224 : if (mie != NULL)
877 : {
878 5656 : Location loc = this->location();
879 :
880 5656 : Expression* map = mie->map();
881 5656 : Map_type* mt = map->type()->map_type();
882 5656 : if (mt == NULL)
883 : {
884 0 : go_assert(saw_errors());
885 0 : return Statement::make_error_statement(loc);
886 : }
887 :
888 5656 : Block* b = new Block(enclosing, loc);
889 :
890 : // Move out any subexpressions on the left hand side to make
891 : // sure that functions are called in the required order.
892 5656 : Move_ordered_evals moe(b);
893 5656 : mie->traverse_subexpressions(&moe);
894 :
895 : // Copy the key into a temporary so that we can take its address
896 : // without pushing the value onto the heap.
897 :
898 : // var key_temp KEY_TYPE = MAP_INDEX
899 5656 : Temporary_statement* key_temp = Statement::make_temporary(mt->key_type(),
900 : mie->index(),
901 : loc);
902 5656 : b->add_statement(key_temp);
903 :
904 : // Copy the value into a temporary to ensure that it is
905 : // evaluated before we add the key to the map. This may matter
906 : // if the value is itself a reference to the map.
907 :
908 : // var val_temp VAL_TYPE = RHS
909 5656 : Temporary_statement* val_temp = Statement::make_temporary(mt->val_type(),
910 : this->rhs_,
911 : loc);
912 5656 : b->add_statement(val_temp);
913 :
914 : // *mapassign(TYPE, MAP, &key_temp) = RHS
915 5656 : Expression* a1 = Expression::make_type_descriptor(mt, loc);
916 5656 : Expression* a2 = mie->map();
917 5656 : Temporary_reference_expression* ref =
918 5656 : Expression::make_temporary_reference(key_temp, loc);
919 5656 : Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc);
920 5656 : Runtime::Function code;
921 5656 : Map_type::Map_alg alg = mt->algorithm(gogo);
922 5656 : switch (alg)
923 : {
924 323 : case Map_type::MAP_ALG_FAST32:
925 323 : {
926 323 : code = Runtime::MAPASSIGN_FAST32;
927 323 : Type* uint32_type = Type::lookup_integer_type("uint32");
928 323 : Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
929 323 : a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3,
930 : loc);
931 323 : a3 = Expression::make_dereference(a3,
932 : Expression::NIL_CHECK_NOT_NEEDED,
933 : loc);
934 323 : break;
935 : }
936 776 : case Map_type::MAP_ALG_FAST64:
937 776 : {
938 776 : code = Runtime::MAPASSIGN_FAST64;
939 776 : Type* uint64_type = Type::lookup_integer_type("uint64");
940 776 : Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
941 776 : a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3,
942 : loc);
943 776 : a3 = Expression::make_dereference(a3,
944 : Expression::NIL_CHECK_NOT_NEEDED,
945 : loc);
946 776 : break;
947 : }
948 593 : case Map_type::MAP_ALG_FAST32PTR:
949 593 : case Map_type::MAP_ALG_FAST64PTR:
950 593 : {
951 328 : code = (alg == Map_type::MAP_ALG_FAST32PTR
952 593 : ? Runtime::MAPASSIGN_FAST32PTR
953 : : Runtime::MAPASSIGN_FAST64PTR);
954 593 : Type* ptr_type =
955 593 : Type::make_pointer_type(Type::make_void_type());
956 593 : Type* ptr_ptr_type = Type::make_pointer_type(ptr_type);
957 593 : a3 = Expression::make_unsafe_cast(ptr_ptr_type, a3,
958 : loc);
959 593 : a3 = Expression::make_dereference(a3,
960 : Expression::NIL_CHECK_NOT_NEEDED,
961 : loc);
962 593 : break;
963 : }
964 : case Map_type::MAP_ALG_FASTSTR:
965 : code = Runtime::MAPASSIGN_FASTSTR;
966 : a3 = ref;
967 : break;
968 1309 : default:
969 1309 : code = Runtime::MAPASSIGN;
970 1309 : break;
971 : }
972 5656 : Expression* call = Runtime::make_call(gogo, code, loc, 3,
973 : a1, a2, a3);
974 5656 : Type* ptrval_type = Type::make_pointer_type(mt->val_type());
975 5656 : call = Expression::make_cast(ptrval_type, call, loc);
976 5656 : Expression* indir =
977 5656 : Expression::make_dereference(call, Expression::NIL_CHECK_NOT_NEEDED,
978 : loc);
979 5656 : ref = Expression::make_temporary_reference(val_temp, loc);
980 5656 : Statement* s = Statement::make_assignment(indir, ref, loc);
981 5656 : s->determine_types(gogo);
982 5656 : b->add_statement(s);
983 :
984 5656 : return Statement::make_block_statement(b, loc);
985 5656 : }
986 :
987 : // An assignment of the form s = s[:n] does not require a write
988 : // barrier, because the pointer value will not change.
989 1382568 : Array_index_expression* aie = this->rhs_->array_index_expression();
990 70177 : if (aie != NULL
991 70177 : && aie->end() != NULL
992 14092 : && Expression::is_same_variable(this->lhs_, aie->array()))
993 : {
994 8161 : Numeric_constant nc;
995 8161 : unsigned long ival;
996 8161 : if (aie->start()->numeric_constant_value(&nc)
997 6158 : && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID
998 14319 : && ival == 0)
999 4034 : this->omit_write_barrier_ = true;
1000 8161 : }
1001 1382568 : String_index_expression* sie = this->rhs_->string_index_expression();
1002 6799 : if (sie != NULL
1003 6799 : && sie->end() != NULL
1004 5973 : && Expression::is_same_variable(this->lhs_, sie->string()))
1005 : {
1006 3978 : Numeric_constant nc;
1007 3978 : unsigned long ival;
1008 3978 : if (sie->start()->numeric_constant_value(&nc)
1009 2917 : && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID
1010 6895 : && ival == 0)
1011 829 : this->omit_write_barrier_ = true;
1012 3978 : }
1013 :
1014 1382568 : return this;
1015 : }
1016 :
1017 : // Set types for the assignment.
1018 :
1019 : void
1020 1468632 : Assignment_statement::do_determine_types(Gogo* gogo)
1021 : {
1022 1468632 : this->lhs_->determine_type_no_context(gogo);
1023 1468632 : Type* rhs_context_type = this->lhs_->type();
1024 1468632 : if (rhs_context_type->is_sink_type())
1025 7388 : rhs_context_type = NULL;
1026 1468632 : Type_context context(rhs_context_type, false);
1027 1468632 : this->rhs_->determine_type(gogo, &context);
1028 1468632 : }
1029 :
1030 : // Check types for an assignment from RHS to LHS. Returns true if the
1031 : // assignment is OK.
1032 :
1033 : bool
1034 318331 : Assignment_statement::check_assignment_types(Expression* lhs,
1035 : Type* rhs_type,
1036 : Location loc)
1037 : {
1038 : // The left hand side must be either addressable, a map index
1039 : // expression, or the blank identifier.
1040 318331 : if (!lhs->is_addressable()
1041 33028 : && !Index_expression::is_map_index(lhs)
1042 345940 : && !lhs->is_sink_expression())
1043 : {
1044 8 : if (!lhs->type()->is_error())
1045 8 : go_error_at(lhs->location(), "invalid left hand side of assignment");
1046 8 : return false;
1047 : }
1048 :
1049 318323 : Type* lhs_type = lhs->type();
1050 :
1051 : // Check for invalid assignment of nil to the blank identifier.
1052 318323 : if (lhs_type->is_sink_type() && rhs_type->is_nil_type())
1053 : {
1054 3 : go_error_at(loc, "use of untyped nil");
1055 3 : return false;
1056 : }
1057 :
1058 318320 : std::string reason;
1059 318320 : if (!Type::are_assignable(lhs_type, rhs_type, &reason))
1060 : {
1061 96 : if (reason.empty())
1062 0 : go_error_at(loc, "incompatible types in assignment");
1063 : else
1064 96 : go_error_at(loc, "incompatible types in assignment (%s)",
1065 : reason.c_str());
1066 96 : return false;
1067 : }
1068 :
1069 318224 : if (lhs_type->is_error_type() || rhs_type->is_error_type())
1070 61 : return false;
1071 :
1072 : return true;
1073 318320 : }
1074 :
1075 : // Check types for an assignment.
1076 :
1077 : void
1078 193257 : Assignment_statement::do_check_types(Gogo*)
1079 : {
1080 193257 : if (!Assignment_statement::check_assignment_types(this->lhs_,
1081 193257 : this->rhs_->type(),
1082 : this->location()))
1083 159 : this->set_is_error();
1084 193257 : }
1085 :
1086 : void
1087 20287 : Assignment_statement::do_export_statement(Export_function_body* efb)
1088 : {
1089 20287 : this->lhs_->export_expression(efb);
1090 20287 : efb->write_c_string(" = ");
1091 20287 : this->rhs_->export_expression(efb);
1092 20287 : }
1093 :
1094 : // Flatten an assignment statement. We may need a temporary for
1095 : // interface conversion.
1096 :
1097 : Statement*
1098 1142087 : Assignment_statement::do_flatten(Gogo*, Named_object*, Block*,
1099 : Statement_inserter* inserter)
1100 : {
1101 1142087 : if (this->lhs_->is_error_expression()
1102 1142086 : || this->lhs_->type()->is_error_type()
1103 1142085 : || this->rhs_->is_error_expression()
1104 2283910 : || this->rhs_->type()->is_error_type())
1105 : {
1106 269 : go_assert(saw_errors());
1107 269 : return Statement::make_error_statement(this->location());
1108 : }
1109 :
1110 1141818 : if (!this->lhs_->is_sink_expression()
1111 1135239 : && !Type::are_identical(this->lhs_->type(), this->rhs_->type(),
1112 : Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
1113 : NULL)
1114 16722 : && this->rhs_->type()->interface_type() != NULL
1115 1141818 : && !this->rhs_->is_multi_eval_safe())
1116 : {
1117 0 : Temporary_statement* temp =
1118 0 : Statement::make_temporary(NULL, this->rhs_, this->location());
1119 0 : inserter->insert(temp);
1120 0 : this->rhs_ = Expression::make_temporary_reference(temp,
1121 : this->location());
1122 : }
1123 1141818 : return this;
1124 : }
1125 :
1126 : // Add explicit type conversions.
1127 :
1128 : void
1129 727201 : Assignment_statement::do_add_conversions()
1130 : {
1131 727201 : Type* lt = this->lhs_->type();
1132 727201 : Type* rt = this->rhs_->type();
1133 727201 : if (!Type::are_identical(lt, rt, 0, NULL)
1134 727201 : && lt->interface_type() != NULL)
1135 20556 : this->rhs_ = Expression::make_cast(lt, this->rhs_, this->location());
1136 727201 : }
1137 :
1138 : // Convert an assignment statement to the backend representation.
1139 :
1140 : Bstatement*
1141 1225071 : Assignment_statement::do_get_backend(Translate_context* context)
1142 : {
1143 1225071 : if (this->lhs_->is_sink_expression())
1144 : {
1145 4494 : Bexpression* rhs = this->rhs_->get_backend(context);
1146 4494 : Bfunction* bfunction = context->function()->func_value()->get_decl();
1147 4494 : return context->backend()->expression_statement(bfunction, rhs);
1148 : }
1149 :
1150 1220577 : Bexpression* lhs = this->lhs_->get_backend(context);
1151 1220577 : Expression* conv =
1152 1220577 : Expression::convert_for_assignment(context->gogo(), this->lhs_->type(),
1153 : this->rhs_, this->location());
1154 1220577 : Bexpression* rhs = conv->get_backend(context);
1155 1220577 : Bfunction* bfunction = context->function()->func_value()->get_decl();
1156 1220577 : return context->backend()->assignment_statement(bfunction, lhs, rhs,
1157 1220577 : this->location());
1158 : }
1159 :
1160 : // Dump the AST representation for an assignment statement.
1161 :
1162 : void
1163 0 : Assignment_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
1164 : const
1165 : {
1166 0 : ast_dump_context->print_indent();
1167 0 : ast_dump_context->dump_expression(this->lhs_);
1168 0 : ast_dump_context->ostream() << " = " ;
1169 0 : ast_dump_context->dump_expression(this->rhs_);
1170 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
1171 0 : }
1172 :
1173 : // Make an assignment statement.
1174 :
1175 : Assignment_statement*
1176 1341151 : Statement::make_assignment(Expression* lhs, Expression* rhs,
1177 : Location location)
1178 : {
1179 1341151 : Temporary_reference_expression* tre = lhs->temporary_reference_expression();
1180 214339 : if (tre != NULL)
1181 214339 : tre->statement()->set_assigned();
1182 1341151 : return new Assignment_statement(lhs, rhs, location);
1183 : }
1184 :
1185 : // An assignment operation statement.
1186 :
1187 : class Assignment_operation_statement : public Statement
1188 : {
1189 : public:
1190 84155 : Assignment_operation_statement(Operator op, Expression* lhs, Expression* rhs,
1191 : Location location)
1192 84155 : : Statement(STATEMENT_ASSIGNMENT_OPERATION, location),
1193 168310 : op_(op), lhs_(lhs), rhs_(rhs)
1194 : { }
1195 :
1196 : protected:
1197 : int
1198 : do_traverse(Traverse*);
1199 :
1200 : void
1201 : do_determine_types(Gogo*);
1202 :
1203 : void
1204 : do_check_types(Gogo*);
1205 :
1206 : Statement*
1207 : do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1208 :
1209 : Bstatement*
1210 0 : do_get_backend(Translate_context*)
1211 0 : { go_unreachable(); }
1212 :
1213 : void
1214 : do_dump_statement(Ast_dump_context*) const;
1215 :
1216 : private:
1217 : Operator
1218 : get_binop();
1219 :
1220 : // The operator (OPERATOR_PLUSEQ, etc.).
1221 : Operator op_;
1222 : // Left hand side.
1223 : Expression* lhs_;
1224 : // Right hand side.
1225 : Expression* rhs_;
1226 : };
1227 :
1228 : // Traversal.
1229 :
1230 : int
1231 185363 : Assignment_operation_statement::do_traverse(Traverse* traverse)
1232 : {
1233 185363 : if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
1234 : return TRAVERSE_EXIT;
1235 185363 : return this->traverse_expression(traverse, &this->rhs_);
1236 : }
1237 :
1238 : void
1239 25309 : Assignment_operation_statement::do_determine_types(Gogo* gogo)
1240 : {
1241 25309 : this->lhs_->determine_type_no_context(gogo);
1242 25309 : Type* rhs_context_type = this->lhs_->type();
1243 25309 : if (rhs_context_type->is_sink_type())
1244 0 : rhs_context_type = NULL;
1245 25309 : Type_context context(rhs_context_type, false);
1246 25309 : this->rhs_->determine_type(gogo, &context);
1247 25309 : }
1248 :
1249 : // Get the binary operator from the assignment operator.
1250 :
1251 : Operator
1252 107708 : Assignment_operation_statement::get_binop()
1253 : {
1254 107708 : switch (this->op_)
1255 : {
1256 : case OPERATOR_PLUSEQ:
1257 : return OPERATOR_PLUS;
1258 : case OPERATOR_MINUSEQ:
1259 : return OPERATOR_MINUS;
1260 : case OPERATOR_OREQ:
1261 : return OPERATOR_OR;
1262 : case OPERATOR_XOREQ:
1263 : return OPERATOR_XOR;
1264 : case OPERATOR_MULTEQ:
1265 : return OPERATOR_MULT;
1266 : case OPERATOR_DIVEQ:
1267 : return OPERATOR_DIV;
1268 : case OPERATOR_MODEQ:
1269 : return OPERATOR_MOD;
1270 : case OPERATOR_LSHIFTEQ:
1271 : return OPERATOR_LSHIFT;
1272 : case OPERATOR_RSHIFTEQ:
1273 : return OPERATOR_RSHIFT;
1274 : case OPERATOR_ANDEQ:
1275 : return OPERATOR_AND;
1276 : case OPERATOR_BITCLEAREQ:
1277 : return OPERATOR_BITCLEAR;
1278 0 : default:
1279 0 : go_unreachable();
1280 : }
1281 : }
1282 :
1283 : void
1284 25309 : Assignment_operation_statement::do_check_types(Gogo*)
1285 : {
1286 25309 : if (this->lhs_->is_sink_expression())
1287 : {
1288 0 : this->report_error(_("cannot use %<_%> as value"));
1289 0 : return;
1290 : }
1291 :
1292 :
1293 25309 : Type* lhs_type = this->lhs_->type();
1294 25309 : Type* rhs_type = this->rhs_->type();
1295 :
1296 25309 : if (!this->lhs_->is_addressable()
1297 25309 : && !Index_expression::is_map_index(this->lhs_))
1298 : {
1299 0 : if (!lhs_type->is_error())
1300 0 : this->report_error(_("invalid left hand side of assignment"));
1301 0 : this->set_is_error();
1302 0 : return;
1303 : }
1304 :
1305 25309 : if (this->op_ != OPERATOR_LSHIFTEQ && this->op_ != OPERATOR_RSHIFTEQ)
1306 : {
1307 23581 : if (!Type::are_compatible_for_binop(lhs_type, rhs_type))
1308 : {
1309 0 : this->report_error(_("incompatible type in binary expression"));
1310 0 : return;
1311 : }
1312 23581 : if (!Binary_expression::check_operator_type(this->get_binop(), lhs_type,
1313 : rhs_type, this->location()))
1314 : {
1315 1 : this->set_is_error();
1316 1 : return;
1317 : }
1318 23580 : if (this->op_ == OPERATOR_DIVEQ || this->op_ == OPERATOR_MODEQ)
1319 : {
1320 461 : Numeric_constant rconst;
1321 461 : unsigned long rval;
1322 461 : if (lhs_type->integer_type() != NULL
1323 370 : && this->rhs_->numeric_constant_value(&rconst)
1324 332 : && rconst.to_unsigned_long(&rval) == Numeric_constant::NC_UL_VALID
1325 332 : && rval == 0)
1326 : {
1327 0 : this->report_error(_("integer division by zero"));
1328 0 : return;
1329 : }
1330 461 : }
1331 : }
1332 : else
1333 : {
1334 1728 : if (lhs_type->integer_type() == NULL)
1335 : {
1336 0 : this->report_error(_("shift of non-integer operand"));
1337 0 : return;
1338 : }
1339 :
1340 1728 : if (rhs_type->is_string_type()
1341 1728 : || (!rhs_type->is_abstract()
1342 1728 : && rhs_type->integer_type() == NULL))
1343 : {
1344 0 : this->report_error(_("shift count not integer"));
1345 0 : return;
1346 : }
1347 :
1348 1728 : Numeric_constant nc;
1349 1728 : if (this->rhs_->numeric_constant_value(&nc))
1350 : {
1351 1462 : mpz_t val;
1352 1462 : if (!nc.to_int(&val))
1353 : {
1354 0 : this->report_error(_("shift count not integer"));
1355 0 : return;
1356 : }
1357 1462 : if (mpz_sgn(val) < 0)
1358 0 : this->report_error(_("negative shift count"));
1359 1462 : mpz_clear(val);
1360 : }
1361 1728 : }
1362 : }
1363 :
1364 : // Lower an assignment operation statement to a regular assignment
1365 : // statement.
1366 :
1367 : Statement*
1368 84127 : Assignment_operation_statement::do_lower(Gogo* gogo, Named_object*,
1369 : Block* enclosing, Statement_inserter*)
1370 : {
1371 84127 : Location loc = this->location();
1372 :
1373 : // We have to evaluate the left hand side expression only once. We
1374 : // do this by moving out any expression with side effects.
1375 84127 : Block* b = new Block(enclosing, loc);
1376 84127 : Move_ordered_evals moe(b);
1377 84127 : this->lhs_->traverse_subexpressions(&moe);
1378 :
1379 : // We can still be left with subexpressions that have to be loaded
1380 : // even if they don't have side effects themselves, in case the RHS
1381 : // changes variables named on the LHS.
1382 84127 : int i;
1383 84127 : if (this->lhs_->must_eval_subexpressions_in_order(&i))
1384 : {
1385 2449 : Move_subexpressions ms(i, b);
1386 2449 : this->lhs_->traverse_subexpressions(&ms);
1387 2449 : }
1388 :
1389 84127 : Expression* lval = this->lhs_->copy();
1390 :
1391 84127 : Expression* binop = Expression::make_binary(this->get_binop(), lval,
1392 : this->rhs_, loc);
1393 84127 : Statement* s = Statement::make_assignment(this->lhs_, binop, loc);
1394 84127 : s->determine_types(gogo);
1395 84127 : if (b->statements()->empty())
1396 : {
1397 75389 : delete b;
1398 75389 : return s;
1399 : }
1400 : else
1401 : {
1402 8738 : b->add_statement(s);
1403 8738 : return Statement::make_block_statement(b, loc);
1404 : }
1405 84127 : }
1406 :
1407 : // Dump the AST representation for an assignment operation statement
1408 :
1409 : void
1410 0 : Assignment_operation_statement::do_dump_statement(
1411 : Ast_dump_context* ast_dump_context) const
1412 : {
1413 0 : ast_dump_context->print_indent();
1414 0 : ast_dump_context->dump_expression(this->lhs_);
1415 0 : ast_dump_context->dump_operator(this->op_);
1416 0 : ast_dump_context->dump_expression(this->rhs_);
1417 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
1418 0 : }
1419 :
1420 : // Make an assignment operation statement.
1421 :
1422 : Statement*
1423 84155 : Statement::make_assignment_operation(Operator op, Expression* lhs,
1424 : Expression* rhs, Location location)
1425 : {
1426 84155 : return new Assignment_operation_statement(op, lhs, rhs, location);
1427 : }
1428 :
1429 : // A tuple assignment statement. This differs from an assignment
1430 : // statement in that the right-hand-side expressions are evaluated in
1431 : // parallel.
1432 :
1433 : class Tuple_assignment_statement : public Statement
1434 : {
1435 : public:
1436 103919 : Tuple_assignment_statement(Expression_list* lhs, Expression_list* rhs,
1437 : Location location)
1438 103919 : : Statement(STATEMENT_TUPLE_ASSIGNMENT, location),
1439 207838 : lhs_(lhs), rhs_(rhs)
1440 : { }
1441 :
1442 : protected:
1443 : int
1444 : do_traverse(Traverse* traverse);
1445 :
1446 : void
1447 : do_determine_types(Gogo*);
1448 :
1449 : void
1450 : do_check_types(Gogo*);
1451 :
1452 : Statement*
1453 : do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1454 :
1455 : Bstatement*
1456 0 : do_get_backend(Translate_context*)
1457 0 : { go_unreachable(); }
1458 :
1459 : void
1460 : do_dump_statement(Ast_dump_context*) const;
1461 :
1462 : private:
1463 : // Left hand side--a list of lvalues.
1464 : Expression_list* lhs_;
1465 : // Right hand side--a list of rvalues.
1466 : Expression_list* rhs_;
1467 : };
1468 :
1469 : // Traversal.
1470 :
1471 : int
1472 214525 : Tuple_assignment_statement::do_traverse(Traverse* traverse)
1473 : {
1474 214525 : if (this->traverse_expression_list(traverse, this->lhs_) == TRAVERSE_EXIT)
1475 : return TRAVERSE_EXIT;
1476 214525 : return this->traverse_expression_list(traverse, this->rhs_);
1477 : }
1478 :
1479 : void
1480 126171 : Tuple_assignment_statement::do_determine_types(Gogo* gogo)
1481 : {
1482 126171 : Expression_list::iterator pr = this->rhs_->begin();
1483 126171 : for (Expression_list::iterator pl = this->lhs_->begin();
1484 391441 : pl != this->lhs_->end();
1485 265270 : ++pl, ++pr)
1486 : {
1487 265270 : go_assert(pr != this->rhs_->end());
1488 265270 : (*pl)->determine_type_no_context(gogo);
1489 265270 : Type* rhs_context_type = (*pl)->type();
1490 265270 : if (rhs_context_type->is_sink_type())
1491 36878 : rhs_context_type = NULL;
1492 265270 : Type_context context(rhs_context_type, false);
1493 265270 : (*pr)->determine_type(gogo, &context);
1494 : }
1495 126171 : go_assert(pr == this->rhs_->end());
1496 126171 : }
1497 :
1498 : void
1499 27653 : Tuple_assignment_statement::do_check_types(Gogo*)
1500 : {
1501 27653 : Expression_list::iterator pr = this->rhs_->begin();
1502 27653 : for (Expression_list::iterator pl = this->lhs_->begin();
1503 86520 : pl != this->lhs_->end();
1504 58867 : ++pl, ++pr)
1505 : {
1506 58867 : go_assert(pr != this->rhs_->end());
1507 58867 : if (!Assignment_statement::check_assignment_types(*pl, (*pr)->type(),
1508 : this->location()))
1509 8 : this->set_is_error();
1510 : }
1511 27653 : go_assert(pr == this->rhs_->end());
1512 27653 : }
1513 :
1514 : // Lower a tuple assignment. We use temporary variables to split it
1515 : // up into a set of single assignments.
1516 :
1517 : Statement*
1518 103913 : Tuple_assignment_statement::do_lower(Gogo* gogo, Named_object*,
1519 : Block* enclosing, Statement_inserter*)
1520 : {
1521 103913 : Location loc = this->location();
1522 :
1523 103913 : if (this->classification() == STATEMENT_ERROR)
1524 0 : return Statement::make_error_statement(loc);
1525 :
1526 103913 : Block* b = new Block(enclosing, loc);
1527 :
1528 : // First move out any subexpressions on the left hand side. The
1529 : // right hand side will be evaluated in the required order anyhow.
1530 103913 : Move_ordered_evals moe(b);
1531 324664 : for (Expression_list::iterator plhs = this->lhs_->begin();
1532 324664 : plhs != this->lhs_->end();
1533 220751 : ++plhs)
1534 220751 : Expression::traverse(&*plhs, &moe);
1535 :
1536 103913 : std::vector<Temporary_statement*> temps;
1537 103913 : temps.reserve(this->lhs_->size());
1538 :
1539 103913 : Expression_list::const_iterator prhs = this->rhs_->begin();
1540 103913 : for (Expression_list::const_iterator plhs = this->lhs_->begin();
1541 324664 : plhs != this->lhs_->end();
1542 220751 : ++plhs, ++prhs)
1543 : {
1544 220751 : go_assert(prhs != this->rhs_->end());
1545 :
1546 220751 : if ((*plhs)->is_error_expression()
1547 220751 : || (*plhs)->type()->is_error()
1548 220750 : || (*prhs)->is_error_expression()
1549 441495 : || (*prhs)->type()->is_error())
1550 20510 : continue;
1551 :
1552 220744 : if ((*plhs)->is_sink_expression())
1553 : {
1554 20503 : if ((*prhs)->type()->is_nil_type())
1555 0 : this->report_error(_("use of untyped nil"));
1556 : else
1557 20503 : b->add_statement(Statement::make_statement(*prhs, true));
1558 20503 : continue;
1559 : }
1560 :
1561 200241 : Temporary_statement* temp = Statement::make_temporary((*plhs)->type(),
1562 200241 : *prhs, loc);
1563 200241 : b->add_statement(temp);
1564 200241 : temps.push_back(temp);
1565 :
1566 : }
1567 103913 : go_assert(prhs == this->rhs_->end());
1568 :
1569 103913 : prhs = this->rhs_->begin();
1570 103913 : std::vector<Temporary_statement*>::const_iterator ptemp = temps.begin();
1571 103913 : for (Expression_list::const_iterator plhs = this->lhs_->begin();
1572 324664 : plhs != this->lhs_->end();
1573 220751 : ++plhs, ++prhs)
1574 : {
1575 220751 : if ((*plhs)->is_error_expression()
1576 220751 : || (*plhs)->type()->is_error()
1577 220750 : || (*prhs)->is_error_expression()
1578 441495 : || (*prhs)->type()->is_error())
1579 7 : continue;
1580 :
1581 220744 : if ((*plhs)->is_sink_expression())
1582 20503 : continue;
1583 :
1584 200241 : Expression* ref = Expression::make_temporary_reference(*ptemp, loc);
1585 200241 : Statement* s = Statement::make_assignment(*plhs, ref, loc);
1586 200241 : s->determine_types(gogo);
1587 200241 : b->add_statement(s);
1588 200241 : ++ptemp;
1589 : }
1590 103913 : go_assert(ptemp == temps.end() || saw_errors());
1591 :
1592 103913 : return Statement::make_block_statement(b, loc);
1593 103913 : }
1594 :
1595 : // Dump the AST representation for a tuple assignment statement.
1596 :
1597 : void
1598 0 : Tuple_assignment_statement::do_dump_statement(
1599 : Ast_dump_context* ast_dump_context) const
1600 : {
1601 0 : ast_dump_context->print_indent();
1602 0 : ast_dump_context->dump_expression_list(this->lhs_);
1603 0 : ast_dump_context->ostream() << " = ";
1604 0 : ast_dump_context->dump_expression_list(this->rhs_);
1605 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
1606 0 : }
1607 :
1608 : // Make a tuple assignment statement.
1609 :
1610 : Statement*
1611 103919 : Statement::make_tuple_assignment(Expression_list* lhs, Expression_list* rhs,
1612 : Location location)
1613 : {
1614 103919 : return new Tuple_assignment_statement(lhs, rhs, location);
1615 : }
1616 :
1617 : // A tuple assignment from a map index expression.
1618 : // v, ok = m[k]
1619 :
1620 : class Tuple_map_assignment_statement : public Statement
1621 : {
1622 : public:
1623 2365 : Tuple_map_assignment_statement(Expression* val, Expression* present,
1624 : Expression* map_index,
1625 : Location location)
1626 2365 : : Statement(STATEMENT_TUPLE_MAP_ASSIGNMENT, location),
1627 4730 : val_(val), present_(present), map_index_(map_index)
1628 : { }
1629 :
1630 : protected:
1631 : int
1632 : do_traverse(Traverse* traverse);
1633 :
1634 : void
1635 : do_determine_types(Gogo*);
1636 :
1637 : void
1638 : do_check_types(Gogo*);
1639 :
1640 : Statement*
1641 : do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1642 :
1643 : Bstatement*
1644 0 : do_get_backend(Translate_context*)
1645 0 : { go_unreachable(); }
1646 :
1647 : void
1648 : do_dump_statement(Ast_dump_context*) const;
1649 :
1650 : private:
1651 : // Lvalue which receives the value from the map.
1652 : Expression* val_;
1653 : // Lvalue which receives whether the key value was present.
1654 : Expression* present_;
1655 : // The map index expression.
1656 : Expression* map_index_;
1657 : };
1658 :
1659 : // Traversal.
1660 :
1661 : int
1662 11825 : Tuple_map_assignment_statement::do_traverse(Traverse* traverse)
1663 : {
1664 11825 : if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
1665 11825 : || this->traverse_expression(traverse, &this->present_) == TRAVERSE_EXIT)
1666 0 : return TRAVERSE_EXIT;
1667 11825 : return this->traverse_expression(traverse, &this->map_index_);
1668 : }
1669 :
1670 : void
1671 2365 : Tuple_map_assignment_statement::do_determine_types(Gogo* gogo)
1672 : {
1673 2365 : this->val_->determine_type_no_context(gogo);
1674 2365 : this->present_->determine_type_no_context(gogo);
1675 2365 : this->map_index_->determine_type_no_context(gogo);
1676 2365 : }
1677 :
1678 : void
1679 2365 : Tuple_map_assignment_statement::do_check_types(Gogo*)
1680 : {
1681 2365 : Expression* map_expr = this->map_index_;
1682 2365 : Map_type* map_type;
1683 2365 : if (map_expr->map_index_expression() != NULL)
1684 0 : map_type = map_expr->map_index_expression()->get_map_type();
1685 2365 : else if (map_expr->index_expression() != NULL)
1686 2365 : map_type = map_expr->index_expression()->left()->type()->map_type();
1687 : else
1688 : {
1689 0 : this->report_error(_("expected map index on right hand side"));
1690 0 : return;
1691 : }
1692 2365 : if (map_type == NULL || map_type->is_error())
1693 : {
1694 0 : go_assert(saw_errors());
1695 0 : this->set_is_error();
1696 0 : return;
1697 : }
1698 :
1699 2365 : if (!Assignment_statement::check_assignment_types(this->val_,
1700 : map_type->val_type(),
1701 : this->location()))
1702 0 : this->set_is_error();
1703 2365 : if (!Assignment_statement::check_assignment_types(this->present_,
1704 : Type::make_boolean_type(),
1705 : this->location()))
1706 0 : this->set_is_error();
1707 : }
1708 :
1709 : // Lower a tuple map assignment.
1710 :
1711 : Statement*
1712 2365 : Tuple_map_assignment_statement::do_lower(Gogo* gogo, Named_object*,
1713 : Block* enclosing, Statement_inserter*)
1714 : {
1715 2365 : Location loc = this->location();
1716 :
1717 2365 : if (this->classification() == STATEMENT_ERROR)
1718 0 : return Statement::make_error_statement(loc);
1719 :
1720 2365 : Map_index_expression* map_index = this->map_index_->map_index_expression();
1721 0 : go_assert(map_index != NULL);
1722 2365 : Map_type* map_type = map_index->get_map_type();
1723 2365 : go_assert(map_type != NULL);
1724 :
1725 : // Avoid copy for string([]byte) conversions used in map keys.
1726 : // mapaccess doesn't keep the reference, so this is safe.
1727 2365 : Type_conversion_expression* ce = map_index->index()->conversion_expression();
1728 31 : if (ce != NULL && ce->type()->is_string_type()
1729 26 : && ce->expr()->type()->is_slice_type())
1730 26 : ce->set_no_copy(true);
1731 :
1732 2365 : Block* b = new Block(enclosing, loc);
1733 :
1734 : // Move out any subexpressions to make sure that functions are
1735 : // called in the required order.
1736 2365 : Move_ordered_evals moe(b);
1737 2365 : this->val_->traverse_subexpressions(&moe);
1738 2365 : this->present_->traverse_subexpressions(&moe);
1739 :
1740 : // Copy the key value into a temporary so that we can take its
1741 : // address without pushing the value onto the heap.
1742 :
1743 : // var key_temp KEY_TYPE = MAP_INDEX
1744 2365 : Temporary_statement* key_temp =
1745 2365 : Statement::make_temporary(map_type->key_type(), map_index->index(), loc);
1746 2365 : b->add_statement(key_temp);
1747 :
1748 : // var val_ptr_temp *VAL_TYPE
1749 2365 : Type* val_ptr_type = Type::make_pointer_type(map_type->val_type());
1750 2365 : Temporary_statement* val_ptr_temp = Statement::make_temporary(val_ptr_type,
1751 : NULL, loc);
1752 2365 : b->add_statement(val_ptr_temp);
1753 :
1754 : // var present_temp bool
1755 2365 : Temporary_statement* present_temp =
1756 4730 : Statement::make_temporary((this->present_->type()->is_boolean_type()
1757 2337 : ? this->present_->type()
1758 28 : : Type::lookup_bool_type()),
1759 : NULL, loc);
1760 2365 : b->add_statement(present_temp);
1761 :
1762 : // val_ptr_temp, present_temp = mapaccess2(DESCRIPTOR, MAP, &key_temp)
1763 2365 : Expression* a1 = Expression::make_type_descriptor(map_type, loc);
1764 2365 : Expression* a2 = map_index->map();
1765 2365 : Temporary_reference_expression* ref =
1766 2365 : Expression::make_temporary_reference(key_temp, loc);
1767 2365 : Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc);
1768 2365 : Expression* a4 = map_type->fat_zero_value(gogo);
1769 2365 : Call_expression* call;
1770 2365 : if (a4 == NULL)
1771 : {
1772 2362 : Runtime::Function code;
1773 2362 : Map_type::Map_alg alg = map_type->algorithm(gogo);
1774 2362 : switch (alg)
1775 : {
1776 261 : case Map_type::MAP_ALG_FAST32:
1777 261 : case Map_type::MAP_ALG_FAST32PTR:
1778 261 : {
1779 261 : code = Runtime::MAPACCESS2_FAST32;
1780 261 : Type* uint32_type = Type::lookup_integer_type("uint32");
1781 261 : Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
1782 261 : a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3,
1783 : loc);
1784 261 : a3 = Expression::make_dereference(a3,
1785 : Expression::NIL_CHECK_NOT_NEEDED,
1786 : loc);
1787 261 : break;
1788 : }
1789 299 : case Map_type::MAP_ALG_FAST64:
1790 299 : case Map_type::MAP_ALG_FAST64PTR:
1791 299 : {
1792 299 : code = Runtime::MAPACCESS2_FAST64;
1793 299 : Type* uint64_type = Type::lookup_integer_type("uint64");
1794 299 : Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
1795 299 : a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3,
1796 : loc);
1797 299 : a3 = Expression::make_dereference(a3,
1798 : Expression::NIL_CHECK_NOT_NEEDED,
1799 : loc);
1800 299 : break;
1801 : }
1802 : case Map_type::MAP_ALG_FASTSTR:
1803 : code = Runtime::MAPACCESS2_FASTSTR;
1804 : a3 = ref;
1805 : break;
1806 523 : default:
1807 523 : code = Runtime::MAPACCESS2;
1808 523 : break;
1809 : }
1810 2362 : call = Runtime::make_call(gogo, code, loc, 3, a1, a2, a3);
1811 : }
1812 : else
1813 3 : call = Runtime::make_call(gogo, Runtime::MAPACCESS2_FAT, loc, 4,
1814 : a1, a2, a3, a4);
1815 2365 : ref = Expression::make_temporary_reference(val_ptr_temp, loc);
1816 2365 : ref->set_is_lvalue();
1817 2365 : Expression* res = Expression::make_call_result(call, 0);
1818 2365 : res = Expression::make_unsafe_cast(val_ptr_type, res, loc);
1819 2365 : Statement* s = Statement::make_assignment(ref, res, loc);
1820 2365 : s->determine_types(gogo);
1821 2365 : b->add_statement(s);
1822 2365 : ref = Expression::make_temporary_reference(present_temp, loc);
1823 2365 : ref->set_is_lvalue();
1824 2365 : res = Expression::make_call_result(call, 1);
1825 2365 : s = Statement::make_assignment(ref, res, loc);
1826 2365 : s->determine_types(gogo);
1827 2365 : b->add_statement(s);
1828 :
1829 : // val = *val__ptr_temp
1830 2365 : ref = Expression::make_temporary_reference(val_ptr_temp, loc);
1831 2365 : Expression* ind =
1832 2365 : Expression::make_dereference(ref, Expression::NIL_CHECK_NOT_NEEDED, loc);
1833 2365 : s = Statement::make_assignment(this->val_, ind, loc);
1834 2365 : s->determine_types(gogo);
1835 2365 : b->add_statement(s);
1836 :
1837 : // present = present_temp
1838 2365 : ref = Expression::make_temporary_reference(present_temp, loc);
1839 2365 : s = Statement::make_assignment(this->present_, ref, loc);
1840 2365 : s->determine_types(gogo);
1841 2365 : b->add_statement(s);
1842 :
1843 2365 : return Statement::make_block_statement(b, loc);
1844 2365 : }
1845 :
1846 : // Dump the AST representation for a tuple map assignment statement.
1847 :
1848 : void
1849 0 : Tuple_map_assignment_statement::do_dump_statement(
1850 : Ast_dump_context* ast_dump_context) const
1851 : {
1852 0 : ast_dump_context->print_indent();
1853 0 : ast_dump_context->dump_expression(this->val_);
1854 0 : ast_dump_context->ostream() << ", ";
1855 0 : ast_dump_context->dump_expression(this->present_);
1856 0 : ast_dump_context->ostream() << " = ";
1857 0 : ast_dump_context->dump_expression(this->map_index_);
1858 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
1859 0 : }
1860 :
1861 : // Make a map assignment statement which returns a pair of values.
1862 :
1863 : Statement*
1864 2365 : Statement::make_tuple_map_assignment(Expression* val, Expression* present,
1865 : Expression* map_index,
1866 : Location location)
1867 : {
1868 2365 : return new Tuple_map_assignment_statement(val, present, map_index, location);
1869 : }
1870 :
1871 : // A tuple assignment from a receive statement.
1872 :
1873 : class Tuple_receive_assignment_statement : public Statement
1874 : {
1875 : public:
1876 186 : Tuple_receive_assignment_statement(Expression* val, Expression* closed,
1877 : Expression* channel, Location location)
1878 186 : : Statement(STATEMENT_TUPLE_RECEIVE_ASSIGNMENT, location),
1879 372 : val_(val), closed_(closed), channel_(channel)
1880 : { }
1881 :
1882 : protected:
1883 : int
1884 : do_traverse(Traverse* traverse);
1885 :
1886 : void
1887 : do_determine_types(Gogo*);
1888 :
1889 : void
1890 : do_check_types(Gogo*);
1891 :
1892 : Statement*
1893 : do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
1894 :
1895 : Bstatement*
1896 0 : do_get_backend(Translate_context*)
1897 0 : { go_unreachable(); }
1898 :
1899 : void
1900 : do_dump_statement(Ast_dump_context*) const;
1901 :
1902 : private:
1903 : // Lvalue which receives the value from the channel.
1904 : Expression* val_;
1905 : // Lvalue which receives whether the channel is closed.
1906 : Expression* closed_;
1907 : // The channel on which we receive the value.
1908 : Expression* channel_;
1909 : };
1910 :
1911 : // Traversal.
1912 :
1913 : int
1914 505 : Tuple_receive_assignment_statement::do_traverse(Traverse* traverse)
1915 : {
1916 505 : if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
1917 505 : || this->traverse_expression(traverse, &this->closed_) == TRAVERSE_EXIT)
1918 0 : return TRAVERSE_EXIT;
1919 505 : return this->traverse_expression(traverse, &this->channel_);
1920 : }
1921 :
1922 : void
1923 287 : Tuple_receive_assignment_statement::do_determine_types(Gogo* gogo)
1924 : {
1925 287 : this->val_->determine_type_no_context(gogo);
1926 287 : this->closed_->determine_type_no_context(gogo);
1927 287 : this->channel_->determine_type_no_context(gogo);
1928 287 : }
1929 :
1930 : void
1931 80 : Tuple_receive_assignment_statement::do_check_types(Gogo*)
1932 : {
1933 80 : Channel_type* ct = this->channel_->type()->channel_type();
1934 80 : if (ct == NULL)
1935 : {
1936 0 : this->report_error(_("expected channel"));
1937 0 : return;
1938 : }
1939 80 : if (!ct->may_receive())
1940 : {
1941 1 : this->report_error(_("invalid receive on send-only channel"));
1942 1 : return;
1943 : }
1944 :
1945 79 : if (!Assignment_statement::check_assignment_types(this->val_,
1946 : ct->element_type(),
1947 : this->location()))
1948 0 : this->set_is_error();
1949 79 : if (!Assignment_statement::check_assignment_types(this->closed_,
1950 : Type::make_boolean_type(),
1951 : this->location()))
1952 0 : this->set_is_error();
1953 : }
1954 :
1955 : // Lower to a function call.
1956 :
1957 : Statement*
1958 185 : Tuple_receive_assignment_statement::do_lower(Gogo* gogo, Named_object*,
1959 : Block* enclosing,
1960 : Statement_inserter*)
1961 : {
1962 185 : Location loc = this->location();
1963 :
1964 185 : if (this->classification() == STATEMENT_ERROR)
1965 0 : return Statement::make_error_statement(loc);
1966 :
1967 185 : Channel_type* channel_type = this->channel_->type()->channel_type();
1968 185 : go_assert(channel_type != NULL && channel_type->may_receive());
1969 :
1970 185 : Block* b = new Block(enclosing, loc);
1971 :
1972 : // Make sure that any subexpressions on the left hand side are
1973 : // evaluated in the right order.
1974 185 : Move_ordered_evals moe(b);
1975 185 : this->val_->traverse_subexpressions(&moe);
1976 185 : this->closed_->traverse_subexpressions(&moe);
1977 :
1978 : // var val_temp ELEMENT_TYPE
1979 185 : Temporary_statement* val_temp =
1980 185 : Statement::make_temporary(channel_type->element_type(), NULL, loc);
1981 185 : b->add_statement(val_temp);
1982 :
1983 : // var closed_temp bool
1984 185 : Temporary_statement* closed_temp =
1985 370 : Statement::make_temporary((this->closed_->type()->is_boolean_type()
1986 182 : ? this->closed_->type()
1987 3 : : Type::lookup_bool_type()),
1988 : NULL, loc);
1989 185 : b->add_statement(closed_temp);
1990 :
1991 : // closed_temp = chanrecv2(channel, &val_temp)
1992 185 : Temporary_reference_expression* ref =
1993 185 : Expression::make_temporary_reference(val_temp, loc);
1994 185 : Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
1995 185 : Expression* call = Runtime::make_call(gogo, Runtime::CHANRECV2,
1996 : loc, 2, this->channel_, p2);
1997 185 : ref = Expression::make_temporary_reference(closed_temp, loc);
1998 185 : ref->set_is_lvalue();
1999 185 : Statement* s = Statement::make_assignment(ref, call, loc);
2000 185 : s->determine_types(gogo);
2001 185 : b->add_statement(s);
2002 :
2003 : // val = val_temp
2004 185 : ref = Expression::make_temporary_reference(val_temp, loc);
2005 185 : s = Statement::make_assignment(this->val_, ref, loc);
2006 185 : s->determine_types(gogo);
2007 185 : b->add_statement(s);
2008 :
2009 : // closed = closed_temp
2010 185 : ref = Expression::make_temporary_reference(closed_temp, loc);
2011 185 : s = Statement::make_assignment(this->closed_, ref, loc);
2012 185 : s->determine_types(gogo);
2013 185 : b->add_statement(s);
2014 :
2015 185 : return Statement::make_block_statement(b, loc);
2016 185 : }
2017 :
2018 : // Dump the AST representation for a tuple receive statement.
2019 :
2020 : void
2021 0 : Tuple_receive_assignment_statement::do_dump_statement(
2022 : Ast_dump_context* ast_dump_context) const
2023 : {
2024 0 : ast_dump_context->print_indent();
2025 0 : ast_dump_context->dump_expression(this->val_);
2026 0 : ast_dump_context->ostream() << ", ";
2027 0 : ast_dump_context->dump_expression(this->closed_);
2028 0 : ast_dump_context->ostream() << " <- ";
2029 0 : ast_dump_context->dump_expression(this->channel_);
2030 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
2031 0 : }
2032 :
2033 : // Make a nonblocking receive statement.
2034 :
2035 : Statement*
2036 186 : Statement::make_tuple_receive_assignment(Expression* val, Expression* closed,
2037 : Expression* channel,
2038 : Location location)
2039 : {
2040 186 : return new Tuple_receive_assignment_statement(val, closed, channel,
2041 186 : location);
2042 : }
2043 :
2044 : // An assignment to a pair of values from a type guard. This is a
2045 : // conditional type guard. v, ok = i.(type).
2046 :
2047 : class Tuple_type_guard_assignment_statement : public Statement
2048 : {
2049 : public:
2050 6693 : Tuple_type_guard_assignment_statement(Expression* val, Expression* ok,
2051 : Expression* expr, Type* type,
2052 : Location location)
2053 6693 : : Statement(STATEMENT_TUPLE_TYPE_GUARD_ASSIGNMENT, location),
2054 13386 : val_(val), ok_(ok), expr_(expr), type_(type)
2055 : { }
2056 :
2057 : protected:
2058 : int
2059 : do_traverse(Traverse*);
2060 :
2061 : void
2062 : do_determine_types(Gogo*);
2063 :
2064 : void
2065 : do_check_types(Gogo*);
2066 :
2067 : Statement*
2068 : do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
2069 :
2070 : Bstatement*
2071 0 : do_get_backend(Translate_context*)
2072 0 : { go_unreachable(); }
2073 :
2074 : void
2075 : do_dump_statement(Ast_dump_context*) const;
2076 :
2077 : private:
2078 : Call_expression*
2079 : lower_to_type(Gogo*, Runtime::Function);
2080 :
2081 : void
2082 : lower_to_object_type(Gogo*, Block*, Runtime::Function);
2083 :
2084 : // The variable which recieves the converted value.
2085 : Expression* val_;
2086 : // The variable which receives the indication of success.
2087 : Expression* ok_;
2088 : // The expression being converted.
2089 : Expression* expr_;
2090 : // The type to which the expression is being converted.
2091 : Type* type_;
2092 : };
2093 :
2094 : // Traverse a type guard tuple assignment.
2095 :
2096 : int
2097 33464 : Tuple_type_guard_assignment_statement::do_traverse(Traverse* traverse)
2098 : {
2099 33464 : if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
2100 33464 : || this->traverse_expression(traverse, &this->ok_) == TRAVERSE_EXIT
2101 66928 : || this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
2102 0 : return TRAVERSE_EXIT;
2103 33464 : return this->traverse_expression(traverse, &this->expr_);
2104 : }
2105 :
2106 : void
2107 6693 : Tuple_type_guard_assignment_statement::do_determine_types(Gogo* gogo)
2108 : {
2109 6693 : this->val_->determine_type_no_context(gogo);
2110 6693 : this->ok_->determine_type_no_context(gogo);
2111 6693 : this->expr_->determine_type_no_context(gogo);
2112 6693 : }
2113 :
2114 : void
2115 6693 : Tuple_type_guard_assignment_statement::do_check_types(Gogo*)
2116 : {
2117 6693 : Type* expr_type = this->expr_->type();
2118 6693 : if (expr_type->interface_type() == NULL)
2119 : {
2120 0 : if (!expr_type->is_error() && !this->type_->is_error())
2121 0 : this->report_error(_("type assertion only valid for interface types"));
2122 0 : return;
2123 : }
2124 :
2125 6693 : if (!Assignment_statement::check_assignment_types(this->val_, this->type_,
2126 : this->location()))
2127 1 : this->set_is_error();
2128 6693 : if (!Assignment_statement::check_assignment_types(this->ok_,
2129 : Type::make_boolean_type(),
2130 : this->location()))
2131 0 : this->set_is_error();
2132 : }
2133 :
2134 : // Lower to a function call.
2135 :
2136 : Statement*
2137 6692 : Tuple_type_guard_assignment_statement::do_lower(Gogo* gogo, Named_object*,
2138 : Block* enclosing,
2139 : Statement_inserter*)
2140 : {
2141 6692 : Location loc = this->location();
2142 :
2143 6692 : if (this->classification() == STATEMENT_ERROR)
2144 0 : return Statement::make_error_statement(loc);
2145 :
2146 6692 : Type* expr_type = this->expr_->type();
2147 6692 : go_assert(expr_type->interface_type() != NULL);
2148 :
2149 6692 : Block* b = new Block(enclosing, loc);
2150 :
2151 : // Make sure that any subexpressions on the left hand side are
2152 : // evaluated in the right order.
2153 6692 : Move_ordered_evals moe(b);
2154 6692 : this->val_->traverse_subexpressions(&moe);
2155 6692 : this->ok_->traverse_subexpressions(&moe);
2156 :
2157 13384 : bool expr_is_empty = expr_type->interface_type()->is_empty();
2158 6692 : Call_expression* call;
2159 6692 : if (this->type_->interface_type() != NULL)
2160 : {
2161 2684 : if (this->type_->interface_type()->is_empty())
2162 20 : call = Runtime::make_call(gogo,
2163 : (expr_is_empty
2164 : ? Runtime::IFACEE2E2
2165 : : Runtime::IFACEI2E2),
2166 : loc, 1, this->expr_);
2167 : else
2168 2362 : call = this->lower_to_type(gogo,
2169 : (expr_is_empty
2170 : ? Runtime::IFACEE2I2
2171 : : Runtime::IFACEI2I2));
2172 : }
2173 5350 : else if (this->type_->points_to() != NULL)
2174 7610 : call = this->lower_to_type(gogo,
2175 : (expr_is_empty
2176 : ? Runtime::IFACEE2T2P
2177 : : Runtime::IFACEI2T2P));
2178 : else
2179 : {
2180 1300 : this->lower_to_object_type(gogo, b,
2181 : (expr_is_empty
2182 : ? Runtime::IFACEE2T2
2183 : : Runtime::IFACEI2T2));
2184 1300 : call = NULL;
2185 : }
2186 :
2187 6692 : if (call != NULL)
2188 : {
2189 5392 : Expression* res = Expression::make_call_result(call, 0);
2190 5392 : res = Expression::make_unsafe_cast(this->type_, res, loc);
2191 5392 : Statement* s = Statement::make_assignment(this->val_, res, loc);
2192 5392 : s->determine_types(gogo);
2193 5392 : b->add_statement(s);
2194 :
2195 5392 : res = Expression::make_call_result(call, 1);
2196 5392 : if (!this->ok_->type()->is_boolean_type())
2197 1209 : res = Expression::make_cast(Type::lookup_bool_type(), res, loc);
2198 5392 : s = Statement::make_assignment(this->ok_, res, loc);
2199 5392 : s->determine_types(gogo);
2200 5392 : b->add_statement(s);
2201 : }
2202 :
2203 6692 : return Statement::make_block_statement(b, loc);
2204 6692 : }
2205 :
2206 : // Lower a conversion to a non-empty interface type or a pointer type.
2207 :
2208 : Call_expression*
2209 5378 : Tuple_type_guard_assignment_statement::lower_to_type(Gogo* gogo,
2210 : Runtime::Function code)
2211 : {
2212 5378 : Location loc = this->location();
2213 5378 : return Runtime::make_call(gogo, code, loc, 2,
2214 : Expression::make_type_descriptor(this->type_, loc),
2215 5378 : this->expr_);
2216 : }
2217 :
2218 : // Lower a conversion to a non-interface non-pointer type.
2219 :
2220 : void
2221 1300 : Tuple_type_guard_assignment_statement::lower_to_object_type(
2222 : Gogo* gogo,
2223 : Block* b,
2224 : Runtime::Function code)
2225 : {
2226 1300 : Location loc = this->location();
2227 :
2228 : // var val_temp TYPE
2229 1300 : Temporary_statement* val_temp = Statement::make_temporary(this->type_,
2230 : NULL, loc);
2231 1300 : b->add_statement(val_temp);
2232 :
2233 : // var ok_temp bool
2234 1300 : Temporary_statement* ok_temp = NULL;
2235 1300 : if (!this->ok_->is_sink_expression())
2236 : {
2237 1924 : ok_temp = Statement::make_temporary((this->ok_->type()->is_boolean_type()
2238 962 : ? this->ok_->type()
2239 0 : : Type::lookup_bool_type()),
2240 : NULL, loc);
2241 962 : b->add_statement(ok_temp);
2242 : }
2243 :
2244 : // ok_temp = CODE(type_descriptor, expr, &val_temp)
2245 1300 : Expression* p1 = Expression::make_type_descriptor(this->type_, loc);
2246 1300 : Expression* ref = Expression::make_temporary_reference(val_temp, loc);
2247 1300 : Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
2248 1300 : Expression* call = Runtime::make_call(gogo, code, loc, 3,
2249 : p1, this->expr_, p3);
2250 1300 : Statement* s;
2251 1300 : if (ok_temp == NULL)
2252 338 : s = Statement::make_statement(call, true);
2253 : else
2254 : {
2255 962 : Expression* ok_ref = Expression::make_temporary_reference(ok_temp, loc);
2256 962 : s = Statement::make_assignment(ok_ref, call, loc);
2257 : }
2258 1300 : s->determine_types(gogo);
2259 1300 : b->add_statement(s);
2260 :
2261 : // val = val_temp
2262 1300 : ref = Expression::make_temporary_reference(val_temp, loc);
2263 1300 : s = Statement::make_assignment(this->val_, ref, loc);
2264 1300 : s->determine_types(gogo);
2265 1300 : b->add_statement(s);
2266 :
2267 : // ok = ok_temp
2268 1300 : if (ok_temp != NULL)
2269 : {
2270 962 : ref = Expression::make_temporary_reference(ok_temp, loc);
2271 962 : s = Statement::make_assignment(this->ok_, ref, loc);
2272 962 : s->determine_types(gogo);
2273 962 : b->add_statement(s);
2274 : }
2275 1300 : }
2276 :
2277 : // Dump the AST representation for a tuple type guard statement.
2278 :
2279 : void
2280 0 : Tuple_type_guard_assignment_statement::do_dump_statement(
2281 : Ast_dump_context* ast_dump_context) const
2282 : {
2283 0 : ast_dump_context->print_indent();
2284 0 : ast_dump_context->dump_expression(this->val_);
2285 0 : ast_dump_context->ostream() << ", ";
2286 0 : ast_dump_context->dump_expression(this->ok_);
2287 0 : ast_dump_context->ostream() << " = ";
2288 0 : ast_dump_context->dump_expression(this->expr_);
2289 0 : ast_dump_context->ostream() << " . ";
2290 0 : ast_dump_context->dump_type(this->type_);
2291 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
2292 0 : }
2293 :
2294 : // Make an assignment from a type guard to a pair of variables.
2295 :
2296 : Statement*
2297 6693 : Statement::make_tuple_type_guard_assignment(Expression* val, Expression* ok,
2298 : Expression* expr, Type* type,
2299 : Location location)
2300 : {
2301 6693 : return new Tuple_type_guard_assignment_statement(val, ok, expr, type,
2302 6693 : location);
2303 : }
2304 :
2305 : // Class Expression_statement.
2306 :
2307 : // Constructor.
2308 :
2309 829784 : Expression_statement::Expression_statement(Expression* expr, bool is_ignored)
2310 : : Statement(STATEMENT_EXPRESSION, expr->location()),
2311 829784 : expr_(expr), is_ignored_(is_ignored)
2312 : {
2313 829784 : }
2314 :
2315 : // Determine types.
2316 :
2317 : void
2318 765202 : Expression_statement::do_determine_types(Gogo* gogo)
2319 : {
2320 765202 : this->expr_->determine_type_no_context(gogo);
2321 765202 : }
2322 :
2323 : // Check the types of an expression statement. The only check we do
2324 : // is to possibly give an error about discarding the value of the
2325 : // expression.
2326 :
2327 : void
2328 259468 : Expression_statement::do_check_types(Gogo*)
2329 : {
2330 259468 : if (!this->is_ignored_)
2331 251818 : this->expr_->discarding_value();
2332 259468 : }
2333 :
2334 : // An expression statement is only a terminating statement if it is
2335 : // a call to panic.
2336 :
2337 : bool
2338 1239 : Expression_statement::do_may_fall_through() const
2339 : {
2340 : // The builtin function panic does not return.
2341 1308 : const Call_expression* call = this->expr_->call_expression();
2342 1239 : if (call == NULL)
2343 : return true;
2344 1239 : const Builtin_call_expression* bce = call->builtin_call_expression();
2345 1228 : return bce == NULL || bce->code() != Builtin_call_expression::BUILTIN_PANIC;
2346 : }
2347 :
2348 : // Export an expression statement.
2349 :
2350 : void
2351 4909 : Expression_statement::do_export_statement(Export_function_body* efb)
2352 : {
2353 4909 : this->expr_->export_expression(efb);
2354 4909 : }
2355 :
2356 : // Convert to backend representation.
2357 :
2358 : Bstatement*
2359 823920 : Expression_statement::do_get_backend(Translate_context* context)
2360 : {
2361 823920 : Bexpression* bexpr = this->expr_->get_backend(context);
2362 823920 : Bfunction* bfunction = context->function()->func_value()->get_decl();
2363 823920 : return context->backend()->expression_statement(bfunction, bexpr);
2364 : }
2365 :
2366 : // Dump the AST representation for an expression statement
2367 :
2368 : void
2369 0 : Expression_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
2370 : const
2371 : {
2372 0 : ast_dump_context->print_indent();
2373 0 : ast_dump_context->dump_expression(expr_);
2374 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
2375 0 : }
2376 :
2377 : // Make an expression statement from an Expression.
2378 :
2379 : Statement*
2380 829784 : Statement::make_statement(Expression* expr, bool is_ignored)
2381 : {
2382 829784 : return new Expression_statement(expr, is_ignored);
2383 : }
2384 :
2385 : // Export data for a block.
2386 :
2387 : void
2388 22817 : Block_statement::do_export_statement(Export_function_body* efb)
2389 : {
2390 22817 : Block_statement::export_block(efb, this->block_,
2391 22817 : this->is_lowered_for_statement_);
2392 22817 : }
2393 :
2394 : void
2395 27416 : Block_statement::export_block(Export_function_body* efb, Block* block,
2396 : bool is_lowered_for_statement)
2397 : {
2398 : // We are already indented to the right position.
2399 27416 : char buf[50];
2400 27416 : efb->write_c_string("{");
2401 27416 : if (is_lowered_for_statement)
2402 445 : efb->write_c_string(" /*for*/");
2403 27416 : snprintf(buf, sizeof buf, " //%d\n",
2404 : Linemap::location_to_line(block->start_location()));
2405 27416 : efb->write_c_string(buf);
2406 :
2407 27416 : block->export_block(efb);
2408 : // The indentation is correct for the statements in the block, so
2409 : // subtract one for the closing curly brace.
2410 27416 : efb->decrement_indent();
2411 27416 : efb->indent();
2412 27416 : efb->write_c_string("}");
2413 : // Increment back to the value the caller thinks it has.
2414 27416 : efb->increment_indent();
2415 27416 : }
2416 :
2417 : // Import a block statement, returning the block.
2418 :
2419 : Block*
2420 26622 : Block_statement::do_import(Import_function_body* ifb, Location loc,
2421 : bool* is_lowered_for_statement)
2422 : {
2423 26622 : go_assert(ifb->match_c_string("{"));
2424 26622 : *is_lowered_for_statement = false;
2425 26622 : if (ifb->match_c_string(" /*for*/"))
2426 : {
2427 0 : ifb->advance(8);
2428 0 : *is_lowered_for_statement = true;
2429 : }
2430 26622 : size_t nl = ifb->body().find('\n', ifb->off());
2431 26622 : if (nl == std::string::npos)
2432 : {
2433 0 : if (!ifb->saw_error())
2434 0 : go_error_at(ifb->location(),
2435 : "import error: no newline after %<{%> at %lu",
2436 0 : static_cast<unsigned long>(ifb->off()));
2437 0 : ifb->set_saw_error();
2438 0 : return NULL;
2439 : }
2440 26622 : ifb->set_off(nl + 1);
2441 26622 : ifb->increment_indent();
2442 26622 : Block* block = new Block(ifb->block(), loc);
2443 26622 : ifb->begin_block(block);
2444 26622 : bool ok = Block::import_block(block, ifb, loc);
2445 26622 : ifb->finish_block();
2446 26622 : ifb->decrement_indent();
2447 26622 : if (!ok)
2448 : return NULL;
2449 : return block;
2450 : }
2451 :
2452 : // Convert a block to the backend representation of a statement.
2453 :
2454 : Bstatement*
2455 1359964 : Block_statement::do_get_backend(Translate_context* context)
2456 : {
2457 1359964 : Bblock* bblock = this->block_->get_backend(context);
2458 1359964 : return context->backend()->block_statement(bblock);
2459 : }
2460 :
2461 : // Dump the AST for a block statement
2462 :
2463 : void
2464 0 : Block_statement::do_dump_statement(Ast_dump_context*) const
2465 : {
2466 : // block statement braces are dumped when traversing.
2467 0 : }
2468 :
2469 : // Make a block statement.
2470 :
2471 : Block_statement*
2472 1363149 : Statement::make_block_statement(Block* block, Location location)
2473 : {
2474 1363149 : return new Block_statement(block, location);
2475 : }
2476 :
2477 : // An increment or decrement statement.
2478 :
2479 : class Inc_dec_statement : public Statement
2480 : {
2481 : public:
2482 58820 : Inc_dec_statement(bool is_inc, Expression* expr)
2483 58820 : : Statement(STATEMENT_INCDEC, expr->location()),
2484 117640 : expr_(expr), is_inc_(is_inc)
2485 : { }
2486 :
2487 : protected:
2488 : int
2489 168631 : do_traverse(Traverse* traverse)
2490 168631 : { return this->traverse_expression(traverse, &this->expr_); }
2491 :
2492 : void
2493 : do_determine_types(Gogo*);
2494 :
2495 : void
2496 : do_check_types(Gogo*);
2497 :
2498 : Statement*
2499 : do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
2500 :
2501 : Bstatement*
2502 0 : do_get_backend(Translate_context*)
2503 0 : { go_unreachable(); }
2504 :
2505 : void
2506 : do_dump_statement(Ast_dump_context*) const;
2507 :
2508 : private:
2509 : // The l-value to increment or decrement.
2510 : Expression* expr_;
2511 : // Whether to increment or decrement.
2512 : bool is_inc_;
2513 : };
2514 :
2515 : void
2516 90187 : Inc_dec_statement::do_determine_types(Gogo* gogo)
2517 : {
2518 90187 : this->expr_->determine_type_no_context(gogo);
2519 90187 : }
2520 :
2521 : void
2522 27453 : Inc_dec_statement::do_check_types(Gogo*)
2523 : {
2524 27453 : if (!this->expr_->is_addressable()
2525 27453 : && !Index_expression::is_map_index(this->expr_))
2526 : {
2527 0 : if (!this->expr_->type()->is_error())
2528 0 : this->report_error(_("invalid left hand side of assignment"));
2529 0 : this->set_is_error();
2530 0 : return;
2531 : }
2532 27453 : if (!this->expr_->type()->is_numeric_type())
2533 : {
2534 1 : this->report_error(_("increment or decrement of non-numeric type"));
2535 1 : return;
2536 : }
2537 : }
2538 :
2539 : // Lower to += or -=.
2540 :
2541 : Statement*
2542 58819 : Inc_dec_statement::do_lower(Gogo*, Named_object*, Block*, Statement_inserter*)
2543 : {
2544 58819 : Location loc = this->location();
2545 58819 : Expression* oexpr = Expression::make_integer_ul(1, this->expr_->type(), loc);
2546 58819 : Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ;
2547 58819 : return Statement::make_assignment_operation(op, this->expr_, oexpr, loc);
2548 : }
2549 :
2550 : // Dump the AST representation for a inc/dec statement.
2551 :
2552 : void
2553 0 : Inc_dec_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
2554 : {
2555 0 : ast_dump_context->print_indent();
2556 0 : ast_dump_context->dump_expression(expr_);
2557 0 : ast_dump_context->ostream() << (is_inc_? "++": "--") << dsuffix(location()) << std::endl;
2558 0 : }
2559 :
2560 : // Make an increment statement.
2561 :
2562 : Statement*
2563 54549 : Statement::make_inc_statement(Expression* expr)
2564 : {
2565 54549 : return new Inc_dec_statement(true, expr);
2566 : }
2567 :
2568 : // Make a decrement statement.
2569 :
2570 : Statement*
2571 4271 : Statement::make_dec_statement(Expression* expr)
2572 : {
2573 4271 : return new Inc_dec_statement(false, expr);
2574 : }
2575 :
2576 : // Class Thunk_statement. This is the base class for go and defer
2577 : // statements.
2578 :
2579 : // Constructor.
2580 :
2581 27523 : Thunk_statement::Thunk_statement(Statement_classification classification,
2582 : Call_expression* call,
2583 27523 : Location location)
2584 : : Statement(classification, location),
2585 27523 : call_(call)
2586 : {
2587 27523 : }
2588 :
2589 : // Return whether this is a simple statement which does not require a
2590 : // thunk.
2591 :
2592 : bool
2593 13743 : Thunk_statement::is_simple(Function_type* fntype) const
2594 : {
2595 : // We need a thunk to call a method, or to pass a variable number of
2596 : // arguments.
2597 13743 : if (fntype->is_method() || fntype->is_varargs())
2598 : return false;
2599 :
2600 : // A defer statement requires a thunk to set up for whether the
2601 : // function can call recover.
2602 13432 : if (this->classification() == STATEMENT_DEFER)
2603 : return false;
2604 :
2605 : // We can only permit a single parameter of pointer type.
2606 2501 : const Typed_identifier_list* parameters = fntype->parameters();
2607 2501 : if (parameters != NULL
2608 3325 : && (parameters->size() > 1
2609 403 : || (parameters->size() == 1
2610 403 : && parameters->begin()->type()->points_to() == NULL)))
2611 771 : return false;
2612 :
2613 : // If the function returns multiple values, or returns a type other
2614 : // than integer, floating point, or pointer, then it may get a
2615 : // hidden first parameter, in which case we need the more
2616 : // complicated approach. This is true even though we are going to
2617 : // ignore the return value.
2618 1730 : const Typed_identifier_list* results = fntype->results();
2619 1730 : if (results != NULL
2620 1755 : && (results->size() > 1
2621 25 : || (results->size() == 1
2622 25 : && !results->begin()->type()->is_basic_type()
2623 24 : && results->begin()->type()->points_to() == NULL)))
2624 24 : return false;
2625 :
2626 : // If this calls something that is not a simple function, then we
2627 : // need a thunk.
2628 1706 : Expression* fn = this->call_->call_expression()->fn();
2629 15200 : if (fn->func_expression() == NULL)
2630 : return false;
2631 :
2632 : // If the function uses a closure, then we need a thunk. FIXME: We
2633 : // could accept a zero argument function with a closure.
2634 1559 : if (fn->func_expression()->closure() != NULL)
2635 : return false;
2636 :
2637 : return true;
2638 : }
2639 :
2640 : // Traverse a thunk statement.
2641 :
2642 : int
2643 328818 : Thunk_statement::do_traverse(Traverse* traverse)
2644 : {
2645 328818 : return this->traverse_expression(traverse, &this->call_);
2646 : }
2647 :
2648 : // Determine types in a thunk statement.
2649 :
2650 : void
2651 27901 : Thunk_statement::do_determine_types(Gogo* gogo)
2652 : {
2653 27901 : this->call_->determine_type_no_context(gogo);
2654 27901 : }
2655 :
2656 : // Check types in a thunk statement.
2657 :
2658 : void
2659 27523 : Thunk_statement::do_check_types(Gogo*)
2660 : {
2661 27523 : if (!this->call_->discarding_value())
2662 : {
2663 42 : this->set_is_error();
2664 42 : return;
2665 : }
2666 27481 : Call_expression* ce = this->call_->call_expression();
2667 2 : if (ce == NULL)
2668 : {
2669 2 : if (!this->call_->is_error_expression())
2670 0 : this->report_error("expected call expression");
2671 2 : this->set_is_error();
2672 2 : return;
2673 : }
2674 : }
2675 :
2676 : // The Traverse class used to find and simplify thunk statements.
2677 :
2678 9292 : class Simplify_thunk_traverse : public Traverse
2679 : {
2680 : public:
2681 4646 : Simplify_thunk_traverse(Gogo* gogo)
2682 4646 : : Traverse(traverse_functions | traverse_blocks),
2683 4646 : gogo_(gogo), function_(NULL)
2684 : { }
2685 :
2686 : int
2687 : function(Named_object*);
2688 :
2689 : int
2690 : block(Block*);
2691 :
2692 : private:
2693 : // General IR.
2694 : Gogo* gogo_;
2695 : // The function we are traversing.
2696 : Named_object* function_;
2697 : };
2698 :
2699 : // Keep track of the current function while looking for thunks.
2700 :
2701 : int
2702 203075 : Simplify_thunk_traverse::function(Named_object* no)
2703 : {
2704 203075 : go_assert(this->function_ == NULL);
2705 203075 : this->function_ = no;
2706 203075 : int t = no->func_value()->traverse(this);
2707 203075 : this->function_ = NULL;
2708 203075 : if (t == TRAVERSE_EXIT)
2709 0 : return t;
2710 : return TRAVERSE_SKIP_COMPONENTS;
2711 : }
2712 :
2713 : // Look for thunks in a block.
2714 :
2715 : int
2716 1722684 : Simplify_thunk_traverse::block(Block* b)
2717 : {
2718 : // The parser ensures that thunk statements always appear at the end
2719 : // of a block.
2720 1722684 : if (b->statements()->size() < 1)
2721 : return TRAVERSE_CONTINUE;
2722 1718069 : Thunk_statement* stat = b->statements()->back()->thunk_statement();
2723 1718069 : if (stat == NULL)
2724 : return TRAVERSE_CONTINUE;
2725 13743 : if (stat->simplify_statement(this->gogo_, this->function_, b))
2726 : return TRAVERSE_SKIP_COMPONENTS;
2727 : return TRAVERSE_CONTINUE;
2728 : }
2729 :
2730 : // Simplify all thunk statements.
2731 :
2732 : void
2733 4646 : Gogo::simplify_thunk_statements()
2734 : {
2735 4646 : Simplify_thunk_traverse thunk_traverse(this);
2736 4646 : this->traverse(&thunk_traverse);
2737 4646 : }
2738 :
2739 : // Return true if the thunk function is a constant, which means that
2740 : // it does not need to be passed to the thunk routine.
2741 :
2742 : bool
2743 40923 : Thunk_statement::is_constant_function() const
2744 : {
2745 40923 : Call_expression* ce = this->call_->call_expression();
2746 40923 : Function_type* fntype = ce->get_function_type();
2747 40923 : if (fntype == NULL)
2748 : {
2749 0 : go_assert(saw_errors());
2750 : return false;
2751 : }
2752 40923 : if (fntype->is_builtin())
2753 : return true;
2754 39930 : Expression* fn = ce->fn();
2755 39930 : if (fn->func_expression() != NULL)
2756 18543 : return fn->func_expression()->closure() == NULL;
2757 21387 : if (fn->interface_field_reference_expression() != NULL)
2758 : return true;
2759 18645 : if (fn->bound_method_expression() != NULL)
2760 : return true;
2761 : return false;
2762 : }
2763 :
2764 : // Simplify complex thunk statements into simple ones. A complicated
2765 : // thunk statement is one which takes anything other than zero
2766 : // parameters or a single pointer parameter. We rewrite it into code
2767 : // which allocates a struct, stores the parameter values into the
2768 : // struct, and does a simple go or defer statement which passes the
2769 : // struct to a thunk. The thunk does the real call.
2770 :
2771 : bool
2772 13743 : Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
2773 : Block* block)
2774 : {
2775 13743 : if (this->classification() == STATEMENT_ERROR)
2776 : return false;
2777 13743 : if (this->call_->is_error_expression())
2778 : return false;
2779 :
2780 13743 : if (this->classification() == STATEMENT_DEFER)
2781 : {
2782 : // Make sure that the defer stack exists for the function. We
2783 : // will use when converting this statement to the backend
2784 : // representation, but we want it to exist when we start
2785 : // converting the function.
2786 11230 : function->func_value()->defer_stack(this->location());
2787 : }
2788 :
2789 13743 : Call_expression* ce = this->call_->call_expression();
2790 13743 : Function_type* fntype = ce->get_function_type();
2791 13743 : if (fntype == NULL)
2792 : {
2793 0 : go_assert(saw_errors());
2794 0 : this->set_is_error();
2795 0 : return false;
2796 : }
2797 13743 : if (this->is_simple(fntype))
2798 : return false;
2799 :
2800 13641 : Struct_type* struct_type = this->build_struct(fntype);
2801 :
2802 13641 : Expression* fn = ce->fn();
2803 13641 : Interface_field_reference_expression* interface_method =
2804 13641 : fn->interface_field_reference_expression();
2805 13641 : Bound_method_expression* bme = fn->bound_method_expression();
2806 :
2807 13641 : Location location = this->location();
2808 :
2809 13641 : bool is_constant_function = this->is_constant_function();
2810 13641 : Temporary_statement* fn_temp = NULL;
2811 13641 : if (!is_constant_function)
2812 : {
2813 3781 : fn_temp = Statement::make_temporary(NULL, fn, location);
2814 3781 : block->insert_statement_before(block->statements()->size() - 1, fn_temp);
2815 3781 : fn = Expression::make_temporary_reference(fn_temp, location);
2816 : }
2817 :
2818 13641 : std::string thunk_name = gogo->thunk_name();
2819 :
2820 : // Build the thunk.
2821 13641 : this->build_thunk(gogo, thunk_name, struct_type);
2822 :
2823 : // Generate code to call the thunk.
2824 :
2825 : // Get the values to store into the struct which is the single
2826 : // argument to the thunk.
2827 :
2828 13641 : Expression_list* vals = new Expression_list();
2829 13641 : if (!is_constant_function)
2830 3781 : vals->push_back(fn);
2831 :
2832 13641 : if (interface_method != NULL)
2833 914 : vals->push_back(interface_method->expr());
2834 13641 : if (bme != NULL)
2835 5513 : vals->push_back(bme->first_argument());
2836 :
2837 13641 : if (ce->args() != NULL)
2838 : {
2839 8610 : for (Expression_list::const_iterator p = ce->args()->begin();
2840 8610 : p != ce->args()->end();
2841 4990 : ++p)
2842 : {
2843 4990 : if ((*p)->is_constant())
2844 499 : continue;
2845 4491 : vals->push_back(*p);
2846 : }
2847 : }
2848 :
2849 : // Build the struct.
2850 13641 : Expression* constructor =
2851 13641 : Expression::make_struct_composite_literal(struct_type, vals, location);
2852 :
2853 : // Allocate the initialized struct on the heap.
2854 13641 : constructor = Expression::make_heap_expression(constructor, location);
2855 13641 : if ((Node::make_node(this)->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
2856 10957 : constructor->heap_expression()->set_allocate_on_stack();
2857 :
2858 : // Throw an error if the function is nil. This is so that for `go
2859 : // nil` we get a backtrace from the go statement, rather than a
2860 : // useless backtrace from the brand new goroutine.
2861 13641 : Expression* param = constructor;
2862 13641 : if (!is_constant_function && this->classification() == STATEMENT_GO)
2863 : {
2864 1758 : fn = Expression::make_temporary_reference(fn_temp, location);
2865 1758 : Expression* nil = Expression::make_nil(location);
2866 1758 : Expression* isnil = Expression::make_binary(OPERATOR_EQEQ, fn, nil,
2867 : location);
2868 1758 : Expression* crash = Runtime::make_call(gogo, Runtime::PANIC_GO_NIL,
2869 : location, 0);
2870 1758 : crash = Expression::make_conditional(isnil, crash,
2871 : Expression::make_nil(location),
2872 : location);
2873 1758 : param = Expression::make_compound(crash, constructor, location);
2874 : }
2875 :
2876 : // Look up the thunk.
2877 13641 : Named_object* named_thunk = gogo->lookup(thunk_name, NULL);
2878 13641 : go_assert(named_thunk != NULL && named_thunk->is_function());
2879 :
2880 : // Build the call.
2881 13641 : Expression* func = Expression::make_func_reference(named_thunk, NULL,
2882 : location);
2883 13641 : Expression_list* params = new Expression_list();
2884 13641 : params->push_back(param);
2885 13641 : Call_expression* call = Expression::make_call(func, params, false, location);
2886 :
2887 : // Build the simple go or defer statement.
2888 13641 : Statement* s;
2889 13641 : if (this->classification() == STATEMENT_GO)
2890 2411 : s = Statement::make_go_statement(call, location);
2891 11230 : else if (this->classification() == STATEMENT_DEFER)
2892 : {
2893 11230 : s = Statement::make_defer_statement(call, location);
2894 11230 : if ((Node::make_node(this)->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
2895 10957 : s->defer_statement()->set_on_stack();
2896 : }
2897 : else
2898 0 : go_unreachable();
2899 :
2900 : // The current block should end with the go statement.
2901 13641 : go_assert(block->statements()->size() >= 1);
2902 13641 : go_assert(block->statements()->back() == this);
2903 13641 : block->replace_statement(block->statements()->size() - 1, s);
2904 :
2905 : // We already ran the determine_types pass, so we need to run it now
2906 : // for the new statement.
2907 13641 : s->determine_types(gogo);
2908 :
2909 : // Sanity check.
2910 13641 : gogo->check_types_in_block(block);
2911 :
2912 : // Return true to tell the block not to keep looking at statements.
2913 13641 : return true;
2914 13641 : }
2915 :
2916 : // Set the name to use for thunk parameter N.
2917 :
2918 : void
2919 4491 : Thunk_statement::thunk_field_param(int n, char* buf, size_t buflen)
2920 : {
2921 4491 : snprintf(buf, buflen, "a%d", n);
2922 4491 : }
2923 :
2924 : // Build a new struct type to hold the parameters for a complicated
2925 : // thunk statement. FNTYPE is the type of the function call.
2926 :
2927 : Struct_type*
2928 13641 : Thunk_statement::build_struct(Function_type* fntype)
2929 : {
2930 13641 : Location location = this->location();
2931 :
2932 13641 : Struct_field_list* fields = new Struct_field_list();
2933 :
2934 13641 : Call_expression* ce = this->call_->call_expression();
2935 13641 : Expression* fn = ce->fn();
2936 :
2937 13641 : if (!this->is_constant_function())
2938 : {
2939 : // The function to call.
2940 7562 : fields->push_back(Struct_field(Typed_identifier("fn", fntype,
2941 3781 : location)));
2942 : }
2943 :
2944 : // If this thunk statement calls a method on an interface, we pass
2945 : // the interface object to the thunk.
2946 13641 : Interface_field_reference_expression* interface_method =
2947 14555 : fn->interface_field_reference_expression();
2948 914 : if (interface_method != NULL)
2949 : {
2950 914 : Typed_identifier tid("object", interface_method->expr()->type(),
2951 1828 : location);
2952 914 : fields->push_back(Struct_field(tid));
2953 914 : }
2954 :
2955 : // If this thunk statement calls a bound method expression, as in
2956 : // "go s.m()", we pass the bound method argument to the thunk,
2957 : // to ensure that we make a copy of it if needed.
2958 13641 : Bound_method_expression* bme = fn->bound_method_expression();
2959 5513 : if (bme != NULL)
2960 : {
2961 11026 : Typed_identifier tid("object", bme->first_argument()->type(), location);
2962 5513 : fields->push_back(Struct_field(tid));
2963 5513 : }
2964 :
2965 13641 : const Expression_list* args = ce->args();
2966 13641 : if (args != NULL)
2967 : {
2968 3620 : int i = 0;
2969 3620 : for (Expression_list::const_iterator p = args->begin();
2970 8610 : p != args->end();
2971 4990 : ++p, ++i)
2972 : {
2973 4990 : if ((*p)->is_constant())
2974 499 : continue;
2975 :
2976 4491 : char buf[50];
2977 4491 : this->thunk_field_param(i, buf, sizeof buf);
2978 8982 : fields->push_back(Struct_field(Typed_identifier(buf, (*p)->type(),
2979 8982 : location)));
2980 : }
2981 : }
2982 :
2983 13641 : Struct_type *st = Type::make_struct_type(fields, location);
2984 13641 : st->set_is_struct_incomparable();
2985 13641 : return st;
2986 : }
2987 :
2988 : // Build the thunk we are going to call. This is a brand new, albeit
2989 : // artificial, function.
2990 :
2991 : void
2992 13641 : Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name,
2993 : Struct_type* struct_type)
2994 : {
2995 13641 : Location location = this->location();
2996 :
2997 13641 : Call_expression* ce = this->call_->call_expression();
2998 :
2999 13641 : bool may_call_recover = false;
3000 13641 : if (this->classification() == STATEMENT_DEFER)
3001 : {
3002 11230 : Func_expression* fn = ce->fn()->func_expression();
3003 4474 : if (fn == NULL)
3004 : may_call_recover = true;
3005 : else
3006 : {
3007 4474 : const Named_object* no = fn->named_object();
3008 4474 : if (!no->is_function())
3009 : may_call_recover = true;
3010 : else
3011 3391 : may_call_recover = no->func_value()->calls_recover();
3012 : }
3013 : }
3014 :
3015 : // Build the type of the thunk. The thunk takes a single parameter,
3016 : // which is a pointer to the special structure we build.
3017 13641 : const char* const parameter_name = "__go_thunk_parameter";
3018 13641 : Typed_identifier_list* thunk_parameters = new Typed_identifier_list();
3019 13641 : Type* pointer_to_struct_type = Type::make_pointer_type(struct_type);
3020 27282 : thunk_parameters->push_back(Typed_identifier(parameter_name,
3021 : pointer_to_struct_type,
3022 13641 : location));
3023 :
3024 13641 : Typed_identifier_list* thunk_results = NULL;
3025 13641 : if (may_call_recover)
3026 : {
3027 : // When deferring a function which may call recover, add a
3028 : // return value, to disable tail call optimizations which will
3029 : // break the way we check whether recover is permitted.
3030 8840 : thunk_results = new Typed_identifier_list();
3031 17680 : thunk_results->push_back(Typed_identifier("", Type::lookup_bool_type(),
3032 8840 : location));
3033 : }
3034 :
3035 13641 : Function_type* thunk_type = Type::make_function_type(NULL, thunk_parameters,
3036 : thunk_results,
3037 : location);
3038 :
3039 : // Start building the thunk.
3040 13641 : Named_object* function = gogo->start_function(thunk_name, thunk_type, true,
3041 : location);
3042 :
3043 13641 : gogo->start_block(location);
3044 :
3045 : // For a defer statement, start with a call to
3046 : // __go_set_defer_retaddr. */
3047 13641 : Label* retaddr_label = NULL;
3048 13641 : if (may_call_recover)
3049 : {
3050 8840 : retaddr_label = gogo->add_label_reference("retaddr", location, false);
3051 8840 : Expression* arg = Expression::make_label_addr(retaddr_label, location);
3052 8840 : Expression* call = Runtime::make_call(gogo, Runtime::SETDEFERRETADDR,
3053 : location, 1, arg);
3054 :
3055 : // This is a hack to prevent the middle-end from deleting the
3056 : // label.
3057 8840 : gogo->start_block(location);
3058 8840 : gogo->add_statement(Statement::make_goto_statement(retaddr_label,
3059 : location));
3060 8840 : Block* then_block = gogo->finish_block(location);
3061 8840 : then_block->determine_types(gogo);
3062 :
3063 8840 : Statement* s = Statement::make_if_statement(call, then_block, NULL,
3064 : location);
3065 8840 : s->determine_types(gogo);
3066 8840 : gogo->add_statement(s);
3067 :
3068 8840 : function->func_value()->set_calls_defer_retaddr();
3069 : }
3070 :
3071 : // Get a reference to the parameter.
3072 13641 : Named_object* named_parameter = gogo->lookup(parameter_name, NULL);
3073 13641 : go_assert(named_parameter != NULL && named_parameter->is_variable());
3074 :
3075 : // Build the call. Note that the field names are the same as the
3076 : // ones used in build_struct.
3077 13641 : Expression* thunk_parameter = Expression::make_var_reference(named_parameter,
3078 : location);
3079 13641 : thunk_parameter =
3080 13641 : Expression::make_dereference(thunk_parameter,
3081 : Expression::NIL_CHECK_NOT_NEEDED,
3082 : location);
3083 :
3084 13641 : Interface_field_reference_expression* interface_method =
3085 13641 : ce->fn()->interface_field_reference_expression();
3086 13641 : Bound_method_expression* bme = ce->fn()->bound_method_expression();
3087 :
3088 13641 : Expression* func_to_call;
3089 13641 : unsigned int next_index;
3090 13641 : if (this->is_constant_function())
3091 : {
3092 9860 : func_to_call = ce->fn();
3093 9860 : next_index = 0;
3094 : }
3095 : else
3096 : {
3097 3781 : func_to_call = Expression::make_field_reference(thunk_parameter,
3098 : 0, location);
3099 3781 : next_index = 1;
3100 : }
3101 :
3102 13641 : if (interface_method != NULL)
3103 : {
3104 : // The main program passes the interface object.
3105 914 : go_assert(next_index == 0);
3106 914 : Expression* r = Expression::make_field_reference(thunk_parameter, 0,
3107 : location);
3108 914 : const std::string& name(interface_method->name());
3109 914 : func_to_call = Expression::make_interface_field_reference(r, name,
3110 : location);
3111 914 : next_index = 1;
3112 : }
3113 :
3114 13641 : if (bme != NULL)
3115 : {
3116 : // This is a call to a method.
3117 5513 : go_assert(next_index == 0);
3118 5513 : Expression* r = Expression::make_field_reference(thunk_parameter, 0,
3119 : location);
3120 5513 : func_to_call = Expression::make_bound_method(r, bme->method(),
3121 : bme->function(), location);
3122 5513 : next_index = 1;
3123 : }
3124 :
3125 13641 : Expression_list* call_params = new Expression_list();
3126 13641 : const Struct_field_list* fields = struct_type->fields();
3127 13641 : Struct_field_list::const_iterator p = fields->begin();
3128 13641 : for (unsigned int i = 0; i < next_index; ++i)
3129 : ++p;
3130 13641 : bool is_recover_call = ce->is_recover_call();
3131 13641 : Expression* recover_arg = NULL;
3132 :
3133 13641 : const Expression_list* args = ce->args();
3134 13641 : if (args != NULL)
3135 : {
3136 8610 : for (Expression_list::const_iterator arg = args->begin();
3137 8610 : arg != args->end();
3138 4990 : ++arg)
3139 : {
3140 4990 : Expression* param;
3141 4990 : if ((*arg)->is_constant())
3142 499 : param = *arg;
3143 : else
3144 : {
3145 4491 : Expression* thunk_param =
3146 4491 : Expression::make_var_reference(named_parameter, location);
3147 4491 : thunk_param =
3148 4491 : Expression::make_dereference(thunk_param,
3149 : Expression::NIL_CHECK_NOT_NEEDED,
3150 : location);
3151 4491 : param = Expression::make_field_reference(thunk_param,
3152 : next_index,
3153 : location);
3154 4491 : ++next_index;
3155 : }
3156 :
3157 4990 : if (!is_recover_call)
3158 4980 : call_params->push_back(param);
3159 : else
3160 : {
3161 10 : go_assert(call_params->empty());
3162 : recover_arg = param;
3163 : }
3164 : }
3165 : }
3166 :
3167 13641 : if (call_params->empty())
3168 : {
3169 10031 : delete call_params;
3170 10031 : call_params = NULL;
3171 : }
3172 :
3173 13641 : Call_expression* call = Expression::make_call(func_to_call, call_params,
3174 : false, location);
3175 :
3176 : // This call expression was already lowered before entering the
3177 : // thunk statement. Don't try to lower varargs again, as that will
3178 : // cause confusion for, e.g., method calls which already have a
3179 : // receiver parameter.
3180 13641 : call->set_varargs_are_lowered();
3181 :
3182 13641 : Statement* call_statement = Statement::make_statement(call, true);
3183 :
3184 13641 : call_statement->determine_types(gogo);
3185 13641 : gogo->add_statement(call_statement);
3186 :
3187 : // If this is a defer statement, the label comes immediately after
3188 : // the call.
3189 13641 : if (may_call_recover)
3190 : {
3191 8840 : gogo->add_label_definition("retaddr", location);
3192 :
3193 8840 : Expression_list* vals = new Expression_list();
3194 8840 : vals->push_back(Expression::make_boolean(false, location));
3195 8840 : Statement* s = Statement::make_return_statement(function, vals,
3196 : location);
3197 8840 : s->determine_types(gogo);
3198 8840 : gogo->add_statement(s);
3199 : }
3200 :
3201 13641 : Block* b = gogo->finish_block(location);
3202 :
3203 13641 : gogo->add_block(b, location);
3204 :
3205 13641 : gogo->lower_block(function, b);
3206 :
3207 : // We already ran the determine_types pass, so we need to run it
3208 : // just for the call statement now. The other types are known.
3209 13641 : call_statement->determine_types(gogo);
3210 :
3211 13641 : gogo->add_conversions_in_block(b);
3212 :
3213 13641 : if (may_call_recover
3214 13641 : || recover_arg != NULL
3215 13641 : || this->classification() == STATEMENT_GO)
3216 : {
3217 : // Dig up the call expression, which may have been changed
3218 : // during lowering.
3219 11251 : go_assert(call_statement->classification() == STATEMENT_EXPRESSION);
3220 11251 : Expression_statement* es =
3221 : static_cast<Expression_statement*>(call_statement);
3222 11251 : ce = es->expr()->call_expression();
3223 11251 : if (ce == NULL)
3224 0 : go_assert(saw_errors());
3225 : else
3226 : {
3227 11251 : if (may_call_recover)
3228 8840 : ce->set_is_deferred();
3229 11251 : if (this->classification() == STATEMENT_GO)
3230 2411 : ce->set_is_concurrent();
3231 11251 : if (recover_arg != NULL)
3232 10 : ce->set_recover_arg(recover_arg);
3233 : }
3234 : }
3235 :
3236 13641 : gogo->flatten_block(function, b);
3237 :
3238 : // That is all the thunk has to do.
3239 13641 : gogo->finish_function(location);
3240 13641 : }
3241 :
3242 : // Get the function and argument expressions.
3243 :
3244 : bool
3245 13741 : Thunk_statement::get_fn_and_arg(Expression** pfn, Expression** parg)
3246 : {
3247 13741 : if (this->call_->is_error_expression())
3248 : return false;
3249 :
3250 13741 : Call_expression* ce = this->call_->call_expression();
3251 :
3252 13741 : Expression* fn = ce->fn();
3253 13741 : Func_expression* fe = fn->func_expression();
3254 0 : go_assert(fe != NULL);
3255 13741 : *pfn = Expression::make_func_code_reference(fe->named_object(),
3256 : fe->location());
3257 :
3258 13741 : const Expression_list* args = ce->args();
3259 13741 : if (args == NULL || args->empty())
3260 81 : *parg = Expression::make_nil(this->location());
3261 : else
3262 : {
3263 13660 : go_assert(args->size() == 1);
3264 13660 : *parg = args->front();
3265 : }
3266 :
3267 : return true;
3268 : }
3269 :
3270 : // Class Go_statement.
3271 :
3272 : Bstatement*
3273 2512 : Go_statement::do_get_backend(Translate_context* context)
3274 : {
3275 2512 : Expression* fn;
3276 2512 : Expression* arg;
3277 2512 : if (!this->get_fn_and_arg(&fn, &arg))
3278 0 : return context->backend()->error_statement();
3279 :
3280 2512 : Gogo* gogo = context->gogo();
3281 2512 : Expression* call = Runtime::make_call(gogo, Runtime::GO, this->location(), 2,
3282 : fn, arg);
3283 2512 : call->determine_type_no_context(gogo);
3284 2512 : Bexpression* bcall = call->get_backend(context);
3285 2512 : Bfunction* bfunction = context->function()->func_value()->get_decl();
3286 2512 : return context->backend()->expression_statement(bfunction, bcall);
3287 : }
3288 :
3289 : // Dump the AST representation for go statement.
3290 :
3291 : void
3292 0 : Go_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3293 : {
3294 0 : ast_dump_context->print_indent();
3295 0 : ast_dump_context->ostream() << "go ";
3296 0 : ast_dump_context->dump_expression(this->call());
3297 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
3298 0 : }
3299 :
3300 : // Make a go statement.
3301 :
3302 : Statement*
3303 4941 : Statement::make_go_statement(Call_expression* call, Location location)
3304 : {
3305 4941 : return new Go_statement(call, location);
3306 : }
3307 :
3308 : // Class Defer_statement.
3309 :
3310 : Bstatement*
3311 11229 : Defer_statement::do_get_backend(Translate_context* context)
3312 : {
3313 11229 : Expression* fn;
3314 11229 : Expression* arg;
3315 11229 : if (!this->get_fn_and_arg(&fn, &arg))
3316 0 : return context->backend()->error_statement();
3317 :
3318 11229 : Gogo* gogo = context->gogo();
3319 11229 : Location loc = this->location();
3320 11229 : Expression* ds = context->function()->func_value()->defer_stack(loc);
3321 :
3322 11229 : Expression* call;
3323 11229 : if (this->on_stack_)
3324 : {
3325 10957 : if (gogo->debug_optimization())
3326 0 : go_debug(loc, "stack allocated defer");
3327 :
3328 10957 : Type* defer_type = Defer_statement::defer_struct_type();
3329 10957 : Expression* defer = Expression::make_allocation(defer_type, loc);
3330 10957 : defer->allocation_expression()->set_allocate_on_stack();
3331 10957 : defer->allocation_expression()->set_no_zero();
3332 10957 : call = Runtime::make_call(gogo, Runtime::DEFERPROCSTACK, loc, 4,
3333 : defer, ds, fn, arg);
3334 : }
3335 : else
3336 272 : call = Runtime::make_call(gogo, Runtime::DEFERPROC, loc, 3,
3337 : ds, fn, arg);
3338 11229 : call->determine_type_no_context(gogo);
3339 11229 : Bexpression* bcall = call->get_backend(context);
3340 11229 : Bfunction* bfunction = context->function()->func_value()->get_decl();
3341 11229 : return context->backend()->expression_statement(bfunction, bcall);
3342 : }
3343 :
3344 : Type*
3345 10957 : Defer_statement::defer_struct_type()
3346 : {
3347 10957 : Type* ptr_type = Type::make_pointer_type(Type::make_void_type());
3348 10957 : Type* uintptr_type = Type::lookup_integer_type("uintptr");
3349 10957 : Type* bool_type = Type::make_boolean_type();
3350 10957 : return Type::make_builtin_struct_type(9,
3351 : "link", ptr_type,
3352 : "frame", ptr_type,
3353 : "panicStack", ptr_type,
3354 : "_panic", ptr_type,
3355 : "pfn", uintptr_type,
3356 : "arg", ptr_type,
3357 : "retaddr", uintptr_type,
3358 : "makefunccanrecover", bool_type,
3359 10957 : "heap", bool_type);
3360 : }
3361 :
3362 : // Dump the AST representation for defer statement.
3363 :
3364 : void
3365 0 : Defer_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3366 : {
3367 0 : ast_dump_context->print_indent();
3368 0 : ast_dump_context->ostream() << "defer ";
3369 0 : ast_dump_context->dump_expression(this->call());
3370 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
3371 0 : }
3372 :
3373 : // Make a defer statement.
3374 :
3375 : Statement*
3376 22582 : Statement::make_defer_statement(Call_expression* call,
3377 : Location location)
3378 : {
3379 22582 : return new Defer_statement(call, location);
3380 : }
3381 :
3382 : // Class Return_statement.
3383 :
3384 : void
3385 603760 : Return_statement::do_determine_types(Gogo* gogo)
3386 : {
3387 603760 : if (this->types_are_determined_)
3388 : return;
3389 373042 : this->types_are_determined_ = true;
3390 :
3391 373042 : size_t vals_count = this->vals_ == NULL ? 0 : this->vals_->size();
3392 341510 : if (vals_count == 0)
3393 : return;
3394 :
3395 341510 : Function::Results* results =
3396 341510 : this->function_->func_value()->result_variables();
3397 683016 : size_t results_count = results == NULL ? 0 : results->size();
3398 :
3399 : // If the current function has multiple return values, and we are
3400 : // returning a single call expression, split up the call expression.
3401 341510 : if (results_count > 1
3402 341510 : && vals_count == 1
3403 341510 : && this->vals_->front()->call_expression() != NULL)
3404 : {
3405 4963 : Call_expression* call = this->vals_->front()->call_expression();
3406 4963 : call->set_expected_result_count(results_count);
3407 4963 : call->determine_type_no_context(gogo);
3408 9926 : delete this->vals_;
3409 4963 : this->vals_ = new Expression_list();
3410 15266 : for (size_t i = 0; i < results_count; ++i)
3411 10303 : this->vals_->push_back(Expression::make_call_result(call, i));
3412 : vals_count = results_count;
3413 : }
3414 :
3415 341510 : if (vals_count != results_count)
3416 : {
3417 : // This is an error which we will report later. Determine all
3418 : // types to avoid knockon errors.
3419 42 : for (Expression_list::const_iterator pe = this->vals_->begin();
3420 42 : pe != this->vals_->end();
3421 27 : ++pe)
3422 27 : (*pe)->determine_type_no_context(gogo);
3423 : return;
3424 : }
3425 :
3426 341495 : Expression_list::const_iterator pe = this->vals_->begin();
3427 341495 : for (Function::Results::const_iterator pr = results->begin();
3428 746373 : pr != results->end();
3429 404878 : ++pr, ++pe)
3430 : {
3431 404878 : Type* rvtype = (*pr)->result_var_value()->type();
3432 404878 : Type_context context(rvtype, false);
3433 404878 : (*pe)->determine_type(gogo, &context);
3434 : }
3435 : }
3436 :
3437 : void
3438 210139 : Return_statement::do_check_types(Gogo*)
3439 : {
3440 210139 : size_t vals_count = this->vals_ == NULL ? 0 : this->vals_->size();
3441 210139 : Function::Results* results =
3442 210139 : this->function_->func_value()->result_variables();
3443 409225 : size_t results_count = results == NULL ? 0 : results->size();
3444 :
3445 210139 : if (vals_count == 0)
3446 : {
3447 18953 : if (results_count > 0
3448 18953 : && !this->function_->func_value()->results_are_named())
3449 1 : this->report_error(_("not enough arguments to return"));
3450 18953 : return;
3451 : }
3452 :
3453 191186 : if (results_count == 0)
3454 : {
3455 4 : this->report_error(_("return with value in function "
3456 : "with no return type"));
3457 8 : delete this->vals_;
3458 4 : this->vals_ = NULL;
3459 4 : return;
3460 : }
3461 :
3462 191182 : if (vals_count < results_count)
3463 : {
3464 8 : this->report_error(_("not enough arguments to return"));
3465 8 : return;
3466 : }
3467 :
3468 191174 : if (vals_count > results_count)
3469 : {
3470 3 : this->report_error(_("too many values in return statement"));
3471 3 : return;
3472 : }
3473 :
3474 191171 : Expression_list::const_iterator pe = this->vals_->begin();
3475 191171 : int i = 1;
3476 191171 : for (Function::Results::const_iterator pr = results->begin();
3477 445653 : pr != results->end();
3478 254482 : ++pr, ++pe, ++i)
3479 : {
3480 254482 : Named_object* rv = *pr;
3481 254482 : Expression* e = *pe;
3482 :
3483 254482 : std::string reason;
3484 254482 : if (!Type::are_assignable(rv->result_var_value()->type(), e->type(),
3485 : &reason))
3486 : {
3487 7 : if (reason.empty())
3488 0 : go_error_at(e->location(),
3489 : "incompatible type for return value %d", i);
3490 : else
3491 7 : go_error_at(e->location(),
3492 : "incompatible type for return value %d (%s)",
3493 : i, reason.c_str());
3494 7 : this->set_is_error();
3495 : }
3496 254482 : }
3497 : }
3498 :
3499 : // Lower a return statement. If we are returning a function call
3500 : // which returns multiple values which match the current function,
3501 : // split up the call's results. If the return statement lists
3502 : // explicit values, implement this statement by assigning the values
3503 : // to the result variables and change this statement to a naked
3504 : // return. This lets panic/recover work correctly.
3505 :
3506 : Statement*
3507 789618 : Return_statement::do_lower(Gogo* gogo, Named_object*,
3508 : Block* enclosing, Statement_inserter*)
3509 : {
3510 789618 : Location loc = this->location();
3511 :
3512 789618 : if (this->classification() == STATEMENT_ERROR)
3513 0 : return Statement::make_error_statement(loc);
3514 :
3515 789618 : if (this->is_lowered_)
3516 416600 : return this;
3517 :
3518 373018 : Expression_list* vals = this->vals_;
3519 373018 : this->vals_ = NULL;
3520 373018 : this->is_lowered_ = true;
3521 :
3522 373018 : size_t vals_count = vals == NULL ? 0 : vals->size();
3523 :
3524 341487 : if (vals_count == 0)
3525 31531 : return this;
3526 :
3527 341487 : Function::Results* results =
3528 341487 : this->function_->func_value()->result_variables();
3529 682974 : size_t results_count = results == NULL ? 0 : results->size();
3530 :
3531 341487 : go_assert(vals_count == results_count);
3532 :
3533 341487 : Block* b = new Block(enclosing, loc);
3534 :
3535 341487 : Expression_list* lhs = new Expression_list();
3536 341487 : Expression_list* rhs = new Expression_list();
3537 :
3538 341487 : Expression_list::const_iterator pe = vals->begin();
3539 341487 : for (Function::Results::const_iterator pr = results->begin();
3540 746355 : pr != results->end();
3541 404868 : ++pr, ++pe)
3542 : {
3543 404868 : Named_object* rv = *pr;
3544 404868 : Expression* e = *pe;
3545 404868 : Expression* ve = Expression::make_var_reference(rv, e->location());
3546 404868 : lhs->push_back(ve);
3547 404868 : rhs->push_back(e);
3548 : }
3549 :
3550 341487 : if (lhs->size() == 1)
3551 : {
3552 287473 : Statement* s = Statement::make_assignment(lhs->front(), rhs->front(),
3553 : loc);
3554 287473 : s->determine_types(gogo);
3555 287473 : b->add_statement(s);
3556 287473 : delete lhs;
3557 287473 : delete rhs;
3558 : }
3559 : else
3560 : {
3561 54014 : Statement* s = Statement::make_tuple_assignment(lhs, rhs, loc);
3562 54014 : s->determine_types(gogo);
3563 54014 : b->add_statement(s);
3564 : }
3565 :
3566 341487 : b->add_statement(this);
3567 :
3568 341487 : delete vals;
3569 :
3570 341487 : return Statement::make_block_statement(b, loc);
3571 : }
3572 :
3573 : // Convert a return statement to the backend representation.
3574 :
3575 : Bstatement*
3576 372486 : Return_statement::do_get_backend(Translate_context* context)
3577 : {
3578 372486 : Location loc = this->location();
3579 :
3580 372486 : Function* function = context->function()->func_value();
3581 372486 : Function::Results* results = function->result_variables();
3582 372486 : std::vector<Bexpression*> retvals;
3583 372486 : if (results != NULL && !results->empty())
3584 : {
3585 361543 : retvals.reserve(results->size());
3586 361543 : for (Function::Results::const_iterator p = results->begin();
3587 795675 : p != results->end();
3588 434132 : p++)
3589 : {
3590 434132 : Expression* vr = Expression::make_var_reference(*p, loc);
3591 434132 : retvals.push_back(vr->get_backend(context));
3592 : }
3593 : }
3594 :
3595 372486 : return context->backend()->return_statement(function->get_decl(),
3596 372486 : retvals, loc);
3597 372486 : }
3598 :
3599 : // Export a return statement. At this point all the expressions have
3600 : // been converted to assignments to the result variables, so this is
3601 : // simple.
3602 :
3603 : void
3604 14161 : Return_statement::do_export_statement(Export_function_body* efb)
3605 : {
3606 14161 : efb->write_c_string("return");
3607 14161 : }
3608 :
3609 : // Dump the AST representation for a return statement.
3610 :
3611 : void
3612 0 : Return_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3613 : {
3614 0 : ast_dump_context->print_indent();
3615 0 : ast_dump_context->ostream() << "return " ;
3616 0 : ast_dump_context->dump_expression_list(this->vals_);
3617 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
3618 0 : }
3619 :
3620 : // Make a return statement.
3621 :
3622 : Return_statement*
3623 373042 : Statement::make_return_statement(Named_object* function, Expression_list* vals,
3624 : Location location)
3625 : {
3626 373042 : return new Return_statement(function, vals, location);
3627 : }
3628 :
3629 : // Make a statement that returns the result of a call expression.
3630 :
3631 : Statement*
3632 2137 : Statement::make_return_from_call(Named_object* function, Call_expression* call,
3633 : Location location)
3634 : {
3635 2137 : size_t rc = call->result_count();
3636 2137 : if (rc == 0)
3637 1349 : return Statement::make_statement(call, true);
3638 : else
3639 : {
3640 788 : Expression_list* vals = new Expression_list();
3641 788 : if (rc == 1)
3642 672 : vals->push_back(call);
3643 : else
3644 : {
3645 354 : for (size_t i = 0; i < rc; ++i)
3646 238 : vals->push_back(Expression::make_call_result(call, i));
3647 : }
3648 788 : return Statement::make_return_statement(function, vals, location);
3649 : }
3650 : }
3651 :
3652 : // A break or continue statement.
3653 :
3654 : class Bc_statement : public Statement
3655 : {
3656 : public:
3657 18944 : Bc_statement(bool is_break, Unnamed_label* label, Location location)
3658 18944 : : Statement(STATEMENT_BREAK_OR_CONTINUE, location),
3659 37888 : label_(label), is_break_(is_break)
3660 : { }
3661 :
3662 : bool
3663 : is_break() const
3664 : { return this->is_break_; }
3665 :
3666 : protected:
3667 : int
3668 475942 : do_traverse(Traverse*)
3669 475942 : { return TRAVERSE_CONTINUE; }
3670 :
3671 : bool
3672 0 : do_may_fall_through() const
3673 0 : { return false; }
3674 :
3675 : Bstatement*
3676 18830 : do_get_backend(Translate_context* context)
3677 18830 : { return this->label_->get_goto(context, this->location()); }
3678 :
3679 : void
3680 : do_dump_statement(Ast_dump_context*) const;
3681 :
3682 : private:
3683 : // The label that this branches to.
3684 : Unnamed_label* label_;
3685 : // True if this is "break", false if it is "continue".
3686 : bool is_break_;
3687 : };
3688 :
3689 : // Dump the AST representation for a break/continue statement
3690 :
3691 : void
3692 0 : Bc_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3693 : {
3694 0 : ast_dump_context->print_indent();
3695 0 : ast_dump_context->ostream() << (this->is_break_ ? "break" : "continue");
3696 0 : if (this->label_ != NULL)
3697 : {
3698 0 : ast_dump_context->ostream() << " ";
3699 0 : ast_dump_context->dump_label_name(this->label_);
3700 : }
3701 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
3702 0 : }
3703 :
3704 : // Make a break statement.
3705 :
3706 : Statement*
3707 8149 : Statement::make_break_statement(Unnamed_label* label, Location location)
3708 : {
3709 8149 : return new Bc_statement(true, label, location);
3710 : }
3711 :
3712 : // Make a continue statement.
3713 :
3714 : Statement*
3715 10795 : Statement::make_continue_statement(Unnamed_label* label,
3716 : Location location)
3717 : {
3718 10795 : return new Bc_statement(false, label, location);
3719 : }
3720 :
3721 : // Class Goto_statement.
3722 :
3723 : int
3724 130014 : Goto_statement::do_traverse(Traverse*)
3725 : {
3726 130014 : return TRAVERSE_CONTINUE;
3727 : }
3728 :
3729 : // Check types for a label. There aren't any types per se, but we use
3730 : // this to give an error if the label was never defined.
3731 :
3732 : void
3733 2101 : Goto_statement::do_check_types(Gogo*)
3734 : {
3735 2101 : if (!this->label_->is_defined())
3736 : {
3737 3 : go_error_at(this->location(), "reference to undefined label %qs",
3738 3 : Gogo::message_name(this->label_->name()).c_str());
3739 3 : this->set_is_error();
3740 : }
3741 2101 : }
3742 :
3743 : // Convert the goto statement to the backend representation.
3744 :
3745 : Bstatement*
3746 10842 : Goto_statement::do_get_backend(Translate_context* context)
3747 : {
3748 10842 : Blabel* blabel = this->label_->get_backend_label(context);
3749 10842 : return context->backend()->goto_statement(blabel, this->location());
3750 : }
3751 :
3752 : // Export a goto statement.
3753 :
3754 : void
3755 8 : Goto_statement::do_export_statement(Export_function_body *efb)
3756 : {
3757 8 : efb->write_c_string("goto ");
3758 8 : efb->write_string(this->label_->name());
3759 8 : }
3760 :
3761 : // Import a goto or goto unnamed statement.
3762 :
3763 : Statement*
3764 1523 : Goto_statement::do_import(Import_function_body* ifb, Location loc)
3765 : {
3766 1523 : ifb->require_c_string("goto ");
3767 1523 : std::string id = ifb->read_identifier();
3768 1523 : if (id[0] != '$')
3769 : {
3770 1 : Function* fn = ifb->function()->func_value();
3771 1 : Label* label = fn->add_label_reference(ifb->gogo(), id, loc, false);
3772 1 : return Statement::make_goto_statement(label, loc);
3773 : }
3774 : else
3775 : {
3776 1522 : if (id[1] != 'l')
3777 : {
3778 0 : if (!ifb->saw_error())
3779 0 : go_error_at(loc,
3780 : ("invalid export data for %qs: "
3781 : "bad unnamed label at %lu"),
3782 0 : ifb->name().c_str(),
3783 0 : static_cast<unsigned long>(ifb->off()));
3784 0 : ifb->set_saw_error();
3785 0 : return Statement::make_error_statement(loc);
3786 : }
3787 1522 : const char* p = id.c_str();
3788 1522 : char* end;
3789 1522 : long idx = strtol(p + 2, &end, 10);
3790 1522 : if (*end != '\0' || idx > 0x7fffffff)
3791 : {
3792 0 : if (!ifb->saw_error())
3793 0 : go_error_at(loc,
3794 : ("invalid export data for %qs: "
3795 : "bad unnamed label index at %lu"),
3796 0 : ifb->name().c_str(),
3797 0 : static_cast<unsigned long>(ifb->off()));
3798 0 : ifb->set_saw_error();
3799 0 : return Statement::make_error_statement(loc);
3800 : }
3801 :
3802 1522 : Unnamed_label* label = ifb->unnamed_label(idx, loc);
3803 1522 : return Statement::make_goto_unnamed_statement(label, loc);
3804 : }
3805 1523 : }
3806 :
3807 : // Dump the AST representation for a goto statement.
3808 :
3809 : void
3810 0 : Goto_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3811 : {
3812 0 : ast_dump_context->print_indent();
3813 0 : ast_dump_context->ostream() << "goto " << this->label_->name() << dsuffix(location()) << std::endl;
3814 0 : }
3815 :
3816 : // Make a goto statement.
3817 :
3818 : Statement*
3819 10942 : Statement::make_goto_statement(Label* label, Location location)
3820 : {
3821 10942 : return new Goto_statement(label, location);
3822 : }
3823 :
3824 : // Class Goto_unnamed_statement.
3825 :
3826 : int
3827 3378213 : Goto_unnamed_statement::do_traverse(Traverse*)
3828 : {
3829 3378213 : return TRAVERSE_CONTINUE;
3830 : }
3831 :
3832 : // Convert the goto unnamed statement to the backend representation.
3833 :
3834 : Bstatement*
3835 175104 : Goto_unnamed_statement::do_get_backend(Translate_context* context)
3836 : {
3837 175104 : return this->label_->get_goto(context, this->location());
3838 : }
3839 :
3840 : // Export a goto unnamed statement.
3841 :
3842 : void
3843 1703 : Goto_unnamed_statement::do_export_statement(Export_function_body *efb)
3844 : {
3845 1703 : unsigned int index = efb->unnamed_label_index(this->label_);
3846 1703 : char buf[100];
3847 1703 : snprintf(buf, sizeof buf, "goto $l%u", index);
3848 1703 : efb->write_c_string(buf);
3849 1703 : }
3850 :
3851 : // Dump the AST representation for an unnamed goto statement
3852 :
3853 : void
3854 0 : Goto_unnamed_statement::do_dump_statement(
3855 : Ast_dump_context* ast_dump_context) const
3856 : {
3857 0 : ast_dump_context->print_indent();
3858 0 : ast_dump_context->ostream() << "goto ";
3859 0 : ast_dump_context->dump_label_name(this->label_);
3860 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
3861 0 : }
3862 :
3863 : // Make a goto statement to an unnamed label.
3864 :
3865 : Statement*
3866 175691 : Statement::make_goto_unnamed_statement(Unnamed_label* label,
3867 : Location location)
3868 : {
3869 175691 : return new Goto_unnamed_statement(label, location);
3870 : }
3871 :
3872 : // Class Label_statement.
3873 :
3874 : // Traversal.
3875 :
3876 : int
3877 120608 : Label_statement::do_traverse(Traverse*)
3878 : {
3879 120608 : return TRAVERSE_CONTINUE;
3880 : }
3881 :
3882 : // Return the backend representation of the statement defining this
3883 : // label.
3884 :
3885 : Bstatement*
3886 10415 : Label_statement::do_get_backend(Translate_context* context)
3887 : {
3888 10415 : if (this->label_->is_dummy_label())
3889 : {
3890 3 : Bexpression* bce = context->backend()->boolean_constant_expression(false);
3891 3 : Bfunction* bfunction = context->function()->func_value()->get_decl();
3892 3 : return context->backend()->expression_statement(bfunction, bce);
3893 : }
3894 10412 : Blabel* blabel = this->label_->get_backend_label(context);
3895 10412 : return context->backend()->label_definition_statement(blabel);
3896 : }
3897 :
3898 : // Export a label.
3899 :
3900 : void
3901 8 : Label_statement::do_export_statement(Export_function_body* efb)
3902 : {
3903 8 : if (this->label_->is_dummy_label())
3904 : return;
3905 : // We use a leading colon, not a trailing one, to simplify import.
3906 8 : efb->write_c_string(":");
3907 8 : efb->write_string(this->label_->name());
3908 : }
3909 :
3910 : // Import a label or an unnamed label.
3911 :
3912 : Statement*
3913 1434 : Label_statement::do_import(Import_function_body* ifb, Location loc)
3914 : {
3915 1434 : ifb->require_c_string(":");
3916 1434 : std::string id = ifb->read_identifier();
3917 1434 : if (id[0] != '$')
3918 : {
3919 1 : Function* fn = ifb->function()->func_value();
3920 1 : Label* label = fn->add_label_definition(ifb->gogo(), id, loc);
3921 1 : return Statement::make_label_statement(label, loc);
3922 : }
3923 : else
3924 : {
3925 1433 : if (id[1] != 'l')
3926 : {
3927 0 : if (!ifb->saw_error())
3928 0 : go_error_at(loc,
3929 : ("invalid export data for %qs: "
3930 : "bad unnamed label at %lu"),
3931 0 : ifb->name().c_str(),
3932 0 : static_cast<unsigned long>(ifb->off()));
3933 0 : ifb->set_saw_error();
3934 0 : return Statement::make_error_statement(loc);
3935 : }
3936 1433 : const char* p = id.c_str();
3937 1433 : char* end;
3938 1433 : long idx = strtol(p + 2, &end, 10);
3939 1433 : if (*end != '\0' || idx > 0x7fffffff)
3940 : {
3941 0 : if (!ifb->saw_error())
3942 0 : go_error_at(loc,
3943 : ("invalid export data for %qs: "
3944 : "bad unnamed label index at %lu"),
3945 0 : ifb->name().c_str(),
3946 0 : static_cast<unsigned long>(ifb->off()));
3947 0 : ifb->set_saw_error();
3948 0 : return Statement::make_error_statement(loc);
3949 : }
3950 :
3951 1433 : Unnamed_label* label = ifb->unnamed_label(idx, loc);
3952 1433 : return Statement::make_unnamed_label_statement(label);
3953 : }
3954 1434 : }
3955 :
3956 : // Dump the AST for a label definition statement.
3957 :
3958 : void
3959 0 : Label_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
3960 : {
3961 0 : ast_dump_context->print_indent();
3962 0 : ast_dump_context->ostream() << this->label_->name() << ":" << dsuffix(location()) << std::endl;
3963 0 : }
3964 :
3965 : // Make a label statement.
3966 :
3967 : Statement*
3968 10526 : Statement::make_label_statement(Label* label, Location location)
3969 : {
3970 10526 : return new Label_statement(label, location);
3971 : }
3972 :
3973 : // Class Unnamed_label_statement.
3974 :
3975 167230 : Unnamed_label_statement::Unnamed_label_statement(Unnamed_label* label)
3976 : : Statement(STATEMENT_UNNAMED_LABEL, label->location()),
3977 167230 : label_(label)
3978 167230 : { }
3979 :
3980 : int
3981 3185853 : Unnamed_label_statement::do_traverse(Traverse*)
3982 : {
3983 3185853 : return TRAVERSE_CONTINUE;
3984 : }
3985 :
3986 : // Get the backend definition for this unnamed label statement.
3987 :
3988 : Bstatement*
3989 166614 : Unnamed_label_statement::do_get_backend(Translate_context* context)
3990 : {
3991 166614 : return this->label_->get_definition(context);
3992 : }
3993 :
3994 : // Export an unnamed label.
3995 :
3996 : void
3997 1641 : Unnamed_label_statement::do_export_statement(Export_function_body* efb)
3998 : {
3999 1641 : unsigned int index = efb->unnamed_label_index(this->label_);
4000 1641 : char buf[50];
4001 : // We use a leading colon, not a trailing one, to simplify import.
4002 1641 : snprintf(buf, sizeof buf, ":$l%u", index);
4003 1641 : efb->write_c_string(buf);
4004 1641 : }
4005 :
4006 : // Dump the AST representation for an unnamed label definition statement.
4007 :
4008 : void
4009 0 : Unnamed_label_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
4010 : const
4011 : {
4012 0 : ast_dump_context->print_indent();
4013 0 : ast_dump_context->dump_label_name(this->label_);
4014 0 : ast_dump_context->ostream() << ":" << dsuffix(location()) << std::endl;
4015 0 : }
4016 :
4017 : // Make an unnamed label statement.
4018 :
4019 : Statement*
4020 167230 : Statement::make_unnamed_label_statement(Unnamed_label* label)
4021 : {
4022 167230 : return new Unnamed_label_statement(label);
4023 : }
4024 :
4025 : // Class If_statement.
4026 :
4027 : // Traversal.
4028 :
4029 : int
4030 9826893 : If_statement::do_traverse(Traverse* traverse)
4031 : {
4032 9826893 : if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT
4033 9826893 : || this->then_block_->traverse(traverse) == TRAVERSE_EXIT)
4034 359153 : return TRAVERSE_EXIT;
4035 9467740 : if (this->else_block_ != NULL)
4036 : {
4037 664448 : if (this->else_block_->traverse(traverse) == TRAVERSE_EXIT)
4038 : return TRAVERSE_EXIT;
4039 : }
4040 : return TRAVERSE_CONTINUE;
4041 : }
4042 :
4043 : void
4044 814416 : If_statement::do_determine_types(Gogo* gogo)
4045 : {
4046 814416 : Type_context context(Type::lookup_bool_type(), false);
4047 814416 : this->cond_->determine_type(gogo, &context);
4048 814416 : this->then_block_->determine_types(gogo);
4049 814416 : if (this->else_block_ != NULL)
4050 240906 : this->else_block_->determine_types(gogo);
4051 814416 : }
4052 :
4053 : // Check types.
4054 :
4055 : void
4056 254022 : If_statement::do_check_types(Gogo*)
4057 : {
4058 254022 : Type* type = this->cond_->type();
4059 254022 : if (type->is_error())
4060 12 : this->set_is_error();
4061 254010 : else if (!type->is_boolean_type())
4062 3 : this->report_error(_("expected boolean expression"));
4063 254022 : }
4064 :
4065 : // Whether the overall statement may fall through.
4066 :
4067 : bool
4068 342 : If_statement::do_may_fall_through() const
4069 : {
4070 342 : return (this->else_block_ == NULL
4071 329 : || this->then_block_->may_fall_through()
4072 670 : || this->else_block_->may_fall_through());
4073 : }
4074 :
4075 : // Get the backend representation.
4076 :
4077 : Bstatement*
4078 698859 : If_statement::do_get_backend(Translate_context* context)
4079 : {
4080 698859 : go_assert(this->cond_->type()->is_boolean_type()
4081 : || this->cond_->type()->is_error());
4082 698859 : Bexpression* cond = this->cond_->get_backend(context);
4083 698859 : Bblock* then_block = this->then_block_->get_backend(context);
4084 698859 : Bblock* else_block = (this->else_block_ == NULL
4085 698859 : ? NULL
4086 235592 : : this->else_block_->get_backend(context));
4087 698859 : Bfunction* bfunction = context->function()->func_value()->get_decl();
4088 698859 : return context->backend()->if_statement(bfunction,
4089 : cond, then_block, else_block,
4090 698859 : this->location());
4091 : }
4092 :
4093 : // Export an if statement.
4094 :
4095 : void
4096 4529 : If_statement::do_export_statement(Export_function_body* efb)
4097 : {
4098 4529 : efb->write_c_string("if ");
4099 4529 : this->cond_->export_expression(efb);
4100 4529 : efb->write_c_string(" ");
4101 4529 : Block_statement::export_block(efb, this->then_block_, false);
4102 4529 : if (this->else_block_ != NULL)
4103 : {
4104 70 : efb->write_c_string(" else ");
4105 70 : Block_statement::export_block(efb, this->else_block_, false);
4106 : }
4107 4529 : }
4108 :
4109 : // Import an if statement.
4110 :
4111 : Statement*
4112 5427 : If_statement::do_import(Import_function_body* ifb, Location loc)
4113 : {
4114 5427 : ifb->require_c_string("if ");
4115 :
4116 5427 : Expression* cond = Expression::import_expression(ifb, loc);
4117 5427 : ifb->require_c_string(" ");
4118 :
4119 5427 : if (!ifb->match_c_string("{"))
4120 : {
4121 0 : if (!ifb->saw_error())
4122 0 : go_error_at(ifb->location(),
4123 : "import error for %qs: no block for if statement at %lu",
4124 0 : ifb->name().c_str(),
4125 0 : static_cast<unsigned long>(ifb->off()));
4126 0 : ifb->set_saw_error();
4127 0 : return Statement::make_error_statement(loc);
4128 : }
4129 :
4130 5427 : bool is_lowered_for_statement;
4131 5427 : Block* then_block = Block_statement::do_import(ifb, loc,
4132 : &is_lowered_for_statement);
4133 5427 : if (then_block == NULL)
4134 0 : return Statement::make_error_statement(loc);
4135 5427 : if (is_lowered_for_statement)
4136 : {
4137 0 : if (!ifb->saw_error())
4138 0 : go_error_at(ifb->location(),
4139 : ("import error for %qs: "
4140 : "unexpected lowered for in if statement at %lu"),
4141 0 : ifb->name().c_str(),
4142 0 : static_cast<unsigned long>(ifb->off()));
4143 0 : ifb->set_saw_error();
4144 0 : return Statement::make_error_statement(loc);
4145 : }
4146 :
4147 5427 : Block* else_block = NULL;
4148 5427 : if (ifb->match_c_string(" else "))
4149 : {
4150 136 : ifb->advance(6);
4151 136 : if (!ifb->match_c_string("{"))
4152 : {
4153 0 : if (!ifb->saw_error())
4154 0 : go_error_at(ifb->location(),
4155 : ("import error for %qs: no else block "
4156 : "for if statement at %lu"),
4157 0 : ifb->name().c_str(),
4158 0 : static_cast<unsigned long>(ifb->off()));
4159 0 : ifb->set_saw_error();
4160 0 : return Statement::make_error_statement(loc);
4161 : }
4162 :
4163 136 : else_block = Block_statement::do_import(ifb, loc,
4164 : &is_lowered_for_statement);
4165 136 : if (else_block == NULL)
4166 0 : return Statement::make_error_statement(loc);
4167 136 : if (is_lowered_for_statement)
4168 : {
4169 0 : if (!ifb->saw_error())
4170 0 : go_error_at(ifb->location(),
4171 : ("import error for %qs: "
4172 : "unexpected lowered for in if statement at %lu"),
4173 0 : ifb->name().c_str(),
4174 0 : static_cast<unsigned long>(ifb->off()));
4175 0 : ifb->set_saw_error();
4176 0 : return Statement::make_error_statement(loc);
4177 : }
4178 : }
4179 :
4180 5427 : return Statement::make_if_statement(cond, then_block, else_block, loc);
4181 : }
4182 :
4183 : // Dump the AST representation for an if statement
4184 :
4185 : void
4186 0 : If_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
4187 : {
4188 0 : ast_dump_context->print_indent();
4189 0 : ast_dump_context->ostream() << "if ";
4190 0 : ast_dump_context->dump_expression(this->cond_);
4191 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
4192 0 : if (ast_dump_context->dump_subblocks())
4193 : {
4194 0 : ast_dump_context->dump_block(this->then_block_);
4195 0 : if (this->else_block_ != NULL)
4196 : {
4197 0 : ast_dump_context->print_indent();
4198 0 : ast_dump_context->ostream() << "else" << std::endl;
4199 0 : ast_dump_context->dump_block(this->else_block_);
4200 : }
4201 : }
4202 0 : }
4203 :
4204 : // Make an if statement.
4205 :
4206 : Statement*
4207 704198 : Statement::make_if_statement(Expression* cond, Block* then_block,
4208 : Block* else_block, Location location)
4209 : {
4210 704198 : return new If_statement(cond, then_block, else_block, location);
4211 : }
4212 :
4213 : // Class Case_clauses::Hash_integer_value.
4214 :
4215 : class Case_clauses::Hash_integer_value
4216 : {
4217 : public:
4218 : size_t
4219 : operator()(Expression*) const;
4220 : };
4221 :
4222 : size_t
4223 33164 : Case_clauses::Hash_integer_value::operator()(Expression* pe) const
4224 : {
4225 33164 : Numeric_constant nc;
4226 33164 : mpz_t ival;
4227 33164 : if (!pe->numeric_constant_value(&nc) || !nc.to_int(&ival))
4228 0 : go_unreachable();
4229 33164 : size_t ret = mpz_get_ui(ival);
4230 33164 : mpz_clear(ival);
4231 66328 : return ret;
4232 33164 : }
4233 :
4234 : // Class Case_clauses::Eq_integer_value.
4235 :
4236 : class Case_clauses::Eq_integer_value
4237 : {
4238 : public:
4239 : bool
4240 : operator()(Expression*, Expression*) const;
4241 : };
4242 :
4243 : bool
4244 47 : Case_clauses::Eq_integer_value::operator()(Expression* a, Expression* b) const
4245 : {
4246 47 : Numeric_constant anc;
4247 47 : mpz_t aval;
4248 47 : Numeric_constant bnc;
4249 47 : mpz_t bval;
4250 47 : if (!a->numeric_constant_value(&anc)
4251 47 : || !anc.to_int(&aval)
4252 47 : || !b->numeric_constant_value(&bnc)
4253 94 : || !bnc.to_int(&bval))
4254 0 : go_unreachable();
4255 47 : bool ret = mpz_cmp(aval, bval) == 0;
4256 47 : mpz_clear(aval);
4257 47 : mpz_clear(bval);
4258 94 : return ret;
4259 47 : }
4260 :
4261 : // Class Case_clauses::Case_clause.
4262 :
4263 : // Traversal.
4264 :
4265 : int
4266 668704 : Case_clauses::Case_clause::traverse(Traverse* traverse)
4267 : {
4268 668704 : if (this->cases_ != NULL
4269 668704 : && (traverse->traverse_mask()
4270 588252 : & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
4271 : {
4272 463414 : if (this->cases_->traverse(traverse) == TRAVERSE_EXIT)
4273 : return TRAVERSE_EXIT;
4274 : }
4275 668704 : if (this->statements_ != NULL)
4276 : {
4277 652097 : if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
4278 : return TRAVERSE_EXIT;
4279 : }
4280 : return TRAVERSE_CONTINUE;
4281 : }
4282 :
4283 : // Check whether all the case expressions are integer constants.
4284 :
4285 : bool
4286 23577 : Case_clauses::Case_clause::is_constant() const
4287 : {
4288 23577 : if (this->cases_ != NULL)
4289 : {
4290 20882 : for (Expression_list::const_iterator p = this->cases_->begin();
4291 54158 : p != this->cases_->end();
4292 33276 : ++p)
4293 66617 : if (!(*p)->is_constant() || (*p)->type()->integer_type() == NULL)
4294 65 : return false;
4295 : }
4296 : return true;
4297 : }
4298 :
4299 : // Lower a case clause for a nonconstant switch. VAL_TEMP is the
4300 : // value we are switching on; it may be NULL. If START_LABEL is not
4301 : // NULL, it goes at the start of the statements, after the condition
4302 : // test. We branch to FINISH_LABEL at the end of the statements.
4303 :
4304 : void
4305 16686 : Case_clauses::Case_clause::lower(Gogo* gogo, Block* b,
4306 : Temporary_statement* val_temp,
4307 : Unnamed_label* start_label,
4308 : Unnamed_label* finish_label) const
4309 : {
4310 16686 : Location loc = this->location_;
4311 16686 : Unnamed_label* next_case_label;
4312 16686 : if (this->cases_ == NULL || this->cases_->empty())
4313 : {
4314 2671 : go_assert(this->is_default_);
4315 : next_case_label = NULL;
4316 : }
4317 : else
4318 : {
4319 : Expression* cond = NULL;
4320 :
4321 17902 : for (Expression_list::const_iterator p = this->cases_->begin();
4322 31917 : p != this->cases_->end();
4323 17902 : ++p)
4324 : {
4325 17902 : Expression* ref = Expression::make_temporary_reference(val_temp,
4326 : loc);
4327 35804 : Expression* this_cond = Expression::make_binary(OPERATOR_EQEQ, ref,
4328 17902 : *p, loc);
4329 17902 : if (cond == NULL)
4330 : cond = this_cond;
4331 : else
4332 3887 : cond = Expression::make_binary(OPERATOR_OROR, cond, this_cond, loc);
4333 : }
4334 :
4335 14015 : Block* then_block = new Block(b, loc);
4336 14015 : next_case_label = new Unnamed_label(Linemap::unknown_location());
4337 14015 : Statement* s = Statement::make_goto_unnamed_statement(next_case_label,
4338 : loc);
4339 14015 : then_block->add_statement(s);
4340 :
4341 : // if !COND { goto NEXT_CASE_LABEL }
4342 14015 : cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
4343 14015 : s = Statement::make_if_statement(cond, then_block, NULL, loc);
4344 14015 : s->determine_types(gogo);
4345 14015 : b->add_statement(s);
4346 : }
4347 :
4348 16686 : if (start_label != NULL)
4349 115 : b->add_statement(Statement::make_unnamed_label_statement(start_label));
4350 :
4351 16686 : if (this->statements_ != NULL)
4352 15974 : b->add_statement(Statement::make_block_statement(this->statements_, loc));
4353 :
4354 16686 : Statement* s = Statement::make_goto_unnamed_statement(finish_label, loc);
4355 16686 : b->add_statement(s);
4356 :
4357 16686 : if (next_case_label != NULL)
4358 14015 : b->add_statement(Statement::make_unnamed_label_statement(next_case_label));
4359 16686 : }
4360 :
4361 : // Determine types.
4362 :
4363 : void
4364 40214 : Case_clauses::Case_clause::determine_types(Gogo* gogo, Type* type)
4365 : {
4366 40214 : if (this->cases_ != NULL)
4367 : {
4368 34843 : Type_context case_context(type, false);
4369 85934 : for (Expression_list::iterator p = this->cases_->begin();
4370 85934 : p != this->cases_->end();
4371 51091 : ++p)
4372 51091 : (*p)->determine_type(gogo, &case_context);
4373 : }
4374 40214 : if (this->statements_ != NULL)
4375 38955 : this->statements_->determine_types(gogo);
4376 40214 : }
4377 :
4378 : // Check types. Returns false if there was an error.
4379 :
4380 : bool
4381 40210 : Case_clauses::Case_clause::check_types(Type* type)
4382 : {
4383 40210 : if (this->cases_ != NULL)
4384 : {
4385 34841 : for (Expression_list::iterator p = this->cases_->begin();
4386 85922 : p != this->cases_->end();
4387 51081 : ++p)
4388 : {
4389 51089 : std::string reason;
4390 51089 : if (!Type::are_compatible_for_comparison(true, type, (*p)->type(),
4391 : &reason))
4392 : {
4393 8 : go_error_at(this->location_, "%s", reason.c_str());
4394 8 : return false;
4395 : }
4396 51089 : }
4397 : }
4398 : return true;
4399 : }
4400 :
4401 : // Return true if this clause may fall through to the following
4402 : // statements. Note that this is not the same as whether the case
4403 : // uses the "fallthrough" keyword.
4404 :
4405 : bool
4406 4442 : Case_clauses::Case_clause::may_fall_through() const
4407 : {
4408 4442 : if (this->statements_ == NULL)
4409 : return true;
4410 4433 : return this->statements_->may_fall_through();
4411 : }
4412 :
4413 : // Convert the case values and statements to the backend
4414 : // representation. BREAK_LABEL is the label which break statements
4415 : // should branch to. CASE_CONSTANTS is used to detect duplicate
4416 : // constants. *CASES should be passed as an empty vector; the values
4417 : // for this case will be added to it. If this is the default case,
4418 : // *CASES will remain empty. This returns the statement to execute if
4419 : // one of these cases is selected.
4420 :
4421 : Bstatement*
4422 23489 : Case_clauses::Case_clause::get_backend(Translate_context* context,
4423 : Unnamed_label* break_label,
4424 : Case_constants* case_constants,
4425 : std::vector<Bexpression*>* cases) const
4426 : {
4427 23489 : if (this->cases_ != NULL)
4428 : {
4429 20803 : go_assert(!this->is_default_);
4430 53967 : for (Expression_list::const_iterator p = this->cases_->begin();
4431 53967 : p != this->cases_->end();
4432 33164 : ++p)
4433 : {
4434 33164 : Expression* e = *p;
4435 33164 : if (e->classification() != Expression::EXPRESSION_INTEGER)
4436 : {
4437 23741 : Numeric_constant nc;
4438 23741 : mpz_t ival;
4439 23741 : if (!(*p)->numeric_constant_value(&nc) || !nc.to_int(&ival))
4440 : {
4441 : // Something went wrong. This can happen with a
4442 : // negative constant and an unsigned switch value.
4443 0 : go_assert(saw_errors());
4444 0 : continue;
4445 : }
4446 23741 : go_assert(nc.type() != NULL);
4447 23741 : e = Expression::make_integer_z(&ival, nc.type(), e->location());
4448 23741 : mpz_clear(ival);
4449 23741 : }
4450 :
4451 33164 : std::pair<Case_constants::iterator, bool> ins =
4452 33164 : case_constants->insert(e);
4453 33164 : if (!ins.second)
4454 : {
4455 : // Value was already present.
4456 3 : go_error_at(this->location_, "duplicate case in switch");
4457 3 : e = Expression::make_error(this->location_);
4458 : }
4459 33164 : cases->push_back(e->get_backend(context));
4460 : }
4461 : }
4462 :
4463 23489 : Bstatement* statements;
4464 23489 : if (this->statements_ == NULL)
4465 : statements = NULL;
4466 : else
4467 : {
4468 22967 : Bblock* bblock = this->statements_->get_backend(context);
4469 22967 : statements = context->backend()->block_statement(bblock);
4470 : }
4471 :
4472 23489 : Bstatement* break_stat;
4473 23489 : if (this->is_fallthrough_)
4474 : break_stat = NULL;
4475 : else
4476 23128 : break_stat = break_label->get_goto(context, this->location_);
4477 :
4478 23489 : if (statements == NULL)
4479 : return break_stat;
4480 22967 : else if (break_stat == NULL)
4481 : return statements;
4482 : else
4483 22625 : return context->backend()->compound_statement(statements, break_stat);
4484 : }
4485 :
4486 : // Dump the AST representation for a case clause
4487 :
4488 : void
4489 0 : Case_clauses::Case_clause::dump_clause(Ast_dump_context* ast_dump_context)
4490 : const
4491 : {
4492 0 : ast_dump_context->print_indent();
4493 0 : if (this->is_default_)
4494 : {
4495 0 : ast_dump_context->ostream() << "default:";
4496 : }
4497 : else
4498 : {
4499 0 : ast_dump_context->ostream() << "case ";
4500 0 : ast_dump_context->dump_expression_list(this->cases_);
4501 0 : ast_dump_context->ostream() << ":" ;
4502 : }
4503 0 : ast_dump_context->dump_block(this->statements_);
4504 0 : if (this->is_fallthrough_)
4505 : {
4506 0 : ast_dump_context->print_indent();
4507 0 : ast_dump_context->ostream() << " (fallthrough)" << dsuffix(location()) << std::endl;
4508 : }
4509 0 : }
4510 :
4511 : // Class Case_clauses.
4512 :
4513 : // Traversal.
4514 :
4515 : int
4516 172198 : Case_clauses::traverse(Traverse* traverse)
4517 : {
4518 840902 : for (Clauses::iterator p = this->clauses_.begin();
4519 840902 : p != this->clauses_.end();
4520 668704 : ++p)
4521 : {
4522 668704 : if (p->traverse(traverse) == TRAVERSE_EXIT)
4523 172198 : return TRAVERSE_EXIT;
4524 : }
4525 : return TRAVERSE_CONTINUE;
4526 : }
4527 :
4528 : // Check whether all the case expressions are constant.
4529 :
4530 : bool
4531 5916 : Case_clauses::is_constant() const
4532 : {
4533 29428 : for (Clauses::const_iterator p = this->clauses_.begin();
4534 29428 : p != this->clauses_.end();
4535 23512 : ++p)
4536 23577 : if (!p->is_constant())
4537 5916 : return false;
4538 : return true;
4539 : }
4540 :
4541 : // Lower case clauses for a nonconstant switch.
4542 :
4543 : void
4544 5301 : Case_clauses::lower(Gogo* gogo, Block* b, Temporary_statement* val_temp,
4545 : Unnamed_label* break_label) const
4546 : {
4547 : // The default case.
4548 5301 : const Case_clause* default_case = NULL;
4549 :
4550 : // The label for the fallthrough of the previous case.
4551 5301 : Unnamed_label* last_fallthrough_label = NULL;
4552 :
4553 : // The label for the start of the default case. This is used if the
4554 : // case before the default case falls through.
4555 5301 : Unnamed_label* default_start_label = NULL;
4556 :
4557 : // The label for the end of the default case. This normally winds
4558 : // up as BREAK_LABEL, but it will be different if the default case
4559 : // falls through.
4560 5301 : Unnamed_label* default_finish_label = NULL;
4561 :
4562 21987 : for (Clauses::const_iterator p = this->clauses_.begin();
4563 21987 : p != this->clauses_.end();
4564 16686 : ++p)
4565 : {
4566 : // The label to use for the start of the statements for this
4567 : // case. This is NULL unless the previous case falls through.
4568 16686 : Unnamed_label* start_label = last_fallthrough_label;
4569 :
4570 : // The label to jump to after the end of the statements for this
4571 : // case.
4572 16686 : Unnamed_label* finish_label = break_label;
4573 :
4574 16686 : last_fallthrough_label = NULL;
4575 16686 : if (p->is_fallthrough() && p + 1 != this->clauses_.end())
4576 : {
4577 115 : finish_label = new Unnamed_label(p->location());
4578 115 : last_fallthrough_label = finish_label;
4579 : }
4580 :
4581 16686 : if (!p->is_default())
4582 14015 : p->lower(gogo, b, val_temp, start_label, finish_label);
4583 : else
4584 : {
4585 : // We have to move the default case to the end, so that we
4586 : // only use it if all the other tests fail.
4587 : default_case = &*p;
4588 : default_start_label = start_label;
4589 : default_finish_label = finish_label;
4590 : }
4591 : }
4592 :
4593 5301 : if (default_case != NULL)
4594 2671 : default_case->lower(gogo, b, val_temp, default_start_label,
4595 : default_finish_label);
4596 5301 : }
4597 :
4598 : // Determine types.
4599 :
4600 : void
4601 11185 : Case_clauses::determine_types(Gogo* gogo, Type* type)
4602 : {
4603 51399 : for (Clauses::iterator p = this->clauses_.begin();
4604 51399 : p != this->clauses_.end();
4605 40214 : ++p)
4606 40214 : p->determine_types(gogo, type);
4607 11185 : }
4608 :
4609 : // Check types. Returns false if there was an error.
4610 :
4611 : bool
4612 11182 : Case_clauses::check_types(Type* type)
4613 : {
4614 11182 : bool ret = true;
4615 51392 : for (Clauses::iterator p = this->clauses_.begin();
4616 51392 : p != this->clauses_.end();
4617 40210 : ++p)
4618 : {
4619 40210 : if (!p->check_types(type))
4620 8 : ret = false;
4621 : }
4622 11182 : return ret;
4623 : }
4624 :
4625 : // Return true if these clauses may fall through to the statements
4626 : // following the switch statement.
4627 :
4628 : bool
4629 1011 : Case_clauses::may_fall_through() const
4630 : {
4631 1011 : bool found_default = false;
4632 5453 : for (Clauses::const_iterator p = this->clauses_.begin();
4633 5453 : p != this->clauses_.end();
4634 4442 : ++p)
4635 : {
4636 4442 : if (p->may_fall_through() && !p->is_fallthrough())
4637 1011 : return true;
4638 4442 : if (p->is_default())
4639 987 : found_default = true;
4640 : }
4641 1011 : return !found_default;
4642 : }
4643 :
4644 : // Convert the cases to the backend representation. This sets
4645 : // *ALL_CASES and *ALL_STATEMENTS.
4646 :
4647 : void
4648 5840 : Case_clauses::get_backend(Translate_context* context,
4649 : Unnamed_label* break_label,
4650 : std::vector<std::vector<Bexpression*> >* all_cases,
4651 : std::vector<Bstatement*>* all_statements) const
4652 : {
4653 5840 : Case_constants case_constants;
4654 :
4655 5840 : size_t c = this->clauses_.size();
4656 5840 : all_cases->resize(c);
4657 5840 : all_statements->resize(c);
4658 :
4659 5840 : size_t i = 0;
4660 5840 : for (Clauses::const_iterator p = this->clauses_.begin();
4661 29329 : p != this->clauses_.end();
4662 23489 : ++p, ++i)
4663 : {
4664 23489 : std::vector<Bexpression*> cases;
4665 23489 : Bstatement* stat = p->get_backend(context, break_label, &case_constants,
4666 : &cases);
4667 : // The final clause can't fall through.
4668 23489 : if (i == c - 1 && p->is_fallthrough())
4669 : {
4670 2 : go_assert(saw_errors());
4671 2 : stat = context->backend()->error_statement();
4672 : }
4673 23489 : (*all_cases)[i].swap(cases);
4674 23489 : (*all_statements)[i] = stat;
4675 23489 : }
4676 5840 : }
4677 :
4678 : // Dump the AST representation for case clauses (from a switch statement)
4679 :
4680 : void
4681 0 : Case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
4682 : {
4683 0 : for (Clauses::const_iterator p = this->clauses_.begin();
4684 0 : p != this->clauses_.end();
4685 0 : ++p)
4686 0 : p->dump_clause(ast_dump_context);
4687 0 : }
4688 :
4689 : // A constant switch statement. A Switch_statement is lowered to this
4690 : // when all the cases are constants.
4691 :
4692 : class Constant_switch_statement : public Statement
4693 : {
4694 : public:
4695 5851 : Constant_switch_statement(Expression* val, Case_clauses* clauses,
4696 : Unnamed_label* break_label,
4697 : Location location)
4698 5851 : : Statement(STATEMENT_CONSTANT_SWITCH, location),
4699 11702 : val_(val), clauses_(clauses), break_label_(break_label)
4700 : { }
4701 :
4702 : protected:
4703 : int
4704 : do_traverse(Traverse*);
4705 :
4706 : Bstatement*
4707 : do_get_backend(Translate_context*);
4708 :
4709 : void
4710 : do_dump_statement(Ast_dump_context*) const;
4711 :
4712 : private:
4713 : // The value to switch on.
4714 : Expression* val_;
4715 : // The case clauses.
4716 : Case_clauses* clauses_;
4717 : // The break label, if needed.
4718 : Unnamed_label* break_label_;
4719 : };
4720 :
4721 : // Traversal.
4722 :
4723 : int
4724 138161 : Constant_switch_statement::do_traverse(Traverse* traverse)
4725 : {
4726 138161 : if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
4727 : return TRAVERSE_EXIT;
4728 116283 : return this->clauses_->traverse(traverse);
4729 : }
4730 :
4731 : // Convert to GENERIC.
4732 :
4733 : Bstatement*
4734 5840 : Constant_switch_statement::do_get_backend(Translate_context* context)
4735 : {
4736 5840 : Bexpression* switch_val_expr = this->val_->get_backend(context);
4737 :
4738 5840 : Unnamed_label* break_label = this->break_label_;
4739 5840 : if (break_label == NULL)
4740 5497 : break_label = new Unnamed_label(this->location());
4741 :
4742 5840 : std::vector<std::vector<Bexpression*> > all_cases;
4743 5840 : std::vector<Bstatement*> all_statements;
4744 5840 : this->clauses_->get_backend(context, break_label, &all_cases,
4745 : &all_statements);
4746 :
4747 5840 : Bfunction* bfunction = context->function()->func_value()->get_decl();
4748 5840 : Bstatement* switch_statement;
4749 5840 : switch_statement = context->backend()->switch_statement(bfunction,
4750 : switch_val_expr,
4751 : all_cases,
4752 : all_statements,
4753 : this->location());
4754 5840 : Bstatement* ldef = break_label->get_definition(context);
4755 5840 : return context->backend()->compound_statement(switch_statement, ldef);
4756 5840 : }
4757 :
4758 : // Dump the AST representation for a constant switch statement.
4759 :
4760 : void
4761 0 : Constant_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
4762 : const
4763 : {
4764 0 : ast_dump_context->print_indent();
4765 0 : ast_dump_context->ostream() << "switch ";
4766 0 : ast_dump_context->dump_expression(this->val_);
4767 :
4768 0 : if (ast_dump_context->dump_subblocks())
4769 : {
4770 0 : ast_dump_context->ostream() << " {" << std::endl;
4771 0 : this->clauses_->dump_clauses(ast_dump_context);
4772 0 : ast_dump_context->ostream() << "}";
4773 : }
4774 :
4775 0 : ast_dump_context->ostream() << std::endl;
4776 0 : }
4777 :
4778 : // Class Switch_statement.
4779 :
4780 : // Traversal.
4781 :
4782 : int
4783 55915 : Switch_statement::do_traverse(Traverse* traverse)
4784 : {
4785 55915 : if (this->val_ != NULL)
4786 : {
4787 40790 : if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
4788 : return TRAVERSE_EXIT;
4789 : }
4790 55915 : return this->clauses_->traverse(traverse);
4791 : }
4792 :
4793 : void
4794 11185 : Switch_statement::do_determine_types(Gogo* gogo)
4795 : {
4796 11185 : if (this->val_ != NULL)
4797 8160 : this->val_->determine_type_no_context(gogo);
4798 11185 : this->clauses_->determine_types(gogo,
4799 11185 : (this->val_ == NULL
4800 : ? NULL
4801 8160 : : this->val_->type()));
4802 11185 : }
4803 :
4804 : void
4805 11185 : Switch_statement::do_check_types(Gogo*)
4806 : {
4807 11185 : if (this->val_ != NULL
4808 11185 : && (this->val_->is_error_expression()
4809 8160 : || this->val_->type()->is_error()))
4810 1 : return;
4811 :
4812 11184 : if (this->val_ != NULL
4813 8159 : && !this->val_->type()->is_comparable()
4814 11195 : && !Type::are_compatible_for_comparison(true, this->val_->type(),
4815 11 : Type::make_nil_type(), NULL))
4816 : {
4817 2 : go_error_at(this->val_->location(),
4818 : "cannot switch on value whose type may not be compared");
4819 2 : this->set_is_error();
4820 2 : return;
4821 : }
4822 :
4823 11182 : Type* type;
4824 11182 : if (this->val_ != NULL)
4825 8157 : type = this->val_->type();
4826 : else
4827 3025 : type = Type::make_boolean_type();
4828 11182 : if (!this->clauses_->check_types(type))
4829 8 : this->set_is_error();
4830 : }
4831 :
4832 : // Lower a Switch_statement to a Constant_switch_statement or a series
4833 : // of if statements.
4834 :
4835 : Statement*
4836 11175 : Switch_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
4837 : Statement_inserter*)
4838 : {
4839 11175 : Location loc = this->location();
4840 :
4841 11175 : if (this->val_ != NULL
4842 11175 : && (this->val_->is_error_expression()
4843 8150 : || this->val_->type()->is_error()))
4844 : {
4845 1 : go_assert(saw_errors());
4846 1 : return Statement::make_error_statement(loc);
4847 : }
4848 :
4849 11174 : if (this->val_ != NULL
4850 8149 : && this->val_->type()->integer_type() != NULL
4851 5917 : && !this->clauses_->empty()
4852 17090 : && this->clauses_->is_constant())
4853 5851 : return new Constant_switch_statement(this->val_, this->clauses_,
4854 5851 : this->break_label_, loc);
4855 :
4856 5323 : Block* b = new Block(enclosing, loc);
4857 :
4858 5323 : if (this->clauses_->empty())
4859 : {
4860 22 : Expression* val = this->val_;
4861 22 : if (val == NULL)
4862 13 : val = Expression::make_boolean(true, loc);
4863 22 : return Statement::make_statement(val, true);
4864 : }
4865 :
4866 : // var val_temp VAL_TYPE = VAL
4867 5301 : Expression* val = this->val_;
4868 5301 : if (val == NULL)
4869 3012 : val = Expression::make_boolean(true, loc);
4870 :
4871 5301 : Type* type = val->type();
4872 5301 : if (type->is_abstract())
4873 3012 : type = type->make_non_abstract_type();
4874 5301 : Temporary_statement* val_temp = Statement::make_temporary(type, val, loc);
4875 5301 : b->add_statement(val_temp);
4876 :
4877 5301 : this->clauses_->lower(gogo, b, val_temp, this->break_label());
4878 :
4879 5301 : Statement* s = Statement::make_unnamed_label_statement(this->break_label_);
4880 5301 : b->add_statement(s);
4881 :
4882 5301 : return Statement::make_block_statement(b, loc);
4883 : }
4884 :
4885 : // Return the break label for this switch statement, creating it if
4886 : // necessary.
4887 :
4888 : Unnamed_label*
4889 6269 : Switch_statement::break_label()
4890 : {
4891 6269 : if (this->break_label_ == NULL)
4892 5644 : this->break_label_ = new Unnamed_label(this->location());
4893 6269 : return this->break_label_;
4894 : }
4895 :
4896 : // Dump the AST representation for a switch statement.
4897 :
4898 : void
4899 0 : Switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
4900 : {
4901 0 : ast_dump_context->print_indent();
4902 0 : ast_dump_context->ostream() << "switch ";
4903 0 : if (this->val_ != NULL)
4904 : {
4905 0 : ast_dump_context->dump_expression(this->val_);
4906 : }
4907 0 : if (ast_dump_context->dump_subblocks())
4908 : {
4909 0 : ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
4910 0 : this->clauses_->dump_clauses(ast_dump_context);
4911 0 : ast_dump_context->print_indent();
4912 0 : ast_dump_context->ostream() << "}";
4913 : }
4914 0 : ast_dump_context->ostream() << std::endl;
4915 0 : }
4916 :
4917 : // Return whether this switch may fall through.
4918 :
4919 : bool
4920 1023 : Switch_statement::do_may_fall_through() const
4921 : {
4922 1023 : if (this->clauses_ == NULL)
4923 : return true;
4924 :
4925 : // If we have a break label, then some case needed it. That implies
4926 : // that the switch statement as a whole can fall through.
4927 1023 : if (this->break_label_ != NULL)
4928 : return true;
4929 :
4930 1011 : return this->clauses_->may_fall_through();
4931 : }
4932 :
4933 : // Make a switch statement.
4934 :
4935 : Switch_statement*
4936 11186 : Statement::make_switch_statement(Expression* val, Location location)
4937 : {
4938 11186 : return new Switch_statement(val, location);
4939 : }
4940 :
4941 : // Class Type_case_clauses::Type_case_clause.
4942 :
4943 : // Traversal.
4944 :
4945 : int
4946 63273 : Type_case_clauses::Type_case_clause::traverse(Traverse* traverse)
4947 : {
4948 63273 : if (!this->is_default_
4949 58007 : && ((traverse->traverse_mask()
4950 58007 : & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
4951 121280 : && Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
4952 : return TRAVERSE_EXIT;
4953 63273 : if (this->statements_ != NULL)
4954 54592 : return this->statements_->traverse(traverse);
4955 : return TRAVERSE_CONTINUE;
4956 : }
4957 :
4958 : void
4959 12656 : Type_case_clauses::Type_case_clause::determine_types(Gogo* gogo)
4960 : {
4961 12656 : if (this->statements_ != NULL)
4962 10919 : this->statements_->determine_types(gogo);
4963 12656 : }
4964 :
4965 : bool
4966 12656 : Type_case_clauses::Type_case_clause::check_types(Type* switch_val_type)
4967 : {
4968 12656 : if (!this->is_default_)
4969 : {
4970 11602 : Type* type = this->type_;
4971 11602 : std::string reason;
4972 11602 : if (switch_val_type->interface_type() != NULL
4973 11600 : && !type->is_nil_constant_as_type()
4974 22697 : && type->interface_type() == NULL
4975 11096 : && !switch_val_type->interface_type()->implements_interface(type,
4976 : &reason))
4977 : {
4978 1 : if (reason.empty())
4979 0 : go_error_at(this->location_, "impossible type switch case");
4980 : else
4981 1 : go_error_at(this->location_, "impossible type switch case (%s)",
4982 : reason.c_str());
4983 1 : return false;
4984 : }
4985 11602 : }
4986 : return true;
4987 : }
4988 :
4989 : // Lower one clause in a type switch. Add statements to the block B.
4990 : // The type descriptor we are switching on is in DESCRIPTOR_TEMP.
4991 : // BREAK_LABEL is the label at the end of the type switch.
4992 : // *STMTS_LABEL, if not NULL, is a label to put at the start of the
4993 : // statements.
4994 :
4995 : void
4996 12649 : Type_case_clauses::Type_case_clause::lower(Gogo* gogo,
4997 : Block* b,
4998 : Temporary_statement* descriptor_temp,
4999 : Unnamed_label* break_label,
5000 : Unnamed_label** stmts_label) const
5001 : {
5002 12649 : Location loc = this->location_;
5003 :
5004 12649 : Unnamed_label* next_case_label = NULL;
5005 12649 : if (!this->is_default_)
5006 : {
5007 11599 : Type* type = this->type_;
5008 :
5009 11599 : Expression* ref = Expression::make_temporary_reference(descriptor_temp,
5010 : loc);
5011 :
5012 11599 : Expression* cond;
5013 : // The language permits case nil, which is of course a constant
5014 : // rather than a type. It will appear here as an invalid
5015 : // forwarding type.
5016 11599 : if (type->is_nil_constant_as_type())
5017 227 : cond = Expression::make_binary(OPERATOR_EQEQ, ref,
5018 : Expression::make_nil(loc),
5019 : loc);
5020 11372 : else if (type->interface_type() == NULL)
5021 : {
5022 11095 : if (!gogo->need_eqtype())
5023 11095 : cond = Expression::make_binary(OPERATOR_EQEQ, ref,
5024 : Expression::make_type_descriptor(type, loc),
5025 : loc);
5026 : else
5027 0 : cond = Runtime::make_call(gogo, Runtime::EQTYPE, loc, 2,
5028 : Expression::make_type_descriptor(type, loc),
5029 : ref);
5030 : }
5031 : else
5032 277 : cond = Runtime::make_call(gogo, Runtime::IFACET2IP, loc, 2,
5033 : Expression::make_type_descriptor(type, loc),
5034 : ref);
5035 :
5036 11599 : Unnamed_label* dest;
5037 11599 : if (!this->is_fallthrough_)
5038 : {
5039 : // if !COND { goto NEXT_CASE_LABEL }
5040 10321 : next_case_label = new Unnamed_label(Linemap::unknown_location());
5041 10321 : dest = next_case_label;
5042 10321 : cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
5043 : }
5044 : else
5045 : {
5046 : // if COND { goto STMTS_LABEL }
5047 1278 : go_assert(stmts_label != NULL);
5048 1278 : if (*stmts_label == NULL)
5049 531 : *stmts_label = new Unnamed_label(Linemap::unknown_location());
5050 1278 : dest = *stmts_label;
5051 : }
5052 11599 : Block* then_block = new Block(b, loc);
5053 11599 : Statement* s = Statement::make_goto_unnamed_statement(dest, loc);
5054 11599 : then_block->add_statement(s);
5055 11599 : s = Statement::make_if_statement(cond, then_block, NULL, loc);
5056 11599 : s->determine_types(gogo);
5057 11599 : b->add_statement(s);
5058 : }
5059 :
5060 12649 : if (this->statements_ != NULL
5061 1733 : || (!this->is_fallthrough_
5062 455 : && stmts_label != NULL
5063 449 : && *stmts_label != NULL))
5064 : {
5065 10994 : go_assert(!this->is_fallthrough_);
5066 10994 : if (stmts_label != NULL && *stmts_label != NULL)
5067 : {
5068 531 : go_assert(!this->is_default_);
5069 531 : if (this->statements_ != NULL)
5070 453 : (*stmts_label)->set_location(this->statements_->start_location());
5071 531 : Statement* s = Statement::make_unnamed_label_statement(*stmts_label);
5072 531 : b->add_statement(s);
5073 531 : *stmts_label = NULL;
5074 : }
5075 10994 : if (this->statements_ != NULL)
5076 10916 : b->add_statement(Statement::make_block_statement(this->statements_,
5077 : loc));
5078 : }
5079 :
5080 12649 : if (this->is_fallthrough_)
5081 1278 : go_assert(next_case_label == NULL);
5082 : else
5083 : {
5084 11371 : Location gloc = (this->statements_ == NULL
5085 11371 : ? loc
5086 11371 : : this->statements_->end_location());
5087 11371 : b->add_statement(Statement::make_goto_unnamed_statement(break_label,
5088 : gloc));
5089 11371 : if (next_case_label != NULL)
5090 : {
5091 10321 : Statement* s =
5092 10321 : Statement::make_unnamed_label_statement(next_case_label);
5093 10321 : b->add_statement(s);
5094 : }
5095 : }
5096 12649 : }
5097 :
5098 : // Return true if this type clause may fall through to the statements
5099 : // following the switch.
5100 :
5101 : bool
5102 984 : Type_case_clauses::Type_case_clause::may_fall_through() const
5103 : {
5104 984 : if (this->is_fallthrough_)
5105 : {
5106 : // This case means that we automatically fall through to the
5107 : // next case (it's used for T1 in case T1, T2:). It does not
5108 : // mean that we fall through to the end of the type switch as a
5109 : // whole. There is sure to be a next case and that next case
5110 : // will determine whether we fall through to the statements
5111 : // after the type switch.
5112 : return false;
5113 : }
5114 901 : if (this->statements_ == NULL)
5115 : return true;
5116 901 : return this->statements_->may_fall_through();
5117 : }
5118 :
5119 : // Dump the AST representation for a type case clause
5120 :
5121 : void
5122 0 : Type_case_clauses::Type_case_clause::dump_clause(
5123 : Ast_dump_context* ast_dump_context) const
5124 : {
5125 0 : ast_dump_context->print_indent();
5126 0 : if (this->is_default_)
5127 : {
5128 0 : ast_dump_context->ostream() << "default:";
5129 : }
5130 : else
5131 : {
5132 0 : ast_dump_context->ostream() << "case ";
5133 0 : ast_dump_context->dump_type(this->type_);
5134 0 : ast_dump_context->ostream() << ":" ;
5135 : }
5136 0 : ast_dump_context->dump_block(this->statements_);
5137 0 : if (this->is_fallthrough_)
5138 : {
5139 0 : ast_dump_context->print_indent();
5140 0 : ast_dump_context->ostream() << " (fallthrough)" << std::endl;
5141 : }
5142 0 : }
5143 :
5144 : // Class Type_case_clauses.
5145 :
5146 : // Traversal.
5147 :
5148 : int
5149 11958 : Type_case_clauses::traverse(Traverse* traverse)
5150 : {
5151 75231 : for (Type_clauses::iterator p = this->clauses_.begin();
5152 75231 : p != this->clauses_.end();
5153 63273 : ++p)
5154 : {
5155 63273 : if (p->traverse(traverse) == TRAVERSE_EXIT)
5156 11958 : return TRAVERSE_EXIT;
5157 : }
5158 : return TRAVERSE_CONTINUE;
5159 : }
5160 :
5161 : void
5162 2393 : Type_case_clauses::determine_types(Gogo* gogo)
5163 : {
5164 15049 : for (Type_clauses::iterator p = this->clauses_.begin();
5165 15049 : p != this->clauses_.end();
5166 12656 : ++p)
5167 12656 : p->determine_types(gogo);
5168 2393 : }
5169 :
5170 : bool
5171 2393 : Type_case_clauses::check_types(Type* switch_val_type)
5172 : {
5173 2393 : bool ret = true;
5174 15049 : for (Type_clauses::iterator p = this->clauses_.begin();
5175 15049 : p != this->clauses_.end();
5176 12656 : ++p)
5177 : {
5178 12656 : if (!p->check_types(switch_val_type))
5179 1 : ret = false;
5180 : }
5181 2393 : return ret;
5182 : }
5183 :
5184 : // Check for duplicate types.
5185 :
5186 : void
5187 2393 : Type_case_clauses::check_duplicates() const
5188 : {
5189 2393 : typedef Unordered_set_hash(const Type*, Type_hash_identical,
5190 : Type_identical) Types_seen;
5191 2393 : Types_seen types_seen;
5192 15049 : for (Type_clauses::const_iterator p = this->clauses_.begin();
5193 15049 : p != this->clauses_.end();
5194 12656 : ++p)
5195 : {
5196 12656 : Type* t = p->type();
5197 12656 : if (t == NULL)
5198 1054 : continue;
5199 11602 : if (t->is_nil_constant_as_type())
5200 227 : t = Type::make_nil_type();
5201 11602 : std::pair<Types_seen::iterator, bool> ins = types_seen.insert(t);
5202 11602 : if (!ins.second)
5203 6 : go_error_at(p->location(), "duplicate type in switch");
5204 : }
5205 2393 : }
5206 :
5207 : // Lower the clauses in a type switch. Add statements to the block B.
5208 : // The type descriptor we are switching on is in DESCRIPTOR_TEMP.
5209 : // BREAK_LABEL is the label at the end of the type switch.
5210 :
5211 : void
5212 2386 : Type_case_clauses::lower(Gogo* gogo, Block* b,
5213 : Temporary_statement* descriptor_temp,
5214 : Unnamed_label* break_label) const
5215 : {
5216 2386 : const Type_case_clause* default_case = NULL;
5217 :
5218 2386 : Unnamed_label* stmts_label = NULL;
5219 15035 : for (Type_clauses::const_iterator p = this->clauses_.begin();
5220 15035 : p != this->clauses_.end();
5221 12649 : ++p)
5222 : {
5223 12649 : if (!p->is_default())
5224 11599 : p->lower(gogo, b, descriptor_temp, break_label, &stmts_label);
5225 : else
5226 : {
5227 : // We are generating a series of tests, which means that we
5228 : // need to move the default case to the end.
5229 : default_case = &*p;
5230 : }
5231 : }
5232 2386 : go_assert(stmts_label == NULL);
5233 :
5234 2386 : if (default_case != NULL)
5235 1050 : default_case->lower(gogo, b, descriptor_temp, break_label, NULL);
5236 2386 : }
5237 :
5238 : // Return true if these clauses may fall through to the statements
5239 : // following the switch statement.
5240 :
5241 : bool
5242 203 : Type_case_clauses::may_fall_through() const
5243 : {
5244 203 : bool found_default = false;
5245 1187 : for (Type_clauses::const_iterator p = this->clauses_.begin();
5246 1187 : p != this->clauses_.end();
5247 984 : ++p)
5248 : {
5249 984 : if (p->may_fall_through())
5250 203 : return true;
5251 984 : if (p->is_default())
5252 191 : found_default = true;
5253 : }
5254 203 : return !found_default;
5255 : }
5256 :
5257 : // Dump the AST representation for case clauses (from a switch statement)
5258 :
5259 : void
5260 0 : Type_case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
5261 : {
5262 0 : for (Type_clauses::const_iterator p = this->clauses_.begin();
5263 0 : p != this->clauses_.end();
5264 0 : ++p)
5265 0 : p->dump_clause(ast_dump_context);
5266 0 : }
5267 :
5268 : // Class Type_switch_statement.
5269 :
5270 : // Traversal.
5271 :
5272 : int
5273 11958 : Type_switch_statement::do_traverse(Traverse* traverse)
5274 : {
5275 11958 : if (this->traverse_expression(traverse, &this->expr_) == TRAVERSE_EXIT)
5276 : return TRAVERSE_EXIT;
5277 11958 : if (this->clauses_ != NULL)
5278 11958 : return this->clauses_->traverse(traverse);
5279 : return TRAVERSE_CONTINUE;
5280 : }
5281 :
5282 : void
5283 2393 : Type_switch_statement::do_determine_types(Gogo* gogo)
5284 : {
5285 2393 : this->expr_->determine_type_no_context(gogo);
5286 2393 : this->clauses_->determine_types(gogo);
5287 2393 : }
5288 :
5289 : void
5290 2393 : Type_switch_statement::do_check_types(Gogo*)
5291 : {
5292 2393 : if (this->clauses_ != NULL)
5293 2393 : this->clauses_->check_duplicates();
5294 :
5295 2393 : Type* expr_type = this->expr_->type();
5296 2393 : if (expr_type->interface_type() == NULL)
5297 : {
5298 6 : if (!expr_type->is_error())
5299 4 : this->report_error(_("cannot type switch on non-interface value"));
5300 6 : this->set_is_error();
5301 : }
5302 :
5303 2393 : if (!this->clauses_->check_types(expr_type))
5304 1 : this->set_is_error();
5305 2393 : }
5306 :
5307 : // Lower a type switch statement to a series of if statements. The gc
5308 : // compiler is able to generate a table in some cases. However, that
5309 : // does not work for us because we may have type descriptors in
5310 : // different shared libraries, so we can't compare them with simple
5311 : // equality testing.
5312 :
5313 : Statement*
5314 2386 : Type_switch_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
5315 : Statement_inserter*)
5316 : {
5317 2386 : const Location loc = this->location();
5318 :
5319 2386 : if (this->classification() == STATEMENT_ERROR)
5320 0 : return Statement::make_error_statement(loc);
5321 :
5322 2386 : Block* b = new Block(enclosing, loc);
5323 :
5324 2386 : Temporary_statement* val_temp =
5325 2386 : Statement::make_temporary(NULL, this->expr_, loc);
5326 2386 : b->add_statement(val_temp);
5327 :
5328 : // var descriptor_temp DESCRIPTOR_TYPE
5329 2386 : Type* descriptor_type = Type::make_type_descriptor_ptr_type();
5330 2386 : Temporary_statement* descriptor_temp =
5331 2386 : Statement::make_temporary(descriptor_type, NULL, loc);
5332 2386 : b->add_statement(descriptor_temp);
5333 :
5334 : // descriptor_temp = ifacetype(val_temp)
5335 2386 : Expression* ref = Expression::make_temporary_reference(val_temp, loc);
5336 2386 : Expression* td = Expression::get_interface_type_descriptor(ref);
5337 2386 : Temporary_reference_expression* lhs =
5338 2386 : Expression::make_temporary_reference(descriptor_temp, loc);
5339 2386 : lhs->set_is_lvalue();
5340 2386 : Statement* s = Statement::make_assignment(lhs, td, loc);
5341 2386 : s->determine_types(gogo);
5342 2386 : b->add_statement(s);
5343 :
5344 2386 : if (this->clauses_ != NULL)
5345 2386 : this->clauses_->lower(gogo, b, descriptor_temp, this->break_label());
5346 :
5347 2386 : s = Statement::make_unnamed_label_statement(this->break_label_);
5348 2386 : b->add_statement(s);
5349 :
5350 2386 : return Statement::make_block_statement(b, loc);
5351 : }
5352 :
5353 : // Return whether this switch may fall through.
5354 :
5355 : bool
5356 215 : Type_switch_statement::do_may_fall_through() const
5357 : {
5358 215 : if (this->clauses_ == NULL)
5359 : return true;
5360 :
5361 : // If we have a break label, then some case needed it. That implies
5362 : // that the switch statement as a whole can fall through.
5363 215 : if (this->break_label_ != NULL)
5364 : return true;
5365 :
5366 203 : return this->clauses_->may_fall_through();
5367 : }
5368 :
5369 : // Return the break label for this type switch statement, creating it
5370 : // if necessary.
5371 :
5372 : Unnamed_label*
5373 2583 : Type_switch_statement::break_label()
5374 : {
5375 2583 : if (this->break_label_ == NULL)
5376 2386 : this->break_label_ = new Unnamed_label(this->location());
5377 2583 : return this->break_label_;
5378 : }
5379 :
5380 : // Dump the AST representation for a type switch statement
5381 :
5382 : void
5383 0 : Type_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
5384 : const
5385 : {
5386 0 : ast_dump_context->print_indent();
5387 0 : ast_dump_context->ostream() << "switch ";
5388 0 : ast_dump_context->dump_expression(this->expr_);
5389 0 : ast_dump_context->ostream() << " .(type)";
5390 0 : if (ast_dump_context->dump_subblocks())
5391 : {
5392 0 : ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
5393 0 : this->clauses_->dump_clauses(ast_dump_context);
5394 0 : ast_dump_context->ostream() << "}";
5395 : }
5396 0 : ast_dump_context->ostream() << std::endl;
5397 0 : }
5398 :
5399 : // Make a type switch statement.
5400 :
5401 : Type_switch_statement*
5402 2393 : Statement::make_type_switch_statement(Expression* expr, Location location)
5403 : {
5404 2393 : return new Type_switch_statement(expr, location);
5405 : }
5406 :
5407 : // Class Send_statement.
5408 :
5409 : // Traversal.
5410 :
5411 : int
5412 60890 : Send_statement::do_traverse(Traverse* traverse)
5413 : {
5414 60890 : if (this->traverse_expression(traverse, &this->channel_) == TRAVERSE_EXIT)
5415 : return TRAVERSE_EXIT;
5416 59936 : return this->traverse_expression(traverse, &this->val_);
5417 : }
5418 :
5419 : // Determine types.
5420 :
5421 : void
5422 2676 : Send_statement::do_determine_types(Gogo* gogo)
5423 : {
5424 2676 : this->channel_->determine_type_no_context(gogo);
5425 2676 : Type* type = this->channel_->type();
5426 2676 : Type_context context;
5427 2676 : if (type->channel_type() != NULL)
5428 5348 : context.type = type->channel_type()->element_type();
5429 2676 : this->val_->determine_type(gogo, &context);
5430 2676 : }
5431 :
5432 : // Check types.
5433 :
5434 : void
5435 2594 : Send_statement::do_check_types(Gogo*)
5436 : {
5437 2594 : Type* type = this->channel_->type();
5438 2594 : if (type->is_error())
5439 : {
5440 1 : this->set_is_error();
5441 1 : return;
5442 : }
5443 2593 : Channel_type* channel_type = type->channel_type();
5444 2593 : if (channel_type == NULL)
5445 : {
5446 1 : go_error_at(this->location(), "left operand of %<<-%> must be channel");
5447 1 : this->set_is_error();
5448 1 : return;
5449 : }
5450 2592 : Type* element_type = channel_type->element_type();
5451 2592 : if (!Type::are_assignable(element_type, this->val_->type(), NULL))
5452 : {
5453 0 : this->report_error(_("incompatible types in send"));
5454 0 : return;
5455 : }
5456 2592 : if (!channel_type->may_send())
5457 : {
5458 1 : this->report_error(_("invalid send on receive-only channel"));
5459 1 : return;
5460 : }
5461 : }
5462 :
5463 : // Flatten a send statement. We may need a temporary for interface
5464 : // conversion.
5465 :
5466 : Statement*
5467 2608 : Send_statement::do_flatten(Gogo*, Named_object*, Block*,
5468 : Statement_inserter* inserter)
5469 : {
5470 2608 : if (this->channel_->is_error_expression()
5471 2608 : || this->channel_->type()->is_error_type())
5472 : {
5473 0 : go_assert(saw_errors());
5474 0 : return Statement::make_error_statement(this->location());
5475 : }
5476 :
5477 5216 : Type* element_type = this->channel_->type()->channel_type()->element_type();
5478 2608 : if (!Type::are_identical(element_type, this->val_->type(),
5479 : Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
5480 : NULL)
5481 18 : && this->val_->type()->interface_type() != NULL
5482 2608 : && !this->val_->is_multi_eval_safe())
5483 : {
5484 0 : Temporary_statement* temp =
5485 0 : Statement::make_temporary(NULL, this->val_, this->location());
5486 0 : inserter->insert(temp);
5487 0 : this->val_ = Expression::make_temporary_reference(temp,
5488 : this->location());
5489 : }
5490 2608 : return this;
5491 : }
5492 :
5493 : // Add explicit type conversions.
5494 :
5495 : void
5496 2598 : Send_statement::do_add_conversions()
5497 : {
5498 5196 : Type* lt = this->channel_->type()->channel_type()->element_type();
5499 2598 : Type* rt = this->val_->type();
5500 2598 : if (!Type::are_identical(lt, rt, 0, NULL)
5501 2598 : && lt->interface_type() != NULL)
5502 97 : this->val_ = Expression::make_cast(lt, this->val_, this->location());
5503 2598 : }
5504 :
5505 : // Convert a send statement to the backend representation.
5506 :
5507 : Bstatement*
5508 2597 : Send_statement::do_get_backend(Translate_context* context)
5509 : {
5510 2597 : Gogo* gogo = context->gogo();
5511 2597 : Location loc = this->location();
5512 :
5513 2597 : Channel_type* channel_type = this->channel_->type()->channel_type();
5514 2597 : Type* element_type = channel_type->element_type();
5515 2597 : Expression* val = Expression::convert_for_assignment(gogo,
5516 : element_type,
5517 : this->val_, loc);
5518 :
5519 2597 : bool can_take_address;
5520 2597 : switch (element_type->base()->classification())
5521 : {
5522 : case Type::TYPE_BOOLEAN:
5523 : case Type::TYPE_INTEGER:
5524 : case Type::TYPE_FUNCTION:
5525 : case Type::TYPE_POINTER:
5526 : case Type::TYPE_MAP:
5527 : case Type::TYPE_CHANNEL:
5528 : case Type::TYPE_FLOAT:
5529 : case Type::TYPE_COMPLEX:
5530 : case Type::TYPE_STRING:
5531 : case Type::TYPE_INTERFACE:
5532 : can_take_address = false;
5533 : break;
5534 :
5535 : case Type::TYPE_STRUCT:
5536 : can_take_address = true;
5537 : break;
5538 :
5539 15 : case Type::TYPE_ARRAY:
5540 15 : can_take_address = !element_type->is_slice_type();
5541 15 : break;
5542 :
5543 0 : default:
5544 0 : case Type::TYPE_ERROR:
5545 0 : case Type::TYPE_VOID:
5546 0 : case Type::TYPE_SINK:
5547 0 : case Type::TYPE_NIL:
5548 0 : case Type::TYPE_NAMED:
5549 0 : case Type::TYPE_FORWARD:
5550 0 : go_assert(saw_errors());
5551 0 : return context->backend()->error_statement();
5552 : }
5553 :
5554 : // Only try to take the address of a variable. We have already
5555 : // moved variables to the heap, so this should not cause that to
5556 : // happen unnecessarily.
5557 15 : if (can_take_address
5558 320 : && val->var_expression() == NULL
5559 2294 : && val->temporary_reference_expression() == NULL)
5560 : can_take_address = false;
5561 :
5562 4818 : Bstatement* btemp = NULL;
5563 2279 : if (can_take_address)
5564 : {
5565 : // The function doesn't change the value, so just take its
5566 : // address directly.
5567 58 : val = Expression::make_unary(OPERATOR_AND, val, loc);
5568 : }
5569 : else
5570 : {
5571 : // The value is not in a variable, or is small enough that it
5572 : // might be in a register, and taking the address would push it
5573 : // on the stack. Copy it into a temporary variable to take the
5574 : // address.
5575 2539 : Temporary_statement* temp = Statement::make_temporary(element_type,
5576 : val, loc);
5577 2539 : Expression* ref = Expression::make_temporary_reference(temp, loc);
5578 2539 : val = Expression::make_unary(OPERATOR_AND, ref, loc);
5579 2539 : btemp = temp->get_backend(context);
5580 : }
5581 :
5582 2597 : Expression* call = Runtime::make_call(gogo, Runtime::CHANSEND, loc, 2,
5583 2597 : this->channel_, val);
5584 2597 : call->determine_type_no_context(gogo);
5585 2597 : gogo->lower_expression(context->function(), NULL, &call);
5586 2597 : Bexpression* bcall = call->get_backend(context);
5587 2597 : Bfunction* bfunction = context->function()->func_value()->get_decl();
5588 2597 : Bstatement* s = context->backend()->expression_statement(bfunction, bcall);
5589 :
5590 2597 : if (btemp == NULL)
5591 : return s;
5592 : else
5593 2539 : return context->backend()->compound_statement(btemp, s);
5594 : }
5595 :
5596 : // Dump the AST representation for a send statement
5597 :
5598 : void
5599 0 : Send_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
5600 : {
5601 0 : ast_dump_context->print_indent();
5602 0 : ast_dump_context->dump_expression(this->channel_);
5603 0 : ast_dump_context->ostream() << " <- ";
5604 0 : ast_dump_context->dump_expression(this->val_);
5605 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
5606 0 : }
5607 :
5608 : // Make a send statement.
5609 :
5610 : Send_statement*
5611 2601 : Statement::make_send_statement(Expression* channel, Expression* val,
5612 : Location location)
5613 : {
5614 2601 : return new Send_statement(channel, val, location);
5615 : }
5616 :
5617 : // Class Select_clauses::Select_clause.
5618 :
5619 : // Traversal.
5620 :
5621 : int
5622 164626 : Select_clauses::Select_clause::traverse(Traverse* traverse)
5623 : {
5624 164626 : if (!this->is_lowered_
5625 164626 : && (traverse->traverse_mask()
5626 39950 : & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
5627 : {
5628 39950 : if (this->channel_ != NULL)
5629 : {
5630 32630 : if (Expression::traverse(&this->channel_, traverse) == TRAVERSE_EXIT)
5631 : return TRAVERSE_EXIT;
5632 : }
5633 39950 : if (this->val_ != NULL)
5634 : {
5635 14765 : if (Expression::traverse(&this->val_, traverse) == TRAVERSE_EXIT)
5636 : return TRAVERSE_EXIT;
5637 : }
5638 39950 : if (this->closed_ != NULL)
5639 : {
5640 45 : if (Expression::traverse(&this->closed_, traverse) == TRAVERSE_EXIT)
5641 : return TRAVERSE_EXIT;
5642 : }
5643 : }
5644 164626 : if (this->statements_ != NULL)
5645 : {
5646 164626 : if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
5647 : return TRAVERSE_EXIT;
5648 : }
5649 : return TRAVERSE_CONTINUE;
5650 : }
5651 :
5652 : // Lowering. We call a function to register this clause, and arrange
5653 : // to set any variables in any receive clause.
5654 :
5655 : void
5656 6746 : Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
5657 : Block* b, Temporary_statement* scases,
5658 : int index, Temporary_statement* recvok)
5659 : {
5660 6746 : Location loc = this->location_;
5661 :
5662 6746 : this->set_case_index(index);
5663 :
5664 6746 : if (this->is_default_)
5665 : {
5666 867 : go_assert(this->channel_ == NULL && this->val_ == NULL);
5667 867 : this->is_lowered_ = true;
5668 867 : return;
5669 : }
5670 :
5671 5879 : Expression* scase = Expression::make_temporary_reference(scases, loc);
5672 5879 : Expression* index_expr = Expression::make_integer_sl(index, NULL, loc);
5673 5879 : scase = Expression::make_array_index(scase, index_expr, NULL, NULL, loc);
5674 :
5675 : // Evaluate the channel before the select statement.
5676 5879 : Temporary_statement* channel_temp = Statement::make_temporary(NULL,
5677 : this->channel_,
5678 : loc);
5679 5879 : b->add_statement(channel_temp);
5680 5879 : Expression* chanref = Expression::make_temporary_reference(channel_temp,
5681 : loc);
5682 :
5683 5879 : if (this->is_send_)
5684 1374 : this->lower_send(gogo, b, scase, chanref);
5685 : else
5686 4505 : this->lower_recv(gogo, function, b, scase, chanref, recvok);
5687 :
5688 : // Now all references should be handled through the statements, not
5689 : // through here.
5690 5879 : this->is_lowered_ = true;
5691 5879 : this->val_ = NULL;
5692 : }
5693 :
5694 : // Lower a send clause in a select statement.
5695 :
5696 : void
5697 1374 : Select_clauses::Select_clause::lower_send(Gogo* gogo, Block* b,
5698 : Expression* scase,
5699 : Expression* chanref)
5700 : {
5701 1374 : Location loc = this->location_;
5702 :
5703 1374 : Channel_type* ct = this->channel_->type()->channel_type();
5704 1374 : if (ct == NULL)
5705 0 : return;
5706 :
5707 1374 : Type* valtype = ct->element_type();
5708 :
5709 : // Note that copying the value to a temporary here means that we
5710 : // evaluate the send values in the required order.
5711 1374 : Temporary_statement* val = Statement::make_temporary(valtype, this->val_,
5712 : loc);
5713 : // The value here escapes, because it might be sent on a channel.
5714 : // We record that via the Temporary_statement, so that the escape
5715 : // analysis pass can pick it up. The gc compiler lowers select
5716 : // statements after escape analysis, so it doesn't have to worry
5717 : // about this.
5718 1374 : val->set_value_escapes();
5719 1374 : b->add_statement(val);
5720 :
5721 1374 : Expression* valref = Expression::make_temporary_reference(val, loc);
5722 1374 : Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
5723 1374 : Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
5724 1374 : valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);
5725 :
5726 1374 : this->set_case(gogo, b, scase, chanref, valaddr);
5727 : }
5728 :
5729 : // Lower a receive clause in a select statement.
5730 :
5731 : void
5732 4505 : Select_clauses::Select_clause::lower_recv(Gogo* gogo, Named_object* function,
5733 : Block* b, Expression* scase,
5734 : Expression* chanref,
5735 : Temporary_statement* recvok)
5736 : {
5737 4505 : Location loc = this->location_;
5738 :
5739 4505 : Channel_type* ct = this->channel_->type()->channel_type();
5740 4505 : if (ct == NULL)
5741 0 : return;
5742 :
5743 4505 : Type* valtype = ct->element_type();
5744 4505 : Temporary_statement* val = Statement::make_temporary(valtype, NULL, loc);
5745 4505 : b->add_statement(val);
5746 :
5747 4505 : Expression* valref = Expression::make_temporary_reference(val, loc);
5748 4505 : Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
5749 4505 : Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
5750 4505 : valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);
5751 :
5752 4505 : this->set_case(gogo, b, scase, chanref, valaddr);
5753 :
5754 : // If the block of statements is executed, arrange for the received
5755 : // value to move from VAL to the place where the statements expect
5756 : // it.
5757 :
5758 4505 : Block* init = NULL;
5759 :
5760 4505 : if (this->var_ != NULL)
5761 : {
5762 460 : go_assert(this->val_ == NULL);
5763 460 : valref = Expression::make_temporary_reference(val, loc);
5764 460 : this->var_->var_value()->set_init(valref);
5765 460 : this->var_->var_value()->clear_type_from_chan_element();
5766 : }
5767 4045 : else if (this->val_ != NULL && !this->val_->is_sink_expression())
5768 : {
5769 1415 : init = new Block(b, loc);
5770 1415 : valref = Expression::make_temporary_reference(val, loc);
5771 1415 : Statement* s = Statement::make_assignment(this->val_, valref, loc);
5772 1415 : s->determine_types(gogo);
5773 1415 : init->add_statement(s);
5774 : }
5775 :
5776 4505 : if (this->closedvar_ != NULL)
5777 : {
5778 28 : go_assert(this->closed_ == NULL);
5779 28 : Expression* cref = Expression::make_temporary_reference(recvok, loc);
5780 28 : this->closedvar_->var_value()->set_init(cref);
5781 : }
5782 4477 : else if (this->closed_ != NULL && !this->closed_->is_sink_expression())
5783 : {
5784 7 : if (init == NULL)
5785 0 : init = new Block(b, loc);
5786 7 : Expression* cref = Expression::make_temporary_reference(recvok, loc);
5787 7 : Statement* s = Statement::make_assignment(this->closed_, cref, loc);
5788 7 : s->determine_types(gogo);
5789 7 : init->add_statement(s);
5790 : }
5791 :
5792 4505 : if (init != NULL)
5793 : {
5794 1415 : gogo->lower_block(function, init);
5795 :
5796 1415 : if (this->statements_ != NULL)
5797 1415 : init->add_statement(Statement::make_block_statement(this->statements_,
5798 : loc));
5799 1415 : this->statements_ = init;
5800 : }
5801 : }
5802 :
5803 : // Set the fields of an scase struct, an element in the array that we
5804 : // pass to the runtime function selectgo.
5805 :
5806 : void
5807 5879 : Select_clauses::Select_clause::set_case(Gogo* gogo,
5808 : Block* b,
5809 : Expression* scase,
5810 : Expression* chanref,
5811 : Expression* elem)
5812 : {
5813 5879 : Location loc = this->location_;
5814 5879 : Struct_type* scase_type = scase->type()->struct_type();
5815 :
5816 5879 : int field_index = 0;
5817 5879 : go_assert(scase_type->field(field_index)->is_field_name("c"));
5818 5879 : Expression* ref = Expression::make_field_reference(scase, field_index, loc);
5819 5879 : Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
5820 5879 : chanref = Expression::make_unsafe_cast(unsafe_pointer_type, chanref, loc);
5821 5879 : Statement* s = Statement::make_assignment(ref, chanref, loc);
5822 5879 : s->determine_types(gogo);
5823 5879 : b->add_statement(s);
5824 :
5825 5879 : if (elem != NULL)
5826 : {
5827 5879 : field_index = 1;
5828 5879 : go_assert(scase_type->field(field_index)->is_field_name("elem"));
5829 5879 : ref = Expression::make_field_reference(scase->copy(), field_index, loc);
5830 5879 : s = Statement::make_assignment(ref, elem, loc);
5831 5879 : s->determine_types(gogo);
5832 5879 : b->add_statement(s);
5833 : }
5834 5879 : }
5835 :
5836 : // Determine types.
5837 :
5838 : void
5839 8070 : Select_clauses::Select_clause::determine_types(Gogo* gogo)
5840 : {
5841 8070 : if (this->channel_ != NULL)
5842 6604 : this->channel_->determine_type_no_context(gogo);
5843 8070 : if (this->val_ != NULL)
5844 2953 : this->val_->determine_type_no_context(gogo);
5845 8070 : if (this->closed_ != NULL)
5846 9 : this->closed_->determine_type_no_context(gogo);
5847 8070 : if (this->var_ != NULL && this->var_->is_variable())
5848 538 : this->var_->var_value()->determine_type(gogo);
5849 8070 : if (this->closedvar_ != NULL && this->closedvar_->is_variable())
5850 41 : this->closedvar_->var_value()->determine_type(gogo);
5851 8070 : if (this->statements_ != NULL)
5852 8070 : this->statements_->determine_types(gogo);
5853 8070 : }
5854 :
5855 : // Check types.
5856 :
5857 : void
5858 7990 : Select_clauses::Select_clause::check_types()
5859 : {
5860 7990 : if (this->is_default_)
5861 : return;
5862 :
5863 6526 : Channel_type* ct = this->channel_->type()->channel_type();
5864 6526 : if (ct == NULL)
5865 : {
5866 0 : go_error_at(this->channel_->location(), "expected channel");
5867 0 : return;
5868 : }
5869 :
5870 6526 : if (this->is_send_ && !ct->may_send())
5871 1 : go_error_at(this->location(), "invalid send on receive-only channel");
5872 6525 : else if (!this->is_send_ && !ct->may_receive())
5873 1 : go_error_at(this->location(), "invalid receive on send-only channel");
5874 : }
5875 :
5876 : // Whether this clause may fall through to the statement which follows
5877 : // the overall select statement.
5878 :
5879 : bool
5880 406 : Select_clauses::Select_clause::may_fall_through() const
5881 : {
5882 406 : if (this->statements_ == NULL)
5883 : return true;
5884 406 : return this->statements_->may_fall_through();
5885 : }
5886 :
5887 : // Return the backend representation for the statements to execute.
5888 :
5889 : Bstatement*
5890 6734 : Select_clauses::Select_clause::get_statements_backend(
5891 : Translate_context* context)
5892 : {
5893 6734 : if (this->statements_ == NULL)
5894 : return NULL;
5895 6734 : Bblock* bblock = this->statements_->get_backend(context);
5896 6734 : return context->backend()->block_statement(bblock);
5897 : }
5898 :
5899 : // Dump the AST representation for a select case clause
5900 :
5901 : void
5902 0 : Select_clauses::Select_clause::dump_clause(
5903 : Ast_dump_context* ast_dump_context) const
5904 : {
5905 0 : ast_dump_context->print_indent();
5906 0 : if (this->is_default_)
5907 : {
5908 0 : ast_dump_context->ostream() << "default:";
5909 : }
5910 : else
5911 : {
5912 0 : ast_dump_context->ostream() << "case " ;
5913 0 : if (this->is_send_)
5914 : {
5915 0 : ast_dump_context->dump_expression(this->channel_);
5916 0 : ast_dump_context->ostream() << " <- " ;
5917 0 : if (this->val_ != NULL)
5918 0 : ast_dump_context->dump_expression(this->val_);
5919 : }
5920 : else
5921 : {
5922 0 : if (this->val_ != NULL)
5923 0 : ast_dump_context->dump_expression(this->val_);
5924 0 : if (this->closed_ != NULL)
5925 : {
5926 : // FIXME: can val_ == NULL and closed_ ! = NULL?
5927 0 : ast_dump_context->ostream() << " , " ;
5928 0 : ast_dump_context->dump_expression(this->closed_);
5929 : }
5930 0 : if (this->closedvar_ != NULL || this->var_ != NULL)
5931 0 : ast_dump_context->ostream() << " := " ;
5932 :
5933 0 : ast_dump_context->ostream() << " <- " ;
5934 0 : ast_dump_context->dump_expression(this->channel_);
5935 : }
5936 0 : ast_dump_context->ostream() << ":" ;
5937 : }
5938 0 : ast_dump_context->dump_block(this->statements_);
5939 0 : }
5940 :
5941 : // Class Select_clauses.
5942 :
5943 : // Whether there is a default case.
5944 :
5945 : bool
5946 2656 : Select_clauses::has_default() const
5947 : {
5948 7202 : for (Clauses::const_iterator p = this->clauses_.begin();
5949 7202 : p != this->clauses_.end();
5950 4546 : ++p)
5951 6010 : if (p->is_default())
5952 2656 : return true;
5953 : return false;
5954 : }
5955 :
5956 : // Traversal.
5957 :
5958 : int
5959 49708 : Select_clauses::traverse(Traverse* traverse)
5960 : {
5961 214334 : for (Clauses::iterator p = this->clauses_.begin();
5962 214334 : p != this->clauses_.end();
5963 164626 : ++p)
5964 : {
5965 164626 : if (p->traverse(traverse) == TRAVERSE_EXIT)
5966 49708 : return TRAVERSE_EXIT;
5967 : }
5968 : return TRAVERSE_CONTINUE;
5969 : }
5970 :
5971 : // Lowering. Here we pull out the channel and the send values, to
5972 : // enforce the order of evaluation. We also add explicit send and
5973 : // receive statements to the clauses. This builds the entries in the
5974 : // local array of scase values. It sets *P_SEND_COUNT and
5975 : // *P_RECV_COUNT.
5976 :
5977 : void
5978 1951 : Select_clauses::lower(Gogo* gogo, Named_object* function, Block* b,
5979 : Temporary_statement* scases, Temporary_statement* recvok,
5980 : int *p_send_count, int *p_recv_count)
5981 : {
5982 1951 : int send_count = 0;
5983 1951 : int recv_count = 0;
5984 1951 : bool has_default = false;
5985 8697 : for (Clauses::iterator p = this->clauses_.begin();
5986 8697 : p != this->clauses_.end();
5987 6746 : ++p)
5988 : {
5989 6746 : if (p->is_default())
5990 : has_default = true;
5991 5879 : else if (p->is_send())
5992 1374 : ++send_count;
5993 : else
5994 4505 : ++recv_count;
5995 : }
5996 :
5997 1951 : *p_send_count = send_count;
5998 1951 : *p_recv_count = recv_count;
5999 :
6000 1951 : int send_index = 0;
6001 1951 : int recv_index = send_count;
6002 8697 : for (Clauses::iterator p = this->clauses_.begin();
6003 8697 : p != this->clauses_.end();
6004 6746 : ++p)
6005 : {
6006 6746 : int index;
6007 6746 : if (p->is_default())
6008 : index = -1;
6009 5879 : else if (p->is_send())
6010 : {
6011 1374 : index = send_index;
6012 1374 : ++send_index;
6013 : }
6014 : else
6015 : {
6016 4505 : index = recv_index;
6017 4505 : ++recv_index;
6018 : }
6019 :
6020 6746 : p->lower(gogo, function, b, scases, index, recvok);
6021 : }
6022 :
6023 1951 : go_assert(send_index == send_count);
6024 1951 : go_assert(recv_index == send_count + recv_count);
6025 3035 : go_assert(static_cast<size_t>(recv_index + (has_default ? 1 : 0))
6026 : == this->size());
6027 1951 : }
6028 :
6029 : // Determine types.
6030 :
6031 : void
6032 2695 : Select_clauses::determine_types(Gogo* gogo)
6033 : {
6034 10765 : for (Clauses::iterator p = this->clauses_.begin();
6035 10765 : p != this->clauses_.end();
6036 8070 : ++p)
6037 8070 : p->determine_types(gogo);
6038 2695 : }
6039 :
6040 : // Check types.
6041 :
6042 : void
6043 2656 : Select_clauses::check_types()
6044 : {
6045 10646 : for (Clauses::iterator p = this->clauses_.begin();
6046 10646 : p != this->clauses_.end();
6047 7990 : ++p)
6048 7990 : p->check_types();
6049 2656 : }
6050 :
6051 : // Return whether these select clauses fall through to the statement
6052 : // following the overall select statement.
6053 :
6054 : bool
6055 194 : Select_clauses::may_fall_through() const
6056 : {
6057 588 : for (Clauses::const_iterator p = this->clauses_.begin();
6058 588 : p != this->clauses_.end();
6059 394 : ++p)
6060 406 : if (p->may_fall_through())
6061 194 : return true;
6062 : return false;
6063 : }
6064 :
6065 : // Convert to the backend representation. Assemble the clauses and
6066 : // build a switch statement on the index value returned by the call to
6067 : // selectgo.
6068 :
6069 : Bstatement*
6070 1945 : Select_clauses::get_backend(Translate_context* context,
6071 : Temporary_statement* index,
6072 : Unnamed_label *break_label,
6073 : Location location)
6074 : {
6075 1945 : size_t count = this->clauses_.size();
6076 1945 : std::vector<std::vector<Bexpression*> > cases(count + 1);
6077 1945 : std::vector<Bstatement*> clauses(count + 1);
6078 :
6079 1945 : Type* int_type = Type::lookup_integer_type("int");
6080 :
6081 1945 : int i = 0;
6082 1945 : for (Clauses::iterator p = this->clauses_.begin();
6083 8679 : p != this->clauses_.end();
6084 6734 : ++p, ++i)
6085 : {
6086 6734 : Expression* index_expr = Expression::make_integer_sl(p->case_index(),
6087 : int_type,
6088 : location);
6089 6734 : cases[i].push_back(index_expr->get_backend(context));
6090 :
6091 6734 : Bstatement* s = p->get_statements_backend(context);
6092 6734 : Location gloc = (p->statements() == NULL
6093 6734 : ? p->location()
6094 6734 : : p->statements()->end_location());
6095 6734 : Bstatement* g = break_label->get_goto(context, gloc);
6096 :
6097 6734 : if (s == NULL)
6098 0 : clauses[i] = g;
6099 : else
6100 6734 : clauses[i] = context->backend()->compound_statement(s, g);
6101 : }
6102 :
6103 1945 : Expression* ref = Expression::make_temporary_reference(index, location);
6104 1945 : Bexpression* bindex = ref->get_backend(context);
6105 :
6106 1945 : Bfunction* bfunction = context->function()->func_value()->get_decl();
6107 :
6108 1945 : if (count == 0)
6109 0 : return context->backend()->expression_statement(bfunction, bindex);
6110 :
6111 1945 : Gogo* gogo = context->gogo();
6112 1945 : Expression* crash = Runtime::make_call(gogo, Runtime::UNREACHABLE,
6113 : location, 0);
6114 1945 : crash->determine_type_no_context(gogo);
6115 1945 : Bexpression* bcrash = crash->get_backend(context);
6116 1945 : clauses[count] = context->backend()->expression_statement(bfunction, bcrash);
6117 :
6118 1945 : std::vector<Bstatement*> statements;
6119 1945 : statements.reserve(2);
6120 :
6121 1945 : Bstatement* switch_stmt = context->backend()->switch_statement(bfunction,
6122 : bindex,
6123 : cases,
6124 : clauses,
6125 1945 : location);
6126 1945 : statements.push_back(switch_stmt);
6127 :
6128 1945 : Bstatement* ldef = break_label->get_definition(context);
6129 1945 : statements.push_back(ldef);
6130 :
6131 1945 : return context->backend()->statement_list(statements);
6132 3890 : }
6133 :
6134 : // Dump the AST representation for select clauses.
6135 :
6136 : void
6137 0 : Select_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
6138 : {
6139 0 : for (Clauses::const_iterator p = this->clauses_.begin();
6140 0 : p != this->clauses_.end();
6141 0 : ++p)
6142 0 : p->dump_clause(ast_dump_context);
6143 0 : }
6144 :
6145 : // Class Select_statement.
6146 :
6147 : // Return the break label for this switch statement, creating it if
6148 : // necessary.
6149 :
6150 : Unnamed_label*
6151 2671 : Select_statement::break_label()
6152 : {
6153 2671 : if (this->break_label_ == NULL)
6154 2607 : this->break_label_ = new Unnamed_label(this->location());
6155 2671 : return this->break_label_;
6156 : }
6157 :
6158 : // Lower a select statement. This will return a block containing this
6159 : // select statement. The block will implement the order of evaluation
6160 : // rules, include the send and receive statements as explicit
6161 : // statements in the clauses, and call the runtime selectgo function.
6162 :
6163 : Statement*
6164 5033 : Select_statement::do_lower(Gogo* gogo, Named_object* function,
6165 : Block* enclosing, Statement_inserter*)
6166 : {
6167 5033 : if (this->is_lowered_)
6168 2377 : return this;
6169 :
6170 2656 : Location loc = this->location();
6171 :
6172 2656 : Block* b = new Block(enclosing, loc);
6173 :
6174 2656 : int ncases = this->clauses_->size();
6175 2656 : bool has_default = this->clauses_->has_default();
6176 :
6177 : // Zero-case select. Just block the execution.
6178 2656 : if (ncases == 0)
6179 : {
6180 45 : Expression* call = Runtime::make_call(gogo, Runtime::BLOCK, loc, 0);
6181 45 : Statement *s = Statement::make_statement(call, false);
6182 45 : s->determine_types(gogo);
6183 45 : b->add_statement(s);
6184 45 : this->is_lowered_ = true;
6185 45 : return Statement::make_block_statement(b, loc);
6186 : }
6187 :
6188 : // One-case select. It is mostly just to run the case.
6189 2611 : if (ncases == 1)
6190 76 : return this->lower_one_case(gogo, b);
6191 :
6192 : // Two-case select with one default case. It is a non-blocking
6193 : // send/receive.
6194 2535 : if (ncases == 2 && has_default)
6195 584 : return this->lower_two_case(gogo, b);
6196 :
6197 : // We don't allocate an entry in scases for the default case.
6198 1951 : if (has_default)
6199 867 : --ncases;
6200 :
6201 1951 : Type* scase_type = Channel_type::select_case_type();
6202 1951 : Expression* ncases_expr =
6203 1951 : Expression::make_integer_ul(ncases, NULL,
6204 : Linemap::predeclared_location());
6205 1951 : Array_type* scases_type = Type::make_array_type(scase_type, ncases_expr);
6206 1951 : scases_type->set_is_array_incomparable();
6207 :
6208 1951 : Temporary_statement* scases = Statement::make_temporary(scases_type, NULL,
6209 : loc);
6210 1951 : b->add_statement(scases);
6211 :
6212 1951 : Expression* ncases2_expr =
6213 1951 : Expression::make_integer_ul(ncases * 2, NULL,
6214 : Linemap::predeclared_location());
6215 1951 : Type* uint16_type = Type::lookup_integer_type("uint16");
6216 1951 : Array_type* order_type = Type::make_array_type(uint16_type, ncases2_expr);
6217 1951 : order_type->set_is_array_incomparable();
6218 :
6219 1951 : Temporary_statement* order = Statement::make_temporary(order_type, NULL,
6220 : loc);
6221 1951 : b->add_statement(order);
6222 :
6223 1951 : Type* int_type = Type::lookup_integer_type("int");
6224 1951 : this->index_ = Statement::make_temporary(int_type, NULL, loc);
6225 1951 : b->add_statement(this->index_);
6226 :
6227 1951 : Type* bool_type = Type::lookup_bool_type();
6228 1951 : Temporary_statement* recvok = Statement::make_temporary(bool_type, NULL,
6229 : loc);
6230 1951 : b->add_statement(recvok);
6231 :
6232 : // Initialize the scases array.
6233 1951 : int send_count;
6234 1951 : int recv_count;
6235 1951 : this->clauses_->lower(gogo, function, b, scases, recvok, &send_count,
6236 : &recv_count);
6237 :
6238 : // Build the call to selectgo. Later, in do_get_backend, we will
6239 : // build a switch on the result that branches to the various cases.
6240 :
6241 1951 : Expression* scases_ref = Expression::make_temporary_reference(scases, loc);
6242 1951 : scases_ref = Expression::make_unary(OPERATOR_AND, scases_ref, loc);
6243 1951 : Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
6244 1951 : scases_ref = Expression::make_cast(unsafe_pointer_type, scases_ref, loc);
6245 :
6246 1951 : Expression* order_ref = Expression::make_temporary_reference(order, loc);
6247 1951 : order_ref = Expression::make_unary(OPERATOR_AND, order_ref, loc);
6248 1951 : order_ref = Expression::make_cast(unsafe_pointer_type, order_ref, loc);
6249 :
6250 1951 : Expression* send_count_expr = Expression::make_integer_sl(send_count,
6251 : int_type,
6252 : loc);
6253 1951 : Expression* recv_count_expr = Expression::make_integer_sl(recv_count,
6254 : int_type,
6255 : loc);
6256 1951 : Expression* block_expr = Expression::make_boolean(!has_default, loc);
6257 :
6258 1951 : Call_expression* call = Runtime::make_call(gogo, Runtime::SELECTGO, loc, 5,
6259 : scases_ref, order_ref,
6260 : send_count_expr, recv_count_expr,
6261 : block_expr);
6262 :
6263 1951 : Expression* result = Expression::make_call_result(call, 0);
6264 1951 : Expression* ref = Expression::make_temporary_reference(this->index_, loc);
6265 1951 : Statement* s = Statement::make_assignment(ref, result, loc);
6266 1951 : s->determine_types(gogo);
6267 1951 : b->add_statement(s);
6268 :
6269 1951 : result = Expression::make_call_result(call, 1);
6270 1951 : ref = Expression::make_temporary_reference(recvok, loc);
6271 1951 : s = Statement::make_assignment(ref, result, loc);
6272 1951 : s->determine_types(gogo);
6273 1951 : b->add_statement(s);
6274 :
6275 1951 : this->is_lowered_ = true;
6276 1951 : b->add_statement(this);
6277 :
6278 1951 : return Statement::make_block_statement(b, loc);
6279 : }
6280 :
6281 : // Lower a one-case select statement.
6282 :
6283 : Statement*
6284 76 : Select_statement::lower_one_case(Gogo* gogo, Block* b)
6285 : {
6286 76 : Select_clauses::Select_clause& scase = this->clauses_->at(0);
6287 76 : Location loc = this->location();
6288 76 : Expression* chan = scase.channel();
6289 76 : if (chan != NULL)
6290 : {
6291 : // Lower this to
6292 : // if chan == nil { block() }; send/recv; body
6293 63 : Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc);
6294 63 : b->add_statement(chantmp);
6295 63 : Expression* chanref = Expression::make_temporary_reference(chantmp, loc);
6296 :
6297 63 : Expression* nil = Expression::make_nil(loc);
6298 63 : Expression* cond = Expression::make_binary(OPERATOR_EQEQ, chanref, nil, loc);
6299 63 : Block* bnil = new Block(b, loc);
6300 63 : Expression* call = Runtime::make_call(gogo, Runtime::BLOCK, loc, 0);
6301 63 : Statement* s = Statement::make_statement(call, false);
6302 63 : s->determine_types(gogo);
6303 63 : bnil->add_statement(s);
6304 63 : Statement* ifs = Statement::make_if_statement(cond, bnil, NULL, loc);
6305 63 : ifs->determine_types(gogo);
6306 63 : b->add_statement(ifs);
6307 :
6308 63 : chanref = chanref->copy();
6309 63 : Location cloc = scase.location();
6310 63 : if (scase.is_send())
6311 : {
6312 7 : s = Statement::make_send_statement(chanref, scase.val(), cloc);
6313 7 : s->determine_types(gogo);
6314 7 : b->add_statement(s);
6315 : }
6316 : else
6317 : {
6318 56 : if (scase.closed() == NULL && scase.closedvar() == NULL)
6319 : {
6320 : // Simple receive.
6321 51 : Expression* recv = Expression::make_receive(chanref, cloc);
6322 51 : if (scase.val() != NULL)
6323 9 : s = Statement::make_assignment(scase.val(), recv, cloc);
6324 42 : else if (scase.var() != NULL)
6325 : {
6326 7 : Temporary_statement *ts =
6327 7 : Statement::make_temporary(NULL, recv, cloc);
6328 7 : Expression* ref =
6329 7 : Expression::make_temporary_reference(ts, cloc);
6330 7 : s = ts;
6331 7 : scase.var()->var_value()->set_init(ref);
6332 7 : scase.var()->var_value()->clear_type_from_chan_element();
6333 : }
6334 : else
6335 35 : s = Statement::make_statement(recv, false);
6336 51 : s->determine_types(gogo);
6337 51 : b->add_statement(s);
6338 : }
6339 : else
6340 : {
6341 : // Tuple receive.
6342 5 : Expression* lhs;
6343 5 : if (scase.val() != NULL)
6344 : lhs = scase.val();
6345 : else
6346 : {
6347 8 : Type* valtype = chan->type()->channel_type()->element_type();
6348 4 : Temporary_statement *ts =
6349 4 : Statement::make_temporary(valtype, NULL, cloc);
6350 4 : lhs = Expression::make_temporary_reference(ts, cloc);
6351 4 : b->add_statement(ts);
6352 : }
6353 :
6354 5 : Expression* lhs2;
6355 5 : if (scase.closed() != NULL)
6356 : lhs2 = scase.closed();
6357 : else
6358 : {
6359 4 : Type* booltype = Type::make_boolean_type();
6360 4 : Temporary_statement *ts =
6361 4 : Statement::make_temporary(booltype, NULL, cloc);
6362 4 : lhs2 = Expression::make_temporary_reference(ts, cloc);
6363 4 : b->add_statement(ts);
6364 : }
6365 :
6366 5 : s = Statement::make_tuple_receive_assignment(lhs, lhs2, chanref, cloc);
6367 5 : s->determine_types(gogo);
6368 5 : b->add_statement(s);
6369 :
6370 5 : if (scase.var() != NULL)
6371 : {
6372 3 : scase.var()->var_value()->set_init(lhs->copy());
6373 3 : scase.var()->var_value()->clear_type_from_chan_element();
6374 : }
6375 :
6376 5 : if (scase.closedvar() != NULL)
6377 4 : scase.closedvar()->var_value()->set_init(lhs2->copy());
6378 : }
6379 : }
6380 : }
6381 :
6382 76 : Statement* bs =
6383 76 : Statement::make_block_statement(scase.statements(), scase.location());
6384 76 : b->add_statement(bs);
6385 :
6386 76 : Statement* label =
6387 76 : Statement::make_unnamed_label_statement(this->break_label());
6388 76 : b->add_statement(label);
6389 :
6390 76 : this->is_lowered_ = true;
6391 76 : return Statement::make_block_statement(b, loc);
6392 : }
6393 :
6394 : // Lower a two-case select statement with one default case.
6395 :
6396 : Statement*
6397 584 : Select_statement::lower_two_case(Gogo* gogo, Block* b)
6398 : {
6399 584 : Select_clauses::Select_clause& chancase =
6400 584 : (this->clauses_->at(0).is_default()
6401 584 : ? this->clauses_->at(1)
6402 495 : : this->clauses_->at(0));
6403 584 : Select_clauses::Select_clause& defcase =
6404 584 : (this->clauses_->at(0).is_default()
6405 584 : ? this->clauses_->at(0)
6406 495 : : this->clauses_->at(1));
6407 584 : Location loc = this->location();
6408 584 : Expression* chan = chancase.channel();
6409 1168 : Type* valtype = chan->type()->channel_type()->element_type();
6410 :
6411 584 : Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc);
6412 584 : b->add_statement(chantmp);
6413 584 : Expression* chanref = Expression::make_temporary_reference(chantmp, loc);
6414 :
6415 584 : Block* bchan;
6416 584 : Expression* cond;
6417 584 : if (chancase.is_send())
6418 : {
6419 : // if selectnbsend(chan, &val) { body } else { default body }
6420 :
6421 99 : Temporary_statement* ts =
6422 99 : Statement::make_temporary(valtype, chancase.val(), loc);
6423 : // Tell the escape analysis that the value escapes, as it may be sent
6424 : // to a channel.
6425 99 : ts->set_value_escapes();
6426 99 : b->add_statement(ts);
6427 :
6428 99 : Expression* ref = Expression::make_temporary_reference(ts, loc);
6429 99 : Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
6430 99 : cond = Runtime::make_call(gogo, Runtime::SELECTNBSEND, loc, 2,
6431 : chanref, addr);
6432 99 : bchan = chancase.statements();
6433 : }
6434 : else
6435 : {
6436 485 : Temporary_statement* ts = Statement::make_temporary(valtype, NULL, loc);
6437 485 : b->add_statement(ts);
6438 :
6439 485 : Expression* ref = Expression::make_temporary_reference(ts, loc);
6440 485 : Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
6441 :
6442 : // selected, ok = selectnbrecv(&lhs, chan)
6443 485 : Call_expression* call = Runtime::make_call(gogo, Runtime::SELECTNBRECV,
6444 : loc, 2, addr, chanref);
6445 :
6446 485 : Temporary_statement* selected_temp =
6447 485 : Statement::make_temporary(Type::make_boolean_type(),
6448 : Expression::make_call_result(call, 0),
6449 : loc);
6450 485 : selected_temp->determine_types(gogo);
6451 485 : b->add_statement(selected_temp);
6452 :
6453 485 : Temporary_statement* ok_temp =
6454 485 : Statement::make_temporary(Type::make_boolean_type(),
6455 : Expression::make_call_result(call, 1),
6456 : loc);
6457 485 : ok_temp->determine_types(gogo);
6458 485 : b->add_statement(ok_temp);
6459 :
6460 485 : cond = Expression::make_temporary_reference(selected_temp, loc);
6461 :
6462 485 : Location cloc = chancase.location();
6463 485 : bchan = new Block(b, loc);
6464 485 : if (chancase.val() != NULL && !chancase.val()->is_sink_expression())
6465 : {
6466 43 : Statement* as = Statement::make_assignment(chancase.val(),
6467 : ref->copy(),
6468 : cloc);
6469 43 : as->determine_types(gogo);
6470 43 : bchan->add_statement(as);
6471 : }
6472 442 : else if (chancase.var() != NULL)
6473 : {
6474 54 : chancase.var()->var_value()->set_init(ref->copy());
6475 54 : chancase.var()->var_value()->clear_type_from_chan_element();
6476 : }
6477 :
6478 485 : if (chancase.closed() != NULL && !chancase.closed()->is_sink_expression())
6479 : {
6480 1 : Expression* okref = Expression::make_temporary_reference(ok_temp,
6481 : cloc);
6482 1 : Statement* as = Statement::make_assignment(chancase.closed(),
6483 : okref, cloc);
6484 1 : as->determine_types(gogo);
6485 1 : bchan->add_statement(as);
6486 : }
6487 484 : else if (chancase.closedvar() != NULL)
6488 : {
6489 9 : Expression* okref = Expression::make_temporary_reference(ok_temp,
6490 : cloc);
6491 9 : chancase.closedvar()->var_value()->set_init(okref);
6492 : }
6493 :
6494 485 : Statement* bs = Statement::make_block_statement(chancase.statements(),
6495 : cloc);
6496 485 : bchan->add_statement(bs);
6497 : }
6498 :
6499 584 : Statement* ifs =
6500 584 : Statement::make_if_statement(cond, bchan, defcase.statements(), loc);
6501 584 : ifs->determine_types(gogo);
6502 584 : b->add_statement(ifs);
6503 :
6504 584 : Statement* label =
6505 584 : Statement::make_unnamed_label_statement(this->break_label());
6506 584 : b->add_statement(label);
6507 :
6508 584 : this->is_lowered_ = true;
6509 584 : return Statement::make_block_statement(b, loc);
6510 : }
6511 :
6512 : // Whether the select statement itself may fall through to the following
6513 : // statement.
6514 :
6515 : bool
6516 214 : Select_statement::do_may_fall_through() const
6517 : {
6518 : // A select statement is terminating if no break statement
6519 : // refers to it and all of its clauses are terminating.
6520 214 : if (this->break_label_ != NULL)
6521 : return true;
6522 194 : return this->clauses_->may_fall_through();
6523 : }
6524 :
6525 : // Return the backend representation for a select statement.
6526 :
6527 : Bstatement*
6528 1945 : Select_statement::do_get_backend(Translate_context* context)
6529 : {
6530 1945 : return this->clauses_->get_backend(context, this->index_,
6531 1945 : this->break_label(), this->location());
6532 : }
6533 :
6534 : // Dump the AST representation for a select statement.
6535 :
6536 : void
6537 0 : Select_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
6538 : {
6539 0 : ast_dump_context->print_indent();
6540 0 : ast_dump_context->ostream() << "select";
6541 0 : if (ast_dump_context->dump_subblocks())
6542 : {
6543 0 : ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
6544 0 : this->clauses_->dump_clauses(ast_dump_context);
6545 0 : ast_dump_context->print_indent();
6546 0 : ast_dump_context->ostream() << "}";
6547 : }
6548 0 : ast_dump_context->ostream() << std::endl;
6549 0 : }
6550 :
6551 : // Make a select statement.
6552 :
6553 : Select_statement*
6554 2656 : Statement::make_select_statement(Location location)
6555 : {
6556 2656 : return new Select_statement(location);
6557 : }
6558 :
6559 : // Class For_statement.
6560 :
6561 : // Traversal.
6562 :
6563 : int
6564 174482 : For_statement::do_traverse(Traverse* traverse)
6565 : {
6566 174482 : if (this->init_ != NULL)
6567 : {
6568 34013 : if (this->init_->traverse(traverse) == TRAVERSE_EXIT)
6569 : return TRAVERSE_EXIT;
6570 : }
6571 174482 : if (this->cond_ != NULL)
6572 : {
6573 155516 : if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT)
6574 : return TRAVERSE_EXIT;
6575 : }
6576 174482 : if (this->post_ != NULL)
6577 : {
6578 123247 : if (this->post_->traverse(traverse) == TRAVERSE_EXIT)
6579 : return TRAVERSE_EXIT;
6580 : }
6581 174482 : return this->statements_->traverse(traverse);
6582 : }
6583 :
6584 : void
6585 62188 : For_statement::do_determine_types(Gogo* gogo)
6586 : {
6587 62188 : if (this->init_ != NULL)
6588 34013 : this->init_->determine_types(gogo);
6589 62188 : if (this->cond_ != NULL)
6590 58314 : this->cond_->determine_type_no_context(gogo);
6591 62188 : if (this->post_ != NULL)
6592 51860 : this->post_->determine_types(gogo);
6593 62188 : this->statements_->determine_types(gogo);
6594 62188 : }
6595 :
6596 : void
6597 28074 : For_statement::do_check_types(Gogo*)
6598 : {
6599 28074 : if (this->cond_ != NULL)
6600 : {
6601 24301 : Type* type = this->cond_->type();
6602 24301 : if (type->is_error())
6603 1 : this->set_is_error();
6604 24300 : else if (!type->is_boolean_type())
6605 : {
6606 1 : go_error_at(this->cond_->location(), "expected boolean expression");
6607 1 : this->set_is_error();
6608 : }
6609 : }
6610 28074 : }
6611 :
6612 : // Lower a For_statement into if statements and gotos. Getting rid of
6613 : // complex statements make it easier to handle garbage collection.
6614 :
6615 : Statement*
6616 62186 : For_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
6617 : Statement_inserter*)
6618 : {
6619 62186 : Location loc = this->location();
6620 :
6621 62186 : if (this->classification() == STATEMENT_ERROR)
6622 0 : return Statement::make_error_statement(loc);
6623 :
6624 62186 : Statement* s;
6625 62186 : Block* b = new Block(enclosing, this->location());
6626 62186 : if (this->init_ != NULL)
6627 : {
6628 68026 : s = Statement::make_block_statement(this->init_,
6629 34013 : this->init_->start_location());
6630 34013 : b->add_statement(s);
6631 : }
6632 :
6633 62186 : Unnamed_label* entry = NULL;
6634 62186 : if (this->cond_ != NULL)
6635 : {
6636 58312 : entry = new Unnamed_label(this->location());
6637 58312 : b->add_statement(Statement::make_goto_unnamed_statement(entry, loc));
6638 : }
6639 :
6640 62186 : Unnamed_label* top = new Unnamed_label(this->location());
6641 62186 : top->set_derived_from(this);
6642 62186 : b->add_statement(Statement::make_unnamed_label_statement(top));
6643 :
6644 124372 : s = Statement::make_block_statement(this->statements_,
6645 62186 : this->statements_->start_location());
6646 62186 : b->add_statement(s);
6647 :
6648 62186 : Location end_loc = this->statements_->end_location();
6649 :
6650 62186 : Unnamed_label* cont = this->continue_label_;
6651 62186 : if (cont != NULL)
6652 6370 : b->add_statement(Statement::make_unnamed_label_statement(cont));
6653 :
6654 62186 : if (this->post_ != NULL)
6655 : {
6656 103718 : s = Statement::make_block_statement(this->post_,
6657 51859 : this->post_->start_location());
6658 51859 : b->add_statement(s);
6659 51859 : end_loc = this->post_->end_location();
6660 : }
6661 :
6662 62186 : if (this->cond_ == NULL)
6663 3874 : b->add_statement(Statement::make_goto_unnamed_statement(top, end_loc));
6664 : else
6665 : {
6666 58312 : b->add_statement(Statement::make_unnamed_label_statement(entry));
6667 :
6668 58312 : Location cond_loc = this->cond_->location();
6669 58312 : Block* then_block = new Block(b, cond_loc);
6670 58312 : s = Statement::make_goto_unnamed_statement(top, cond_loc);
6671 58312 : then_block->add_statement(s);
6672 :
6673 58312 : s = Statement::make_if_statement(this->cond_, then_block, NULL, cond_loc);
6674 58312 : s->determine_types(gogo);
6675 58312 : b->add_statement(s);
6676 : }
6677 :
6678 62186 : Unnamed_label* brk = this->break_label_;
6679 62186 : if (brk != NULL)
6680 5600 : b->add_statement(Statement::make_unnamed_label_statement(brk));
6681 :
6682 62186 : b->set_end_location(end_loc);
6683 :
6684 62186 : Statement* bs = Statement::make_block_statement(b, loc);
6685 62186 : bs->block_statement()->set_is_lowered_for_statement();
6686 62186 : return bs;
6687 : }
6688 :
6689 : // Return the break label, creating it if necessary.
6690 :
6691 : Unnamed_label*
6692 5391 : For_statement::break_label()
6693 : {
6694 5391 : if (this->break_label_ == NULL)
6695 4186 : this->break_label_ = new Unnamed_label(this->location());
6696 5391 : return this->break_label_;
6697 : }
6698 :
6699 : // Return the continue LABEL_EXPR.
6700 :
6701 : Unnamed_label*
6702 4887 : For_statement::continue_label()
6703 : {
6704 4887 : if (this->continue_label_ == NULL)
6705 2807 : this->continue_label_ = new Unnamed_label(this->location());
6706 4887 : return this->continue_label_;
6707 : }
6708 :
6709 : // Set the break and continue labels a for statement. This is used
6710 : // when lowering a for range statement.
6711 :
6712 : void
6713 34114 : For_statement::set_break_continue_labels(Unnamed_label* break_label,
6714 : Unnamed_label* continue_label)
6715 : {
6716 34114 : go_assert(this->break_label_ == NULL && this->continue_label_ == NULL);
6717 34114 : this->break_label_ = break_label;
6718 34114 : this->continue_label_ = continue_label;
6719 34114 : }
6720 :
6721 : // Whether the overall statement may fall through.
6722 :
6723 : bool
6724 1095 : For_statement::do_may_fall_through() const
6725 : {
6726 : // A for loop is terminating if it has no condition and
6727 : // no break statement.
6728 1095 : if(this->cond_ != NULL)
6729 : return true;
6730 1071 : if(this->break_label_ != NULL)
6731 12 : return true;
6732 : return false;
6733 : }
6734 :
6735 : // Dump the AST representation for a for statement.
6736 :
6737 : void
6738 0 : For_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
6739 : {
6740 0 : if (this->init_ != NULL && ast_dump_context->dump_subblocks())
6741 : {
6742 0 : ast_dump_context->print_indent();
6743 0 : ast_dump_context->indent();
6744 0 : ast_dump_context->ostream() << "// INIT " << std::endl;
6745 0 : ast_dump_context->dump_block(this->init_);
6746 0 : ast_dump_context->unindent();
6747 : }
6748 0 : ast_dump_context->print_indent();
6749 0 : ast_dump_context->ostream() << "for ";
6750 0 : if (this->cond_ != NULL)
6751 0 : ast_dump_context->dump_expression(this->cond_);
6752 :
6753 0 : if (ast_dump_context->dump_subblocks())
6754 : {
6755 0 : ast_dump_context->ostream() << " {" << std::endl;
6756 0 : ast_dump_context->dump_block(this->statements_);
6757 0 : if (this->init_ != NULL)
6758 : {
6759 0 : ast_dump_context->print_indent();
6760 0 : ast_dump_context->ostream() << "// POST " << std::endl;
6761 0 : ast_dump_context->dump_block(this->post_);
6762 : }
6763 0 : ast_dump_context->unindent();
6764 :
6765 0 : ast_dump_context->print_indent();
6766 0 : ast_dump_context->ostream() << "}";
6767 : }
6768 :
6769 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
6770 0 : }
6771 :
6772 : // Make a for statement.
6773 :
6774 : For_statement*
6775 62188 : Statement::make_for_statement(Block* init, Expression* cond, Block* post,
6776 : Location location)
6777 : {
6778 62188 : return new For_statement(init, cond, post, location);
6779 : }
6780 :
6781 : // Class For_range_statement.
6782 :
6783 : // Traversal.
6784 :
6785 : int
6786 137404 : For_range_statement::do_traverse(Traverse* traverse)
6787 : {
6788 137404 : if (this->index_var_ != NULL)
6789 : {
6790 136950 : if (this->traverse_expression(traverse, &this->index_var_)
6791 : == TRAVERSE_EXIT)
6792 : return TRAVERSE_EXIT;
6793 : }
6794 137404 : if (this->value_var_ != NULL)
6795 : {
6796 111400 : if (this->traverse_expression(traverse, &this->value_var_)
6797 : == TRAVERSE_EXIT)
6798 : return TRAVERSE_EXIT;
6799 : }
6800 137404 : if (this->traverse_expression(traverse, &this->range_) == TRAVERSE_EXIT)
6801 : return TRAVERSE_EXIT;
6802 137404 : return this->statements_->traverse(traverse);
6803 : }
6804 :
6805 : void
6806 43116 : For_range_statement::do_determine_types(Gogo* gogo)
6807 : {
6808 43116 : if (this->index_var_ != NULL)
6809 43025 : this->index_var_->determine_type_no_context(gogo);
6810 43116 : if (this->value_var_ != NULL)
6811 22280 : this->value_var_->determine_type_no_context(gogo);
6812 43116 : this->range_->determine_type_no_context(gogo);
6813 43116 : this->statements_->determine_types(gogo);
6814 43116 : }
6815 :
6816 : void
6817 25744 : For_range_statement::do_check_types(Gogo*)
6818 : {
6819 25744 : Type* range_type = this->range_->type();
6820 :
6821 25744 : Type* index_type;
6822 25744 : Type* value_type = NULL;
6823 :
6824 25744 : if (range_type->points_to() != NULL
6825 207 : && range_type->points_to()->array_type() != NULL
6826 25951 : && !range_type->points_to()->is_slice_type())
6827 207 : range_type = range_type->points_to();
6828 :
6829 25744 : if (range_type->array_type() != NULL)
6830 : {
6831 22962 : index_type = Type::lookup_integer_type("int");
6832 45924 : value_type = range_type->array_type()->element_type();
6833 : }
6834 2782 : else if (range_type->is_string_type())
6835 : {
6836 612 : index_type = Type::lookup_integer_type("int");
6837 612 : value_type = Type::lookup_integer_type("rune");
6838 : }
6839 2170 : else if (range_type->map_type() != NULL)
6840 : {
6841 4134 : index_type = range_type->map_type()->key_type();
6842 4134 : value_type = range_type->map_type()->val_type();
6843 : }
6844 103 : else if (range_type->channel_type() != NULL)
6845 : {
6846 206 : if (!range_type->channel_type()->may_receive())
6847 2 : this->report_error(_("invalid receive on send-only channel"));
6848 206 : index_type = range_type->channel_type()->element_type();
6849 103 : if (this->value_var_ != NULL)
6850 : {
6851 0 : if (!this->value_var_->type()->is_error())
6852 0 : this->report_error(_("too many variables for range clause "
6853 : "with channel"));
6854 0 : this->set_is_error();
6855 0 : return;
6856 : }
6857 : }
6858 : else
6859 : {
6860 0 : this->report_error(_("range clause must have "
6861 : "array, slice, string, map, or channel type"));
6862 0 : return;
6863 : }
6864 :
6865 25744 : if (this->index_var_ != NULL
6866 25744 : && !Assignment_statement::check_assignment_types(this->index_var_,
6867 : index_type,
6868 : this->location()))
6869 0 : this->set_is_error();
6870 25744 : if (this->value_var_ != NULL
6871 25744 : && !Assignment_statement::check_assignment_types(this->value_var_,
6872 : value_type,
6873 : this->location()))
6874 0 : this->set_is_error();
6875 : }
6876 :
6877 : // Lower a for range statement. For simplicity we lower this into a
6878 : // for statement, which will then be lowered in turn to goto
6879 : // statements.
6880 :
6881 : Statement*
6882 34428 : For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
6883 : Statement_inserter*)
6884 : {
6885 34428 : if (this->classification() == STATEMENT_ERROR)
6886 0 : return Statement::make_error_statement(this->location());
6887 :
6888 34428 : Type* range_type = this->range_->type();
6889 34428 : if (range_type->points_to() != NULL
6890 8893 : && range_type->points_to()->array_type() != NULL
6891 43321 : && !range_type->points_to()->is_slice_type())
6892 8893 : range_type = range_type->points_to();
6893 :
6894 34428 : Type* index_type;
6895 34428 : Type* value_type = NULL;
6896 34428 : if (range_type->array_type() != NULL)
6897 : {
6898 31648 : index_type = Type::lookup_integer_type("int");
6899 63296 : value_type = range_type->array_type()->element_type();
6900 : }
6901 2780 : else if (range_type->is_string_type())
6902 : {
6903 612 : index_type = Type::lookup_integer_type("int");
6904 612 : value_type = Type::lookup_integer_type("rune");
6905 : }
6906 2168 : else if (range_type->map_type() != NULL)
6907 : {
6908 4134 : index_type = range_type->map_type()->key_type();
6909 4134 : value_type = range_type->map_type()->val_type();
6910 : }
6911 101 : else if (range_type->channel_type() != NULL)
6912 : {
6913 202 : index_type = range_type->channel_type()->element_type();
6914 101 : go_assert(this->value_var_ == NULL);
6915 : }
6916 : else
6917 0 : go_unreachable();
6918 :
6919 : // If there is only one iteration variable, and len(this->range_) is
6920 : // constant, then we do not evaluate the range variable. len(x) is
6921 : // a contant if x is a string constant or if x is an array. If x is
6922 : // a constant then evaluating it won't make any difference, so the
6923 : // only case to consider is when x is an array whose length is constant.
6924 34428 : bool eval = true;
6925 22280 : if ((this->value_var_ == NULL || this->value_var_->is_sink_expression())
6926 45786 : && range_type->array_type() != NULL
6927 11358 : && !range_type->is_slice_type()
6928 43732 : && Builtin_call_expression::array_len_is_constant(this->range_))
6929 : eval = false;
6930 :
6931 34428 : Location loc = this->location();
6932 34428 : Block* temp_block = new Block(enclosing, loc);
6933 :
6934 34428 : Expression* orig_range_expr = this->range_;
6935 34428 : Named_object* range_object = NULL;
6936 34428 : Temporary_statement* range_temp = NULL;
6937 34428 : if (eval)
6938 : {
6939 25128 : Var_expression* ve = this->range_->var_expression();
6940 25128 : if (ve != NULL)
6941 14959 : range_object = ve->named_object();
6942 : else
6943 : {
6944 10169 : range_temp = Statement::make_temporary(NULL, this->range_, loc);
6945 10169 : temp_block->add_statement(range_temp);
6946 10169 : this->range_ = NULL;
6947 : }
6948 : }
6949 :
6950 : // Try to match "range clear" patterns and rewrite to simple runtime
6951 : // calls.
6952 34428 : if (range_type->map_type() != NULL)
6953 : {
6954 2067 : Statement* clear = this->lower_map_range_clear(gogo,
6955 : range_type,
6956 : enclosing,
6957 : orig_range_expr,
6958 : range_object,
6959 : range_temp, loc);
6960 2067 : if (clear != NULL)
6961 : {
6962 33 : if (gogo->debug_optimization())
6963 1 : go_debug(loc, "map range clear");
6964 33 : clear->determine_types(gogo);
6965 33 : temp_block->add_statement(clear);
6966 33 : return Statement::make_block_statement(temp_block, loc);
6967 : }
6968 : }
6969 32361 : else if (range_type->array_type() != NULL)
6970 : {
6971 : // Slice or array.
6972 31648 : Statement* clear = this->lower_array_range_clear(gogo,
6973 : range_type,
6974 : orig_range_expr,
6975 : temp_block,
6976 : range_object,
6977 : range_temp, loc);
6978 31648 : if (clear != NULL)
6979 : {
6980 281 : if (gogo->debug_optimization())
6981 2 : go_debug(loc, "array range clear");
6982 281 : clear->determine_types(gogo);
6983 281 : temp_block->add_statement(clear);
6984 281 : return Statement::make_block_statement(temp_block, loc);
6985 : }
6986 : }
6987 :
6988 34114 : Temporary_statement* index_temp = Statement::make_temporary(index_type,
6989 : NULL, loc);
6990 34114 : temp_block->add_statement(index_temp);
6991 :
6992 34114 : Temporary_statement* value_temp = NULL;
6993 34114 : if (this->value_var_ != NULL && !this->value_var_->is_sink_expression())
6994 : {
6995 22252 : value_temp = Statement::make_temporary(value_type, NULL, loc);
6996 22252 : temp_block->add_statement(value_temp);
6997 : }
6998 :
6999 34114 : Block* body = new Block(temp_block, loc);
7000 :
7001 34114 : Block* init;
7002 34114 : Expression* cond;
7003 34114 : Block* iter_init;
7004 34114 : Block* post;
7005 :
7006 : // Arrange to do a loop appropriate for the type. We will produce
7007 : // for INIT ; COND ; POST {
7008 : // ITER_INIT
7009 : // INDEX = INDEX_TEMP
7010 : // VALUE = VALUE_TEMP // If there is a value
7011 : // original statements
7012 : // }
7013 :
7014 34114 : if (range_type->is_slice_type())
7015 21657 : this->lower_range_slice(gogo, temp_block, body, range_object, range_temp,
7016 : index_temp, value_temp, &init, &cond, &iter_init,
7017 : &post);
7018 12457 : else if (range_type->array_type() != NULL)
7019 9710 : this->lower_range_array(gogo, temp_block, body, range_object, range_temp,
7020 : index_temp, value_temp, &init, &cond, &iter_init,
7021 : &post);
7022 2747 : else if (range_type->is_string_type())
7023 612 : this->lower_range_string(gogo, temp_block, body, range_object, range_temp,
7024 : index_temp, value_temp, &init, &cond, &iter_init,
7025 : &post);
7026 2135 : else if (range_type->map_type() != NULL)
7027 4068 : this->lower_range_map(gogo, range_type->map_type(), temp_block, body,
7028 : range_object, range_temp, index_temp, value_temp,
7029 : &init, &cond, &iter_init, &post);
7030 101 : else if (range_type->channel_type() != NULL)
7031 101 : this->lower_range_channel(gogo, temp_block, body, range_object, range_temp,
7032 : index_temp, value_temp, &init, &cond, &iter_init,
7033 : &post);
7034 : else
7035 0 : go_unreachable();
7036 :
7037 34114 : if (iter_init != NULL)
7038 23037 : body->add_statement(Statement::make_block_statement(iter_init, loc));
7039 :
7040 34114 : if (this->index_var_ != NULL)
7041 : {
7042 34024 : Statement* assign;
7043 34024 : Expression* index_ref =
7044 34024 : Expression::make_temporary_reference(index_temp, loc);
7045 34024 : if (this->value_var_ == NULL || this->value_var_->is_sink_expression())
7046 11772 : assign = Statement::make_assignment(this->index_var_, index_ref, loc);
7047 : else
7048 : {
7049 22252 : Expression_list* lhs = new Expression_list();
7050 22252 : lhs->push_back(this->index_var_);
7051 22252 : lhs->push_back(this->value_var_);
7052 :
7053 22252 : Expression_list* rhs = new Expression_list();
7054 22252 : rhs->push_back(index_ref);
7055 22252 : rhs->push_back(Expression::make_temporary_reference(value_temp, loc));
7056 :
7057 22252 : assign = Statement::make_tuple_assignment(lhs, rhs, loc);
7058 : }
7059 34024 : assign->determine_types(gogo);
7060 34024 : body->add_statement(assign);
7061 : }
7062 :
7063 34114 : body->add_statement(Statement::make_block_statement(this->statements_, loc));
7064 :
7065 34114 : body->set_end_location(this->statements_->end_location());
7066 :
7067 34114 : For_statement* loop = Statement::make_for_statement(init, cond, post,
7068 : this->location());
7069 34114 : loop->add_statements(body);
7070 34114 : loop->determine_types(gogo);
7071 34114 : loop->set_break_continue_labels(this->break_label_, this->continue_label_);
7072 :
7073 34114 : temp_block->add_statement(loop);
7074 :
7075 34114 : return Statement::make_block_statement(temp_block, loc);
7076 : }
7077 :
7078 : // Return a reference to the range, which may be in RANGE_OBJECT or in
7079 : // RANGE_TEMP.
7080 :
7081 : Expression*
7082 26352 : For_range_statement::make_range_ref(Named_object* range_object,
7083 : Temporary_statement* range_temp,
7084 : Location loc)
7085 : {
7086 26352 : if (range_object != NULL)
7087 16021 : return Expression::make_var_reference(range_object, loc);
7088 : else
7089 10331 : return Expression::make_temporary_reference(range_temp, loc);
7090 : }
7091 :
7092 : // Return a call to the predeclared function FUNCNAME passing a
7093 : // reference to the temporary variable ARG.
7094 :
7095 : Call_expression*
7096 32260 : For_range_statement::call_builtin(Gogo* gogo, const char* funcname,
7097 : Expression* arg,
7098 : Location loc)
7099 : {
7100 32260 : Named_object* no = gogo->lookup_global(funcname);
7101 32260 : go_assert(no != NULL && no->is_function_declaration());
7102 32260 : Expression* func = Expression::make_func_reference(no, NULL, loc);
7103 32260 : Expression_list* params = new Expression_list();
7104 32260 : params->push_back(arg);
7105 32260 : return Expression::make_call(func, params, false, loc);
7106 : }
7107 :
7108 : // Lower a for range over an array.
7109 :
7110 : void
7111 9710 : For_range_statement::lower_range_array(Gogo* gogo,
7112 : Block* enclosing,
7113 : Block* body_block,
7114 : Named_object* range_object,
7115 : Temporary_statement* range_temp,
7116 : Temporary_statement* index_temp,
7117 : Temporary_statement* value_temp,
7118 : Block** pinit,
7119 : Expression** pcond,
7120 : Block** piter_init,
7121 : Block** ppost)
7122 : {
7123 9710 : Location loc = this->location();
7124 :
7125 : // The loop we generate:
7126 : // len_temp := len(range)
7127 : // range_temp := range
7128 : // for index_temp = 0; index_temp < len_temp; index_temp++ {
7129 : // value_temp = range_temp[index_temp]
7130 : // index = index_temp
7131 : // value = value_temp
7132 : // original body
7133 : // }
7134 :
7135 : // Set *PINIT to
7136 : // var len_temp int
7137 : // len_temp = len(range)
7138 : // index_temp = 0
7139 :
7140 9710 : Block* init = new Block(enclosing, loc);
7141 :
7142 9710 : Expression* len_arg;
7143 9710 : if (range_object == NULL && range_temp == NULL)
7144 : {
7145 : // Don't evaluate this->range_, just get its length.
7146 9209 : len_arg = this->range_;
7147 : }
7148 : else
7149 : {
7150 501 : Expression* ref = this->make_range_ref(range_object, range_temp, loc);
7151 501 : range_temp = Statement::make_temporary(NULL, ref, loc);
7152 501 : range_temp->determine_types(gogo);
7153 501 : init->add_statement(range_temp);
7154 501 : len_arg = ref;
7155 : }
7156 9710 : Expression* len_call = this->call_builtin(gogo, "len", len_arg, loc);
7157 9710 : Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
7158 : len_call, loc);
7159 9710 : len_temp->determine_types(gogo);
7160 9710 : init->add_statement(len_temp);
7161 :
7162 9710 : Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);
7163 :
7164 9710 : Temporary_reference_expression* tref =
7165 9710 : Expression::make_temporary_reference(index_temp, loc);
7166 9710 : tref->set_is_lvalue();
7167 9710 : Statement* s = Statement::make_assignment(tref, zexpr, loc);
7168 9710 : s->determine_types(gogo);
7169 9710 : init->add_statement(s);
7170 :
7171 9710 : *pinit = init;
7172 :
7173 : // Set *PCOND to
7174 : // index_temp < len_temp
7175 :
7176 9710 : Expression* ref = Expression::make_temporary_reference(index_temp, loc);
7177 9710 : Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
7178 9710 : Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);
7179 :
7180 9710 : *pcond = lt;
7181 :
7182 : // Set *PITER_INIT to
7183 : // value_temp = range[index_temp]
7184 :
7185 9710 : Block* iter_init = NULL;
7186 9710 : if (value_temp != NULL)
7187 : {
7188 497 : iter_init = new Block(body_block, loc);
7189 :
7190 497 : ref = Expression::make_temporary_reference(range_temp, loc);
7191 497 : ref2 = Expression::make_temporary_reference(index_temp, loc);
7192 497 : Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
7193 :
7194 497 : tref = Expression::make_temporary_reference(value_temp, loc);
7195 497 : tref->set_is_lvalue();
7196 497 : s = Statement::make_assignment(tref, index, loc);
7197 497 : s->determine_types(gogo);
7198 :
7199 497 : iter_init->add_statement(s);
7200 : }
7201 9710 : *piter_init = iter_init;
7202 :
7203 : // Set *PPOST to
7204 : // index_temp++
7205 :
7206 9710 : Block* post = new Block(enclosing, loc);
7207 9710 : tref = Expression::make_temporary_reference(index_temp, loc);
7208 9710 : tref->set_is_lvalue();
7209 9710 : s = Statement::make_inc_statement(tref);
7210 9710 : s->determine_types(gogo);
7211 9710 : post->add_statement(s);
7212 9710 : *ppost = post;
7213 9710 : }
7214 :
7215 : // Lower a for range over a slice.
7216 :
7217 : void
7218 21657 : For_range_statement::lower_range_slice(Gogo* gogo,
7219 : Block* enclosing,
7220 : Block* body_block,
7221 : Named_object* range_object,
7222 : Temporary_statement* range_temp,
7223 : Temporary_statement* index_temp,
7224 : Temporary_statement* value_temp,
7225 : Block** pinit,
7226 : Expression** pcond,
7227 : Block** piter_init,
7228 : Block** ppost)
7229 : {
7230 21657 : Location loc = this->location();
7231 :
7232 : // The loop we generate:
7233 : // for_temp := range
7234 : // len_temp := len(for_temp)
7235 : // for index_temp = 0; index_temp < len_temp; index_temp++ {
7236 : // value_temp = for_temp[index_temp]
7237 : // index = index_temp
7238 : // value = value_temp
7239 : // original body
7240 : // }
7241 : //
7242 : // Using for_temp means that we don't need to check bounds when
7243 : // fetching range_temp[index_temp].
7244 :
7245 : // Set *PINIT to
7246 : // range_temp := range
7247 : // var len_temp int
7248 : // len_temp = len(range_temp)
7249 : // index_temp = 0
7250 :
7251 21657 : Block* init = new Block(enclosing, loc);
7252 :
7253 21657 : Expression* ref = this->make_range_ref(range_object, range_temp, loc);
7254 21657 : Temporary_statement* for_temp = Statement::make_temporary(NULL, ref, loc);
7255 21657 : for_temp->determine_types(gogo);
7256 21657 : init->add_statement(for_temp);
7257 :
7258 21657 : ref = Expression::make_temporary_reference(for_temp, loc);
7259 21657 : Expression* len_call = this->call_builtin(gogo, "len", ref, loc);
7260 21657 : Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
7261 : len_call, loc);
7262 21657 : len_temp->determine_types(gogo);
7263 21657 : init->add_statement(len_temp);
7264 :
7265 21657 : Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);
7266 :
7267 21657 : Temporary_reference_expression* tref =
7268 21657 : Expression::make_temporary_reference(index_temp, loc);
7269 21657 : tref->set_is_lvalue();
7270 21657 : Statement* s = Statement::make_assignment(tref, zexpr, loc);
7271 21657 : s->determine_types(gogo);
7272 21657 : init->add_statement(s);
7273 :
7274 21657 : *pinit = init;
7275 :
7276 : // Set *PCOND to
7277 : // index_temp < len_temp
7278 :
7279 21657 : ref = Expression::make_temporary_reference(index_temp, loc);
7280 21657 : Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
7281 21657 : Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);
7282 :
7283 21657 : *pcond = lt;
7284 :
7285 : // Set *PITER_INIT to
7286 : // value_temp = range[index_temp]
7287 :
7288 21657 : Block* iter_init = NULL;
7289 21657 : if (value_temp != NULL)
7290 : {
7291 19793 : iter_init = new Block(body_block, loc);
7292 :
7293 19793 : ref = Expression::make_temporary_reference(for_temp, loc);
7294 19793 : ref2 = Expression::make_temporary_reference(index_temp, loc);
7295 19793 : Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
7296 :
7297 19793 : tref = Expression::make_temporary_reference(value_temp, loc);
7298 19793 : tref->set_is_lvalue();
7299 19793 : s = Statement::make_assignment(tref, index, loc);
7300 19793 : s->determine_types(gogo);
7301 :
7302 19793 : iter_init->add_statement(s);
7303 : }
7304 21657 : *piter_init = iter_init;
7305 :
7306 : // Set *PPOST to
7307 : // index_temp++
7308 :
7309 21657 : Block* post = new Block(enclosing, loc);
7310 21657 : tref = Expression::make_temporary_reference(index_temp, loc);
7311 21657 : tref->set_is_lvalue();
7312 21657 : s = Statement::make_inc_statement(tref);
7313 21657 : s->determine_types(gogo);
7314 21657 : post->add_statement(s);
7315 21657 : *ppost = post;
7316 21657 : }
7317 :
7318 : // Lower a for range over a string.
7319 :
7320 : void
7321 612 : For_range_statement::lower_range_string(Gogo* gogo,
7322 : Block* enclosing,
7323 : Block* body_block,
7324 : Named_object* range_object,
7325 : Temporary_statement* range_temp,
7326 : Temporary_statement* index_temp,
7327 : Temporary_statement* value_temp,
7328 : Block** pinit,
7329 : Expression** pcond,
7330 : Block** piter_init,
7331 : Block** ppost)
7332 : {
7333 612 : Location loc = this->location();
7334 :
7335 : // The loop we generate:
7336 : // len_temp := len(range)
7337 : // var next_index_temp int
7338 : // for index_temp = 0; index_temp < len_temp; index_temp = next_index_temp {
7339 : // value_temp = rune(range[index_temp])
7340 : // if value_temp < utf8.RuneSelf {
7341 : // next_index_temp = index_temp + 1
7342 : // } else {
7343 : // value_temp, next_index_temp = decoderune(range, index_temp)
7344 : // }
7345 : // index = index_temp
7346 : // value = value_temp
7347 : // // original body
7348 : // }
7349 :
7350 : // Set *PINIT to
7351 : // len_temp := len(range)
7352 : // var next_index_temp int
7353 : // index_temp = 0
7354 : // var value_temp rune // if value_temp not passed in
7355 :
7356 612 : Block* init = new Block(enclosing, loc);
7357 :
7358 612 : Expression* ref = this->make_range_ref(range_object, range_temp, loc);
7359 612 : Call_expression* call = this->call_builtin(gogo, "len", ref, loc);
7360 612 : Temporary_statement* len_temp =
7361 612 : Statement::make_temporary(index_temp->type(), call, loc);
7362 612 : len_temp->determine_types(gogo);
7363 612 : init->add_statement(len_temp);
7364 :
7365 612 : Temporary_statement* next_index_temp =
7366 612 : Statement::make_temporary(index_temp->type(), NULL, loc);
7367 612 : init->add_statement(next_index_temp);
7368 :
7369 612 : Temporary_reference_expression* index_ref =
7370 612 : Expression::make_temporary_reference(index_temp, loc);
7371 612 : index_ref->set_is_lvalue();
7372 612 : Expression* zexpr = Expression::make_integer_ul(0, index_temp->type(), loc);
7373 612 : Statement* s = Statement::make_assignment(index_ref, zexpr, loc);
7374 612 : s->determine_types(gogo);
7375 612 : init->add_statement(s);
7376 :
7377 612 : Type* rune_type;
7378 612 : if (value_temp != NULL)
7379 561 : rune_type = value_temp->type();
7380 : else
7381 : {
7382 51 : rune_type = Type::lookup_integer_type("rune");
7383 51 : value_temp = Statement::make_temporary(rune_type, NULL, loc);
7384 51 : init->add_statement(value_temp);
7385 : }
7386 :
7387 612 : *pinit = init;
7388 :
7389 : // Set *PCOND to
7390 : // index_temp < len_temp
7391 :
7392 612 : index_ref = Expression::make_temporary_reference(index_temp, loc);
7393 612 : Expression* len_ref =
7394 612 : Expression::make_temporary_reference(len_temp, loc);
7395 612 : *pcond = Expression::make_binary(OPERATOR_LT, index_ref, len_ref, loc);
7396 :
7397 : // Set *PITER_INIT to
7398 : // value_temp = rune(range[index_temp])
7399 : // if value_temp < utf8.RuneSelf {
7400 : // next_index_temp = index_temp + 1
7401 : // } else {
7402 : // value_temp, next_index_temp = decoderune(range, index_temp)
7403 : // }
7404 :
7405 612 : Block* iter_init = new Block(body_block, loc);
7406 :
7407 612 : ref = this->make_range_ref(range_object, range_temp, loc);
7408 612 : index_ref = Expression::make_temporary_reference(index_temp, loc);
7409 612 : ref = Expression::make_string_index(ref, index_ref, NULL, loc);
7410 612 : ref = Expression::make_cast(rune_type, ref, loc);
7411 612 : Temporary_reference_expression* value_ref =
7412 612 : Expression::make_temporary_reference(value_temp, loc);
7413 612 : value_ref->set_is_lvalue();
7414 612 : s = Statement::make_assignment(value_ref, ref, loc);
7415 612 : s->determine_types(gogo);
7416 612 : iter_init->add_statement(s);
7417 :
7418 612 : value_ref = Expression::make_temporary_reference(value_temp, loc);
7419 612 : Expression* rune_self = Expression::make_integer_ul(0x80, rune_type, loc);
7420 612 : Expression* cond = Expression::make_binary(OPERATOR_LT, value_ref, rune_self,
7421 : loc);
7422 :
7423 612 : Block* then_block = new Block(iter_init, loc);
7424 :
7425 612 : Temporary_reference_expression* lhs =
7426 612 : Expression::make_temporary_reference(next_index_temp, loc);
7427 612 : lhs->set_is_lvalue();
7428 612 : index_ref = Expression::make_temporary_reference(index_temp, loc);
7429 612 : Expression* one = Expression::make_integer_ul(1, index_temp->type(), loc);
7430 612 : Expression* sum = Expression::make_binary(OPERATOR_PLUS, index_ref, one,
7431 : loc);
7432 612 : s = Statement::make_assignment(lhs, sum, loc);
7433 612 : s->determine_types(gogo);
7434 612 : then_block->add_statement(s);
7435 :
7436 612 : Block* else_block = new Block(iter_init, loc);
7437 :
7438 612 : ref = this->make_range_ref(range_object, range_temp, loc);
7439 612 : index_ref = Expression::make_temporary_reference(index_temp, loc);
7440 612 : call = Runtime::make_call(gogo, Runtime::DECODERUNE, loc, 2, ref, index_ref);
7441 :
7442 612 : value_ref = Expression::make_temporary_reference(value_temp, loc);
7443 612 : value_ref->set_is_lvalue();
7444 612 : Expression* res = Expression::make_call_result(call, 0);
7445 612 : s = Statement::make_assignment(value_ref, res, loc);
7446 612 : s->determine_types(gogo);
7447 612 : else_block->add_statement(s);
7448 :
7449 612 : lhs = Expression::make_temporary_reference(next_index_temp, loc);
7450 612 : lhs->set_is_lvalue();
7451 612 : res = Expression::make_call_result(call, 1);
7452 612 : s = Statement::make_assignment(lhs, res, loc);
7453 612 : s->determine_types(gogo);
7454 612 : else_block->add_statement(s);
7455 :
7456 612 : s = Statement::make_if_statement(cond, then_block, else_block, loc);
7457 612 : s->determine_types(gogo);
7458 612 : iter_init->add_statement(s);
7459 :
7460 612 : *piter_init = iter_init;
7461 :
7462 : // Set *PPOST to
7463 : // index_temp = next_index_temp
7464 :
7465 612 : Block* post = new Block(enclosing, loc);
7466 :
7467 612 : index_ref = Expression::make_temporary_reference(index_temp, loc);
7468 612 : index_ref->set_is_lvalue();
7469 612 : ref = Expression::make_temporary_reference(next_index_temp, loc);
7470 612 : s = Statement::make_assignment(index_ref, ref, loc);
7471 612 : s->determine_types(gogo);
7472 :
7473 612 : post->add_statement(s);
7474 612 : *ppost = post;
7475 612 : }
7476 :
7477 : // Lower a for range over a map.
7478 :
7479 : void
7480 2034 : For_range_statement::lower_range_map(Gogo* gogo,
7481 : Map_type* map_type,
7482 : Block* enclosing,
7483 : Block* body_block,
7484 : Named_object* range_object,
7485 : Temporary_statement* range_temp,
7486 : Temporary_statement* index_temp,
7487 : Temporary_statement* value_temp,
7488 : Block** pinit,
7489 : Expression** pcond,
7490 : Block** piter_init,
7491 : Block** ppost)
7492 : {
7493 2034 : Location loc = this->location();
7494 :
7495 : // The runtime uses a struct to handle ranges over a map. The
7496 : // struct is built by Map_type::hiter_type for a specific map type.
7497 :
7498 : // The loop we generate:
7499 : // var hiter map_iteration_struct
7500 : // for mapiterinit(type, range, &hiter); hiter.key != nil; mapiternext(&hiter) {
7501 : // index_temp = *hiter.key
7502 : // value_temp = *hiter.val
7503 : // index = index_temp
7504 : // value = value_temp
7505 : // original body
7506 : // }
7507 :
7508 : // Set *PINIT to
7509 : // var hiter map_iteration_struct
7510 : // runtime.mapiterinit(type, range, &hiter)
7511 :
7512 2034 : Block* init = new Block(enclosing, loc);
7513 :
7514 2034 : Type* map_iteration_type = map_type->hiter_type(gogo);
7515 2034 : Temporary_statement* hiter = Statement::make_temporary(map_iteration_type,
7516 : NULL, loc);
7517 2034 : init->add_statement(hiter);
7518 :
7519 2034 : Expression* p1 = Expression::make_type_descriptor(map_type, loc);
7520 2034 : Expression* p2 = this->make_range_ref(range_object, range_temp, loc);
7521 2034 : Expression* ref = Expression::make_temporary_reference(hiter, loc);
7522 2034 : Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
7523 2034 : Expression* call = Runtime::make_call(gogo, Runtime::MAPITERINIT, loc, 3,
7524 : p1, p2, p3);
7525 2034 : Statement* s = Statement::make_statement(call, true);
7526 2034 : s->determine_types(gogo);
7527 2034 : init->add_statement(s);
7528 :
7529 2034 : *pinit = init;
7530 :
7531 : // Set *PCOND to
7532 : // hiter.key != nil
7533 :
7534 2034 : ref = Expression::make_temporary_reference(hiter, loc);
7535 2034 : ref = Expression::make_field_reference(ref, 0, loc);
7536 2034 : Expression* ne = Expression::make_binary(OPERATOR_NOTEQ, ref,
7537 : Expression::make_nil(loc),
7538 : loc);
7539 2034 : *pcond = ne;
7540 :
7541 : // Set *PITER_INIT to
7542 : // index_temp = *hiter.key
7543 : // value_temp = *hiter.val
7544 :
7545 2034 : Block* iter_init = new Block(body_block, loc);
7546 :
7547 2034 : Expression* lhs = Expression::make_temporary_reference(index_temp, loc);
7548 2034 : Expression* rhs = Expression::make_temporary_reference(hiter, loc);
7549 2034 : rhs = Expression::make_field_reference(ref, 0, loc);
7550 2034 : rhs = Expression::make_dereference(ref, Expression::NIL_CHECK_NOT_NEEDED,
7551 : loc);
7552 2034 : Statement* set = Statement::make_assignment(lhs, rhs, loc);
7553 2034 : set->determine_types(gogo);
7554 2034 : iter_init->add_statement(set);
7555 :
7556 2034 : if (value_temp != NULL)
7557 : {
7558 1401 : lhs = Expression::make_temporary_reference(value_temp, loc);
7559 1401 : rhs = Expression::make_temporary_reference(hiter, loc);
7560 1401 : rhs = Expression::make_field_reference(rhs, 1, loc);
7561 1401 : rhs = Expression::make_dereference(rhs, Expression::NIL_CHECK_NOT_NEEDED,
7562 : loc);
7563 1401 : set = Statement::make_assignment(lhs, rhs, loc);
7564 1401 : set->determine_types(gogo);
7565 1401 : iter_init->add_statement(set);
7566 : }
7567 :
7568 2034 : *piter_init = iter_init;
7569 :
7570 : // Set *PPOST to
7571 : // mapiternext(&hiter)
7572 :
7573 2034 : Block* post = new Block(enclosing, loc);
7574 :
7575 2034 : ref = Expression::make_temporary_reference(hiter, loc);
7576 2034 : p1 = Expression::make_unary(OPERATOR_AND, ref, loc);
7577 2034 : call = Runtime::make_call(gogo, Runtime::MAPITERNEXT, loc, 1, p1);
7578 2034 : s = Statement::make_statement(call, true);
7579 2034 : s->determine_types(gogo);
7580 2034 : post->add_statement(s);
7581 :
7582 2034 : *ppost = post;
7583 2034 : }
7584 :
7585 : // Lower a for range over a channel.
7586 :
7587 : void
7588 101 : For_range_statement::lower_range_channel(Gogo* gogo,
7589 : Block*,
7590 : Block* body_block,
7591 : Named_object* range_object,
7592 : Temporary_statement* range_temp,
7593 : Temporary_statement* index_temp,
7594 : Temporary_statement* value_temp,
7595 : Block** pinit,
7596 : Expression** pcond,
7597 : Block** piter_init,
7598 : Block** ppost)
7599 : {
7600 101 : go_assert(value_temp == NULL);
7601 :
7602 101 : Location loc = this->location();
7603 :
7604 : // The loop we generate:
7605 : // for {
7606 : // index_temp, ok_temp = <-range
7607 : // if !ok_temp {
7608 : // break
7609 : // }
7610 : // index = index_temp
7611 : // original body
7612 : // }
7613 :
7614 : // We have no initialization code, no condition, and no post code.
7615 :
7616 101 : *pinit = NULL;
7617 101 : *pcond = NULL;
7618 101 : *ppost = NULL;
7619 :
7620 : // Set *PITER_INIT to
7621 : // index_temp, ok_temp = <-range
7622 : // if !ok_temp {
7623 : // break
7624 : // }
7625 :
7626 101 : Block* iter_init = new Block(body_block, loc);
7627 :
7628 101 : Temporary_statement* ok_temp =
7629 101 : Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
7630 101 : iter_init->add_statement(ok_temp);
7631 :
7632 101 : Expression* cref = this->make_range_ref(range_object, range_temp, loc);
7633 101 : Temporary_reference_expression* iref =
7634 101 : Expression::make_temporary_reference(index_temp, loc);
7635 101 : iref->set_is_lvalue();
7636 101 : Temporary_reference_expression* oref =
7637 101 : Expression::make_temporary_reference(ok_temp, loc);
7638 101 : oref->set_is_lvalue();
7639 101 : Statement* s = Statement::make_tuple_receive_assignment(iref, oref, cref,
7640 : loc);
7641 101 : s->determine_types(gogo);
7642 101 : iter_init->add_statement(s);
7643 :
7644 101 : Block* then_block = new Block(iter_init, loc);
7645 101 : s = Statement::make_break_statement(this->break_label(), loc);
7646 101 : then_block->add_statement(s);
7647 :
7648 101 : oref = Expression::make_temporary_reference(ok_temp, loc);
7649 101 : Expression* cond = Expression::make_unary(OPERATOR_NOT, oref, loc);
7650 101 : s = Statement::make_if_statement(cond, then_block, NULL, loc);
7651 101 : s->determine_types(gogo);
7652 101 : iter_init->add_statement(s);
7653 :
7654 101 : *piter_init = iter_init;
7655 101 : }
7656 :
7657 : // Match
7658 : //
7659 : // for k := range m { delete(m, k) }
7660 : //
7661 : // Lower it to runtime.mapclear(TYPE, m) on match, return the statement
7662 : // containing the call. Return NULL otherwise.
7663 :
7664 : Statement*
7665 2067 : For_range_statement::lower_map_range_clear(Gogo* gogo,
7666 : Type* map_type,
7667 : Block* enclosing,
7668 : Expression* orig_range_expr,
7669 : Named_object* range_object,
7670 : Temporary_statement* range_temp,
7671 : Location loc)
7672 : {
7673 2067 : if (this->value_var_ != NULL)
7674 : return NULL;
7675 645 : if (this->index_var_ == NULL)
7676 : return NULL;
7677 :
7678 : // Require the loop index be a new variable. We cannot rewrite
7679 : // if it is used outside of the loop.
7680 2664 : Var_expression* index_ve = this->index_var_->var_expression();
7681 630 : if (index_ve == NULL)
7682 : return NULL;
7683 630 : Named_object* index_no = index_ve->named_object();
7684 630 : if (enclosing->bindings()->lookup_local(index_no->name()) != index_no)
7685 : return NULL;
7686 :
7687 : // Match the body, a single call statement delete(m, k).
7688 629 : const std::vector<Statement*>* statements = this->statements_->statements();
7689 629 : if (statements->size() != 1)
7690 : return NULL;
7691 2123 : Expression_statement* es = statements->at(0)->expression_statement();
7692 89 : if (es == NULL)
7693 : return NULL;
7694 89 : Call_expression* call = es->expr()->call_expression();
7695 89 : if (call == NULL || !call->is_builtin()
7696 40 : || call->builtin_call_expression()->code()
7697 : != Builtin_call_expression::BUILTIN_DELETE)
7698 49 : return NULL;
7699 40 : if (!Expression::is_same_variable(call->args()->at(0), orig_range_expr)
7700 40 : || !Expression::is_same_variable(call->args()->at(1), this->index_var_))
7701 7 : return NULL;
7702 :
7703 : // Everything matches. Rewrite to mapclear(TYPE, MAP).
7704 33 : Expression* e1 = Expression::make_type_descriptor(map_type, loc);
7705 33 : Expression* e2 = this->make_range_ref(range_object, range_temp, loc);
7706 33 : call = Runtime::make_call(gogo, Runtime::MAPCLEAR, loc, 2, e1, e2);
7707 33 : Statement* s = Statement::make_statement(call, true);
7708 33 : s->determine_types(gogo);
7709 33 : return s;
7710 : }
7711 :
7712 : // Match
7713 : //
7714 : // for i := range a { a[i] = zero }
7715 : //
7716 : // Lower it to call memclr on match, and return the statement. Return
7717 : // NULL otherwise.
7718 :
7719 : Statement*
7720 31648 : For_range_statement::lower_array_range_clear(Gogo* gogo,
7721 : Type* array_type,
7722 : Expression* orig_range_expr,
7723 : Block* temp_block,
7724 : Named_object* range_object,
7725 : Temporary_statement* range_temp,
7726 : Location loc)
7727 : {
7728 31648 : if (this->value_var_ != NULL)
7729 : return NULL;
7730 11354 : if (this->index_var_ == NULL)
7731 : return NULL;
7732 :
7733 : // Match the body, a single assignment statement a[i] = zero.
7734 11330 : const std::vector<Statement*>* statements = this->statements_->statements();
7735 11330 : if (statements->size() != 1)
7736 : return NULL;
7737 7844 : Assignment_statement* as = statements->at(0)->assignment_statement();
7738 1190 : if (as == NULL || !as->rhs()->is_zero_value())
7739 7461 : return NULL;
7740 385 : if (as->lhs()->type()->interface_type() != NULL
7741 4 : && as->rhs()->type()->interface_type() == NULL
7742 2 : && !as->rhs()->type()->is_nil_type())
7743 : // Implicit type conversion may change a zero value to non-zero, like
7744 : // interface{}(0).
7745 : return NULL;
7746 381 : Array_index_expression* aie = as->lhs()->array_index_expression();
7747 373 : if (aie == NULL || aie->end() != NULL
7748 373 : || !Expression::is_same_variable(orig_range_expr, aie->array())
7749 282 : || !Expression::is_same_variable(this->index_var_, aie->start()))
7750 100 : return NULL;
7751 :
7752 : // Everything matches. Rewrite to
7753 : //
7754 : // if len(a) != 0 {
7755 : // tmp1 = &a[0]
7756 : // tmp2 = len(a)*sizeof(elem(a))
7757 : // memclr{NoHeap,Has}Pointers(tmp1, tmp2)
7758 : // i = len(a) - 1
7759 : // }
7760 :
7761 562 : Type* elem_type = array_type->array_type()->element_type();
7762 281 : int64_t elme_sz;
7763 281 : bool ok = elem_type->backend_type_size(gogo, &elme_sz);
7764 281 : if (!ok)
7765 : return NULL;
7766 :
7767 281 : Block* b = new Block(temp_block, loc);
7768 :
7769 281 : Expression* ref;
7770 281 : if (range_object == NULL && range_temp == NULL)
7771 : // is_same_variable implies no side effect, so it is ok to copy.
7772 91 : ref = orig_range_expr->copy();
7773 : else
7774 190 : ref = this->make_range_ref(range_object, range_temp, loc);
7775 281 : Expression* len = this->call_builtin(gogo, "len", ref, loc);
7776 281 : Temporary_statement* tslen = Statement::make_temporary(NULL, len, loc);
7777 281 : tslen->determine_types(gogo);
7778 281 : temp_block->add_statement(tslen);
7779 :
7780 281 : Expression* zero = Expression::make_integer_ul(0, this->index_var_->type(), loc);
7781 281 : ref = ref->copy();
7782 281 : Expression* elem = Expression::make_array_index(ref, zero, NULL, NULL, loc);
7783 281 : elem->array_index_expression()->set_needs_bounds_check(false);
7784 281 : Expression* e1 = Expression::make_unary(OPERATOR_AND, elem, loc);
7785 281 : Temporary_statement* ts1 = Statement::make_temporary(NULL, e1, loc);
7786 281 : ts1->determine_types(gogo);
7787 281 : b->add_statement(ts1);
7788 :
7789 281 : len = Expression::make_temporary_reference(tslen, loc);
7790 281 : Expression* sz = Expression::make_integer_int64(elme_sz, len->type(), loc);
7791 281 : Expression* e2 = Expression::make_binary(OPERATOR_MULT, len, sz, loc);
7792 281 : Temporary_statement* ts2 = Statement::make_temporary(NULL, e2, loc);
7793 281 : ts2->determine_types(gogo);
7794 281 : b->add_statement(ts2);
7795 :
7796 281 : Expression* ptr_arg = Expression::make_temporary_reference(ts1, loc);
7797 281 : Expression* sz_arg = Expression::make_temporary_reference(ts2, loc);
7798 281 : Expression* call;
7799 281 : if (elem_type->has_pointer())
7800 30 : call = Runtime::make_call(gogo, Runtime::MEMCLRHASPTR, loc, 2,
7801 : ptr_arg, sz_arg);
7802 : else
7803 : {
7804 251 : Type* int32_type = Type::lookup_integer_type("int32");
7805 251 : Expression* zero32 = Expression::make_integer_ul(0, int32_type, loc);
7806 251 : call = Runtime::make_call(gogo, Runtime::BUILTIN_MEMSET, loc, 3, ptr_arg,
7807 : zero32, sz_arg);
7808 : }
7809 281 : Statement* cs3 = Statement::make_statement(call, true);
7810 281 : cs3->determine_types(gogo);
7811 281 : b->add_statement(cs3);
7812 :
7813 281 : len = Expression::make_temporary_reference(tslen, loc);
7814 281 : Expression* one = Expression::make_integer_ul(1, len->type(), loc);
7815 281 : Expression* rhs = Expression::make_binary(OPERATOR_MINUS, len, one, loc);
7816 281 : Expression* lhs = this->index_var_->copy();
7817 281 : Statement* as4 = Statement::make_assignment(lhs, rhs, loc);
7818 281 : as4->determine_types(gogo);
7819 281 : b->add_statement(as4);
7820 :
7821 281 : len = Expression::make_temporary_reference(tslen, loc);
7822 281 : zero = zero->copy();
7823 281 : Expression* cond = Expression::make_binary(OPERATOR_NOTEQ, len, zero, loc);
7824 281 : Statement* ret = Statement::make_if_statement(cond, b, NULL, loc);
7825 281 : ret->determine_types(gogo);
7826 281 : return ret;
7827 : }
7828 :
7829 : // Return the break LABEL_EXPR.
7830 :
7831 : Unnamed_label*
7832 1527 : For_range_statement::break_label()
7833 : {
7834 1527 : if (this->break_label_ == NULL)
7835 1414 : this->break_label_ = new Unnamed_label(this->location());
7836 1527 : return this->break_label_;
7837 : }
7838 :
7839 : // Return the continue LABEL_EXPR.
7840 :
7841 : Unnamed_label*
7842 5908 : For_range_statement::continue_label()
7843 : {
7844 5908 : if (this->continue_label_ == NULL)
7845 3563 : this->continue_label_ = new Unnamed_label(this->location());
7846 5908 : return this->continue_label_;
7847 : }
7848 :
7849 : // Dump the AST representation for a for range statement.
7850 :
7851 : void
7852 0 : For_range_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
7853 : {
7854 :
7855 0 : ast_dump_context->print_indent();
7856 0 : ast_dump_context->ostream() << "for ";
7857 0 : ast_dump_context->dump_expression(this->index_var_);
7858 0 : if (this->value_var_ != NULL)
7859 : {
7860 0 : ast_dump_context->ostream() << ", ";
7861 0 : ast_dump_context->dump_expression(this->value_var_);
7862 : }
7863 :
7864 0 : ast_dump_context->ostream() << " = range ";
7865 0 : ast_dump_context->dump_expression(this->range_);
7866 0 : if (ast_dump_context->dump_subblocks())
7867 : {
7868 0 : ast_dump_context->ostream() << " {" << std::endl;
7869 :
7870 0 : ast_dump_context->indent();
7871 :
7872 0 : ast_dump_context->dump_block(this->statements_);
7873 :
7874 0 : ast_dump_context->unindent();
7875 0 : ast_dump_context->print_indent();
7876 0 : ast_dump_context->ostream() << "}";
7877 : }
7878 0 : ast_dump_context->ostream() << dsuffix(location()) << std::endl;
7879 0 : }
7880 :
7881 : // Make a for statement with a range clause.
7882 :
7883 : For_range_statement*
7884 34430 : Statement::make_for_range_statement(Expression* index_var,
7885 : Expression* value_var,
7886 : Expression* range,
7887 : Location location)
7888 : {
7889 34430 : return new For_range_statement(index_var, value_var, range, location);
7890 : }
|