github.com/golang/gofrontend@v0.0.0-20240429183944-60f985a78526/go/statements.cc (about) 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 Statement::Statement(Statement_classification classification, 24 Location location) 25 : classification_(classification), location_(location) 26 { 27 } 28 29 Statement::~Statement() 30 { 31 } 32 33 // Traverse the tree. The work of walking the components is handled 34 // by the subclasses. 35 36 int 37 Statement::traverse(Block* block, size_t* pindex, Traverse* traverse) 38 { 39 if (this->classification_ == STATEMENT_ERROR) 40 return TRAVERSE_CONTINUE; 41 42 unsigned int traverse_mask = traverse->traverse_mask(); 43 44 if ((traverse_mask & Traverse::traverse_statements) != 0) 45 { 46 int t = traverse->statement(block, pindex, this); 47 if (t == TRAVERSE_EXIT) 48 return TRAVERSE_EXIT; 49 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 return this->do_traverse(traverse); 57 } 58 59 // Traverse the contents of a statement. 60 61 int 62 Statement::traverse_contents(Traverse* traverse) 63 { 64 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 Statement::traverse_expression(Traverse* traverse, Expression** expr) 72 { 73 if ((traverse->traverse_mask() 74 & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0) 75 return TRAVERSE_CONTINUE; 76 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 Statement::traverse_expression_list(Traverse* traverse, 84 Expression_list* expr_list) 85 { 86 if (expr_list == NULL) 87 return TRAVERSE_CONTINUE; 88 if ((traverse->traverse_mask() 89 & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0) 90 return TRAVERSE_CONTINUE; 91 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 Statement::traverse_type(Traverse* traverse, Type* type) 99 { 100 if ((traverse->traverse_mask() 101 & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0) 102 return TRAVERSE_CONTINUE; 103 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 Statement::determine_types(Gogo* gogo) 111 { 112 this->do_determine_types(gogo); 113 } 114 115 // Read a statement from export data. 116 117 Statement* 118 Statement::import_statement(Import_function_body* ifb, Location loc) 119 { 120 if (ifb->match_c_string("{")) 121 { 122 bool is_lowered_for_statement; 123 Block* block = Block_statement::do_import(ifb, loc, 124 &is_lowered_for_statement); 125 if (block == NULL) 126 return Statement::make_error_statement(loc); 127 Block_statement* s = Statement::make_block_statement(block, loc); 128 if (is_lowered_for_statement) 129 s->set_is_lowered_for_statement(); 130 return s; 131 } 132 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 ifb->advance(6); 137 return Statement::make_return_statement(ifb->function(), NULL, loc); 138 } 139 else if (ifb->match_c_string("var $t")) 140 return Temporary_statement::do_import(ifb, loc); 141 else if (ifb->match_c_string("var ")) 142 return Variable_declaration_statement::do_import(ifb, loc); 143 else if (ifb->match_c_string("if ")) 144 return If_statement::do_import(ifb, loc); 145 else if (ifb->match_c_string(":")) 146 return Label_statement::do_import(ifb, loc); 147 else if (ifb->match_c_string("goto ")) 148 return Goto_statement::do_import(ifb, loc); 149 150 Expression* lhs = Expression::import_expression(ifb, loc); 151 152 if (ifb->match_c_string(" //")) 153 return Statement::make_statement(lhs, true); 154 155 ifb->require_c_string(" = "); 156 Expression* rhs = Expression::import_expression(ifb, loc); 157 return Statement::make_assignment(lhs, rhs, loc); 158 } 159 160 // If this is a thunk statement, return it. 161 162 Thunk_statement* 163 Statement::thunk_statement() 164 { 165 Thunk_statement* ret = this->convert<Thunk_statement, STATEMENT_GO>(); 166 if (ret == NULL) 167 ret = this->convert<Thunk_statement, STATEMENT_DEFER>(); 168 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 Statement::get_backend(Translate_context* context) 176 { 177 if (this->classification_ == STATEMENT_ERROR) 178 return context->backend()->error_statement(); 179 return this->do_get_backend(context); 180 } 181 182 // Dump AST representation for a statement to a dump context. 183 184 void 185 Statement::dump_statement(Ast_dump_context* ast_dump_context) const 186 { 187 this->do_dump_statement(ast_dump_context); 188 } 189 190 // Note that this statement is erroneous. This is called by children 191 // when they discover an error. 192 193 void 194 Statement::set_is_error() 195 { 196 this->classification_ = STATEMENT_ERROR; 197 } 198 199 // For children to call to report an error conveniently. 200 201 void 202 Statement::report_error(const char* msg) 203 { 204 go_error_at(this->location_, "%s", msg); 205 this->set_is_error(); 206 } 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 Error_statement(Location location) 215 : Statement(STATEMENT_ERROR, location) 216 { } 217 218 protected: 219 int 220 do_traverse(Traverse*) 221 { return TRAVERSE_CONTINUE; } 222 223 Bstatement* 224 do_get_backend(Translate_context*) 225 { 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 dsuffix(Location location) 237 { 238 std::string lstr = Linemap::location_to_string(location); 239 if (lstr == "") 240 return lstr; 241 std::string rval(" // "); 242 rval += lstr; 243 return rval; 244 } 245 246 // Dump the AST representation for an error statement. 247 248 void 249 Error_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 250 { 251 ast_dump_context->print_indent(); 252 ast_dump_context->ostream() << "Error statement" << std::endl; 253 } 254 255 // Make an error statement. 256 257 Statement* 258 Statement::make_error_statement(Location location) 259 { 260 return new Error_statement(location); 261 } 262 263 // Class Variable_declaration_statement. 264 265 Variable_declaration_statement::Variable_declaration_statement( 266 Named_object* var) 267 : Statement(STATEMENT_VARIABLE_DECLARATION, var->var_value()->location()), 268 var_(var) 269 { 270 } 271 272 // We don't actually traverse the variable here; it was traversed 273 // while traversing the Block. 274 275 int 276 Variable_declaration_statement::do_traverse(Traverse*) 277 { 278 return TRAVERSE_CONTINUE; 279 } 280 281 void 282 Variable_declaration_statement::do_determine_types(Gogo* gogo) 283 { 284 this->var_->var_value()->determine_type(gogo); 285 } 286 287 // Lower the variable's initialization expression. 288 289 Statement* 290 Variable_declaration_statement::do_lower(Gogo* gogo, Named_object* function, 291 Block*, Statement_inserter* inserter) 292 { 293 this->var_->var_value()->lower_init_expression(gogo, function, inserter); 294 return this; 295 } 296 297 // Flatten the variable's initialization expression. 298 299 Statement* 300 Variable_declaration_statement::do_flatten(Gogo* gogo, Named_object* function, 301 Block*, Statement_inserter* inserter) 302 { 303 Variable* var = this->var_->var_value(); 304 if (var->type()->is_error_type() 305 || (var->init() != NULL 306 && var->init()->is_error_expression())) 307 { 308 go_assert(saw_errors()); 309 return Statement::make_error_statement(this->location()); 310 } 311 this->var_->var_value()->flatten_init_expression(gogo, function, inserter); 312 return this; 313 } 314 315 // Add explicit type conversions. 316 317 void 318 Variable_declaration_statement::do_add_conversions() 319 { 320 Variable* var = this->var_->var_value(); 321 Expression* init = var->init(); 322 if (init == NULL) 323 return; 324 Type* lt = var->type(); 325 Type* rt = init->type(); 326 if (!Type::are_identical(lt, rt, 0, NULL) 327 && lt->interface_type() != NULL) 328 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 Variable_declaration_statement::do_get_backend(Translate_context* context) 335 { 336 if (this->var_->is_redefinition()) 337 return context->backend()->error_statement(); 338 Bfunction* bfunction = context->function()->func_value()->get_decl(); 339 Variable* var = this->var_->var_value(); 340 Bvariable* bvar = this->var_->get_backend_variable(context->gogo(), 341 context->function()); 342 Bexpression* binit = var->get_init(context->gogo(), context->function()); 343 344 if (!var->is_in_heap()) 345 { 346 go_assert(binit != NULL); 347 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 Location loc = this->location(); 354 Named_object* newfn = context->gogo()->lookup_global("new"); 355 go_assert(newfn != NULL && newfn->is_function_declaration()); 356 Expression* func = Expression::make_func_reference(newfn, NULL, loc); 357 Expression_list* params = new Expression_list(); 358 params->push_back(Expression::make_type(var->type(), loc)); 359 Expression* call = Expression::make_call(func, params, false, loc); 360 context->gogo()->lower_expression(context->function(), NULL, &call); 361 Temporary_statement* temp = Statement::make_temporary(NULL, call, loc); 362 Bstatement* btemp = temp->get_backend(context); 363 364 Bstatement* set = NULL; 365 if (binit != NULL) 366 { 367 Expression* e = Expression::make_temporary_reference(temp, loc); 368 e = Expression::make_dereference(e, Expression::NIL_CHECK_NOT_NEEDED, 369 loc); 370 Bexpression* be = e->get_backend(context); 371 set = context->backend()->assignment_statement(bfunction, be, binit, loc); 372 } 373 374 Expression* ref = Expression::make_temporary_reference(temp, loc); 375 Bexpression* bref = ref->get_backend(context); 376 Bstatement* sinit = context->backend()->init_statement(bfunction, bvar, bref); 377 378 std::vector<Bstatement*> stats; 379 stats.reserve(3); 380 stats.push_back(btemp); 381 if (set != NULL) 382 stats.push_back(set); 383 stats.push_back(sinit); 384 return context->backend()->statement_list(stats); 385 } 386 387 // Dump the AST representation for a variable declaration. 388 389 void 390 Variable_declaration_statement::do_dump_statement( 391 Ast_dump_context* ast_dump_context) const 392 { 393 ast_dump_context->print_indent(); 394 395 go_assert(var_->is_variable()); 396 ast_dump_context->ostream() << "var " << this->var_->name() << " "; 397 Variable* var = this->var_->var_value(); 398 if (var->has_type()) 399 { 400 ast_dump_context->dump_type(var->type()); 401 ast_dump_context->ostream() << " "; 402 } 403 if (var->init() != NULL) 404 { 405 ast_dump_context->ostream() << "= "; 406 ast_dump_context->dump_expression(var->init()); 407 } 408 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 409 } 410 411 // Make a variable declaration. 412 413 Statement* 414 Statement::make_variable_declaration(Named_object* var) 415 { 416 return new Variable_declaration_statement(var); 417 } 418 419 // Export a variable declaration. 420 421 void 422 Variable_declaration_statement::do_export_statement(Export_function_body* efb) 423 { 424 efb->write_c_string("var "); 425 efb->write_string(Gogo::unpack_hidden_name(this->var_->name())); 426 efb->write_c_string(" "); 427 Variable* var = this->var_->var_value(); 428 Type* type = var->type(); 429 efb->write_type(type); 430 Expression* init = var->init(); 431 if (init != NULL) 432 { 433 efb->write_c_string(" = "); 434 435 go_assert(efb->type_context() == NULL); 436 efb->set_type_context(type); 437 438 init->export_expression(efb); 439 440 efb->set_type_context(NULL); 441 } 442 } 443 444 // Import a variable declaration. 445 446 Statement* 447 Variable_declaration_statement::do_import(Import_function_body* ifb, 448 Location loc) 449 { 450 ifb->require_c_string("var "); 451 std::string id = ifb->read_identifier(); 452 ifb->require_c_string(" "); 453 Type* type = ifb->read_type(); 454 Expression* init = NULL; 455 if (ifb->match_c_string(" = ")) 456 { 457 ifb->advance(3); 458 init = Expression::import_expression(ifb, loc); 459 } 460 Variable* var = new Variable(type, init, false, false, false, loc); 461 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 Named_object* no = ifb->block()->bindings()->add_variable(id, NULL, var); 465 return Statement::make_variable_declaration(no); 466 } 467 468 // Class Temporary_statement. 469 470 // Return the type of the temporary variable. 471 472 Type* 473 Temporary_statement::type() const 474 { 475 Type* type = this->type_ != NULL ? this->type_ : this->init_->type(); 476 477 // Temporary variables cannot have a void type. 478 if (type->is_void_type()) 479 { 480 go_assert(saw_errors()); 481 return Type::make_error_type(); 482 } 483 return type; 484 } 485 486 // Traversal. 487 488 int 489 Temporary_statement::do_traverse(Traverse* traverse) 490 { 491 if (this->type_ != NULL 492 && this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT) 493 return TRAVERSE_EXIT; 494 if (this->init_ == NULL) 495 return TRAVERSE_CONTINUE; 496 else 497 return this->traverse_expression(traverse, &this->init_); 498 } 499 500 // Determine types. 501 502 void 503 Temporary_statement::do_determine_types(Gogo* gogo) 504 { 505 if (this->type_ != NULL && this->type_->is_abstract()) 506 this->type_ = this->type_->make_non_abstract_type(); 507 508 if (this->init_ != NULL) 509 { 510 if (this->type_ == NULL) 511 this->init_->determine_type_no_context(gogo); 512 else 513 { 514 Type_context context(this->type_, false); 515 this->init_->determine_type(gogo, &context); 516 } 517 } 518 519 if (this->type_ == NULL) 520 { 521 this->type_ = this->init_->type(); 522 go_assert(!this->type_->is_abstract()); 523 } 524 } 525 526 // Check types. 527 528 void 529 Temporary_statement::do_check_types(Gogo*) 530 { 531 if (this->type_ != NULL && this->init_ != NULL) 532 { 533 std::string reason; 534 if (!Type::are_assignable(this->type_, this->init_->type(), &reason)) 535 { 536 if (reason.empty()) 537 go_error_at(this->location(), "incompatible types in assignment"); 538 else 539 go_error_at(this->location(), "incompatible types in assignment (%s)", 540 reason.c_str()); 541 this->set_is_error(); 542 } 543 } 544 } 545 546 // Flatten a temporary statement: add another temporary when it might 547 // be needed for interface conversion. 548 549 Statement* 550 Temporary_statement::do_flatten(Gogo*, Named_object*, Block*, 551 Statement_inserter* inserter) 552 { 553 if (this->type()->is_error_type() 554 || (this->init_ != NULL 555 && this->init_->is_error_expression())) 556 { 557 go_assert(saw_errors()); 558 return Statement::make_error_statement(this->location()); 559 } 560 561 if (this->type_ != NULL 562 && this->init_ != NULL 563 && !Type::are_identical(this->type_, this->init_->type(), 564 Type::COMPARE_ERRORS | Type::COMPARE_TAGS, 565 NULL) 566 && this->init_->type()->interface_type() != NULL 567 && !this->init_->is_multi_eval_safe()) 568 { 569 Temporary_statement *temp = 570 Statement::make_temporary(NULL, this->init_, this->location()); 571 inserter->insert(temp); 572 this->init_ = Expression::make_temporary_reference(temp, 573 this->location()); 574 } 575 return this; 576 } 577 578 // Add explicit type conversions. 579 580 void 581 Temporary_statement::do_add_conversions() 582 { 583 if (this->init_ == NULL) 584 return; 585 Type* lt = this->type(); 586 Type* rt = this->init_->type(); 587 if (!Type::are_identical(lt, rt, 0, NULL) 588 && lt->interface_type() != NULL) 589 this->init_ = Expression::make_cast(lt, this->init_, this->location()); 590 } 591 592 // Convert to backend representation. 593 594 Bstatement* 595 Temporary_statement::do_get_backend(Translate_context* context) 596 { 597 go_assert(this->bvariable_ == NULL); 598 599 Named_object* function = context->function(); 600 go_assert(function != NULL); 601 Bfunction* bfunction = function->func_value()->get_decl(); 602 Btype* btype = this->type()->get_backend(context->gogo()); 603 604 Bexpression* binit; 605 if (this->init_ == NULL) 606 binit = NULL; 607 else if (this->type_ == NULL) 608 binit = this->init_->get_backend(context); 609 else 610 { 611 Expression* init = Expression::convert_for_assignment(context->gogo(), 612 this->type_, 613 this->init_, 614 this->location()); 615 binit = init->get_backend(context); 616 } 617 618 if (binit != NULL) 619 binit = context->backend()->convert_expression(btype, binit, 620 this->location()); 621 622 unsigned int flags = 0; 623 if (this->is_address_taken_) 624 flags |= Backend::variable_address_is_taken; 625 Bstatement* statement; 626 this->bvariable_ = 627 context->backend()->temporary_variable(bfunction, context->bblock(), 628 btype, binit, flags, 629 this->location(), &statement); 630 return statement; 631 } 632 633 // Return the backend variable. 634 635 Bvariable* 636 Temporary_statement::get_backend_variable(Translate_context* context) const 637 { 638 if (this->bvariable_ == NULL) 639 { 640 go_assert(saw_errors()); 641 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 Temporary_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 650 { 651 ast_dump_context->print_indent(); 652 ast_dump_context->dump_temp_variable_name(this); 653 if (this->type_ != NULL) 654 { 655 ast_dump_context->ostream() << " "; 656 ast_dump_context->dump_type(this->type_); 657 } 658 if (this->init_ != NULL) 659 { 660 ast_dump_context->ostream() << " = "; 661 ast_dump_context->dump_expression(this->init_); 662 } 663 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 664 } 665 666 // Make and initialize a temporary variable in BLOCK. 667 668 Temporary_statement* 669 Statement::make_temporary(Type* type, Expression* init, 670 Location location) 671 { 672 return new Temporary_statement(type, init, location); 673 } 674 675 // Export a temporary statement. 676 677 void 678 Temporary_statement::do_export_statement(Export_function_body* efb) 679 { 680 unsigned int idx = efb->record_temporary(this); 681 char buf[100]; 682 snprintf(buf, sizeof buf, "var $t%u", idx); 683 efb->write_c_string(buf); 684 if (this->type_ != NULL) 685 { 686 efb->write_c_string(" "); 687 efb->write_type(this->type_); 688 } 689 if (this->init_ != NULL) 690 { 691 efb->write_c_string(" = "); 692 693 go_assert(efb->type_context() == NULL); 694 efb->set_type_context(this->type_); 695 696 this->init_->export_expression(efb); 697 698 efb->set_type_context(NULL); 699 } 700 } 701 702 // Import a temporary statement. 703 704 Statement* 705 Temporary_statement::do_import(Import_function_body* ifb, Location loc) 706 { 707 ifb->require_c_string("var "); 708 std::string id = ifb->read_identifier(); 709 go_assert(id[0] == '$' && id[1] == 't'); 710 const char *p = id.c_str(); 711 char *end; 712 long idx = strtol(p + 2, &end, 10); 713 if (*end != '\0' || idx > 0x7fffffff) 714 { 715 if (!ifb->saw_error()) 716 go_error_at(loc, 717 ("invalid export data for %qs: " 718 "bad temporary statement index at %lu"), 719 ifb->name().c_str(), 720 static_cast<unsigned long>(ifb->off())); 721 ifb->set_saw_error(); 722 return Statement::make_error_statement(loc); 723 } 724 725 Type* type = NULL; 726 if (!ifb->match_c_string(" = ")) 727 { 728 ifb->require_c_string(" "); 729 type = ifb->read_type(); 730 } 731 Expression* init = NULL; 732 if (ifb->match_c_string(" = ")) 733 { 734 ifb->advance(3); 735 init = Expression::import_expression(ifb, loc); 736 } 737 if (type == NULL && init == NULL) 738 { 739 if (!ifb->saw_error()) 740 go_error_at(loc, 741 ("invalid export data for %qs: " 742 "temporary statement has neither type nor init at %lu"), 743 ifb->name().c_str(), 744 static_cast<unsigned long>(ifb->off())); 745 ifb->set_saw_error(); 746 return Statement::make_error_statement(loc); 747 } 748 749 Temporary_statement* temp = Statement::make_temporary(type, init, loc); 750 751 ifb->record_temporary(temp, static_cast<unsigned int>(idx)); 752 753 return temp; 754 } 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 class Move_subexpressions : public Traverse 762 { 763 public: 764 Move_subexpressions(int skip, Block* block) 765 : Traverse(traverse_expressions), 766 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 Move_subexpressions::expression(Expression** pexpr) 783 { 784 if (this->skip_ > 0) 785 --this->skip_; 786 else if ((*pexpr)->temporary_reference_expression() == NULL 787 && !(*pexpr)->is_nil_expression() 788 && !(*pexpr)->is_constant()) 789 { 790 Location loc = (*pexpr)->location(); 791 Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc); 792 this->block_->add_statement(temp); 793 *pexpr = Expression::make_temporary_reference(temp, loc); 794 } 795 // We only need to move top-level subexpressions. 796 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 class Move_ordered_evals : public Traverse 804 { 805 public: 806 Move_ordered_evals(Block* block) 807 : Traverse(traverse_expressions), 808 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 Move_ordered_evals::expression(Expression** pexpr) 822 { 823 // We have to look at subexpressions first. 824 if ((*pexpr)->traverse_subexpressions(this) == TRAVERSE_EXIT) 825 return TRAVERSE_EXIT; 826 827 int i; 828 if ((*pexpr)->must_eval_subexpressions_in_order(&i)) 829 { 830 Move_subexpressions ms(i, this->block_); 831 if ((*pexpr)->traverse_subexpressions(&ms) == TRAVERSE_EXIT) 832 return TRAVERSE_EXIT; 833 } 834 835 if ((*pexpr)->must_eval_in_order()) 836 { 837 Call_expression* call = (*pexpr)->call_expression(); 838 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 return TRAVERSE_SKIP_COMPONENTS; 846 } 847 848 Location loc = (*pexpr)->location(); 849 Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc); 850 this->block_->add_statement(temp); 851 *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 Assignment_statement::do_traverse(Traverse* traverse) 862 { 863 if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT) 864 return TRAVERSE_EXIT; 865 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 Assignment_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing, 873 Statement_inserter*) 874 { 875 Map_index_expression* mie = this->lhs_->map_index_expression(); 876 if (mie != NULL) 877 { 878 Location loc = this->location(); 879 880 Expression* map = mie->map(); 881 Map_type* mt = map->type()->map_type(); 882 if (mt == NULL) 883 { 884 go_assert(saw_errors()); 885 return Statement::make_error_statement(loc); 886 } 887 888 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 Move_ordered_evals moe(b); 893 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 Temporary_statement* key_temp = Statement::make_temporary(mt->key_type(), 900 mie->index(), 901 loc); 902 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 Temporary_statement* val_temp = Statement::make_temporary(mt->val_type(), 910 this->rhs_, 911 loc); 912 b->add_statement(val_temp); 913 914 // *mapassign(TYPE, MAP, &key_temp) = RHS 915 Expression* a1 = Expression::make_type_descriptor(mt, loc); 916 Expression* a2 = mie->map(); 917 Temporary_reference_expression* ref = 918 Expression::make_temporary_reference(key_temp, loc); 919 Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc); 920 Runtime::Function code; 921 Map_type::Map_alg alg = mt->algorithm(gogo); 922 switch (alg) 923 { 924 case Map_type::MAP_ALG_FAST32: 925 { 926 code = Runtime::MAPASSIGN_FAST32; 927 Type* uint32_type = Type::lookup_integer_type("uint32"); 928 Type* uint32_ptr_type = Type::make_pointer_type(uint32_type); 929 a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3, 930 loc); 931 a3 = Expression::make_dereference(a3, 932 Expression::NIL_CHECK_NOT_NEEDED, 933 loc); 934 break; 935 } 936 case Map_type::MAP_ALG_FAST64: 937 { 938 code = Runtime::MAPASSIGN_FAST64; 939 Type* uint64_type = Type::lookup_integer_type("uint64"); 940 Type* uint64_ptr_type = Type::make_pointer_type(uint64_type); 941 a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3, 942 loc); 943 a3 = Expression::make_dereference(a3, 944 Expression::NIL_CHECK_NOT_NEEDED, 945 loc); 946 break; 947 } 948 case Map_type::MAP_ALG_FAST32PTR: 949 case Map_type::MAP_ALG_FAST64PTR: 950 { 951 code = (alg == Map_type::MAP_ALG_FAST32PTR 952 ? Runtime::MAPASSIGN_FAST32PTR 953 : Runtime::MAPASSIGN_FAST64PTR); 954 Type* ptr_type = 955 Type::make_pointer_type(Type::make_void_type()); 956 Type* ptr_ptr_type = Type::make_pointer_type(ptr_type); 957 a3 = Expression::make_unsafe_cast(ptr_ptr_type, a3, 958 loc); 959 a3 = Expression::make_dereference(a3, 960 Expression::NIL_CHECK_NOT_NEEDED, 961 loc); 962 break; 963 } 964 case Map_type::MAP_ALG_FASTSTR: 965 code = Runtime::MAPASSIGN_FASTSTR; 966 a3 = ref; 967 break; 968 default: 969 code = Runtime::MAPASSIGN; 970 break; 971 } 972 Expression* call = Runtime::make_call(gogo, code, loc, 3, 973 a1, a2, a3); 974 Type* ptrval_type = Type::make_pointer_type(mt->val_type()); 975 call = Expression::make_cast(ptrval_type, call, loc); 976 Expression* indir = 977 Expression::make_dereference(call, Expression::NIL_CHECK_NOT_NEEDED, 978 loc); 979 ref = Expression::make_temporary_reference(val_temp, loc); 980 Statement* s = Statement::make_assignment(indir, ref, loc); 981 s->determine_types(gogo); 982 b->add_statement(s); 983 984 return Statement::make_block_statement(b, loc); 985 } 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 Array_index_expression* aie = this->rhs_->array_index_expression(); 990 if (aie != NULL 991 && aie->end() != NULL 992 && Expression::is_same_variable(this->lhs_, aie->array())) 993 { 994 Numeric_constant nc; 995 unsigned long ival; 996 if (aie->start()->numeric_constant_value(&nc) 997 && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID 998 && ival == 0) 999 this->omit_write_barrier_ = true; 1000 } 1001 String_index_expression* sie = this->rhs_->string_index_expression(); 1002 if (sie != NULL 1003 && sie->end() != NULL 1004 && Expression::is_same_variable(this->lhs_, sie->string())) 1005 { 1006 Numeric_constant nc; 1007 unsigned long ival; 1008 if (sie->start()->numeric_constant_value(&nc) 1009 && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID 1010 && ival == 0) 1011 this->omit_write_barrier_ = true; 1012 } 1013 1014 return this; 1015 } 1016 1017 // Set types for the assignment. 1018 1019 void 1020 Assignment_statement::do_determine_types(Gogo* gogo) 1021 { 1022 this->lhs_->determine_type_no_context(gogo); 1023 Type* rhs_context_type = this->lhs_->type(); 1024 if (rhs_context_type->is_sink_type()) 1025 rhs_context_type = NULL; 1026 Type_context context(rhs_context_type, false); 1027 this->rhs_->determine_type(gogo, &context); 1028 } 1029 1030 // Check types for an assignment from RHS to LHS. Returns true if the 1031 // assignment is OK. 1032 1033 bool 1034 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 if (!lhs->is_addressable() 1041 && !Index_expression::is_map_index(lhs) 1042 && !lhs->is_sink_expression()) 1043 { 1044 if (!lhs->type()->is_error()) 1045 go_error_at(lhs->location(), "invalid left hand side of assignment"); 1046 return false; 1047 } 1048 1049 Type* lhs_type = lhs->type(); 1050 1051 // Check for invalid assignment of nil to the blank identifier. 1052 if (lhs_type->is_sink_type() && rhs_type->is_nil_type()) 1053 { 1054 go_error_at(loc, "use of untyped nil"); 1055 return false; 1056 } 1057 1058 std::string reason; 1059 if (!Type::are_assignable(lhs_type, rhs_type, &reason)) 1060 { 1061 if (reason.empty()) 1062 go_error_at(loc, "incompatible types in assignment"); 1063 else 1064 go_error_at(loc, "incompatible types in assignment (%s)", 1065 reason.c_str()); 1066 return false; 1067 } 1068 1069 if (lhs_type->is_error_type() || rhs_type->is_error_type()) 1070 return false; 1071 1072 return true; 1073 } 1074 1075 // Check types for an assignment. 1076 1077 void 1078 Assignment_statement::do_check_types(Gogo*) 1079 { 1080 if (!Assignment_statement::check_assignment_types(this->lhs_, 1081 this->rhs_->type(), 1082 this->location())) 1083 this->set_is_error(); 1084 } 1085 1086 void 1087 Assignment_statement::do_export_statement(Export_function_body* efb) 1088 { 1089 this->lhs_->export_expression(efb); 1090 efb->write_c_string(" = "); 1091 this->rhs_->export_expression(efb); 1092 } 1093 1094 // Flatten an assignment statement. We may need a temporary for 1095 // interface conversion. 1096 1097 Statement* 1098 Assignment_statement::do_flatten(Gogo*, Named_object*, Block*, 1099 Statement_inserter* inserter) 1100 { 1101 if (this->lhs_->is_error_expression() 1102 || this->lhs_->type()->is_error_type() 1103 || this->rhs_->is_error_expression() 1104 || this->rhs_->type()->is_error_type()) 1105 { 1106 go_assert(saw_errors()); 1107 return Statement::make_error_statement(this->location()); 1108 } 1109 1110 if (!this->lhs_->is_sink_expression() 1111 && !Type::are_identical(this->lhs_->type(), this->rhs_->type(), 1112 Type::COMPARE_ERRORS | Type::COMPARE_TAGS, 1113 NULL) 1114 && this->rhs_->type()->interface_type() != NULL 1115 && !this->rhs_->is_multi_eval_safe()) 1116 { 1117 Temporary_statement* temp = 1118 Statement::make_temporary(NULL, this->rhs_, this->location()); 1119 inserter->insert(temp); 1120 this->rhs_ = Expression::make_temporary_reference(temp, 1121 this->location()); 1122 } 1123 return this; 1124 } 1125 1126 // Add explicit type conversions. 1127 1128 void 1129 Assignment_statement::do_add_conversions() 1130 { 1131 Type* lt = this->lhs_->type(); 1132 Type* rt = this->rhs_->type(); 1133 if (!Type::are_identical(lt, rt, 0, NULL) 1134 && lt->interface_type() != NULL) 1135 this->rhs_ = Expression::make_cast(lt, this->rhs_, this->location()); 1136 } 1137 1138 // Convert an assignment statement to the backend representation. 1139 1140 Bstatement* 1141 Assignment_statement::do_get_backend(Translate_context* context) 1142 { 1143 if (this->lhs_->is_sink_expression()) 1144 { 1145 Bexpression* rhs = this->rhs_->get_backend(context); 1146 Bfunction* bfunction = context->function()->func_value()->get_decl(); 1147 return context->backend()->expression_statement(bfunction, rhs); 1148 } 1149 1150 Bexpression* lhs = this->lhs_->get_backend(context); 1151 Expression* conv = 1152 Expression::convert_for_assignment(context->gogo(), this->lhs_->type(), 1153 this->rhs_, this->location()); 1154 Bexpression* rhs = conv->get_backend(context); 1155 Bfunction* bfunction = context->function()->func_value()->get_decl(); 1156 return context->backend()->assignment_statement(bfunction, lhs, rhs, 1157 this->location()); 1158 } 1159 1160 // Dump the AST representation for an assignment statement. 1161 1162 void 1163 Assignment_statement::do_dump_statement(Ast_dump_context* ast_dump_context) 1164 const 1165 { 1166 ast_dump_context->print_indent(); 1167 ast_dump_context->dump_expression(this->lhs_); 1168 ast_dump_context->ostream() << " = " ; 1169 ast_dump_context->dump_expression(this->rhs_); 1170 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 1171 } 1172 1173 // Make an assignment statement. 1174 1175 Assignment_statement* 1176 Statement::make_assignment(Expression* lhs, Expression* rhs, 1177 Location location) 1178 { 1179 Temporary_reference_expression* tre = lhs->temporary_reference_expression(); 1180 if (tre != NULL) 1181 tre->statement()->set_assigned(); 1182 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 Assignment_operation_statement(Operator op, Expression* lhs, Expression* rhs, 1191 Location location) 1192 : Statement(STATEMENT_ASSIGNMENT_OPERATION, location), 1193 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 do_get_backend(Translate_context*) 1211 { 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 Assignment_operation_statement::do_traverse(Traverse* traverse) 1232 { 1233 if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT) 1234 return TRAVERSE_EXIT; 1235 return this->traverse_expression(traverse, &this->rhs_); 1236 } 1237 1238 void 1239 Assignment_operation_statement::do_determine_types(Gogo* gogo) 1240 { 1241 this->lhs_->determine_type_no_context(gogo); 1242 Type* rhs_context_type = this->lhs_->type(); 1243 if (rhs_context_type->is_sink_type()) 1244 rhs_context_type = NULL; 1245 Type_context context(rhs_context_type, false); 1246 this->rhs_->determine_type(gogo, &context); 1247 } 1248 1249 // Get the binary operator from the assignment operator. 1250 1251 Operator 1252 Assignment_operation_statement::get_binop() 1253 { 1254 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 default: 1279 go_unreachable(); 1280 } 1281 } 1282 1283 void 1284 Assignment_operation_statement::do_check_types(Gogo*) 1285 { 1286 if (this->lhs_->is_sink_expression()) 1287 { 1288 this->report_error(_("cannot use %<_%> as value")); 1289 return; 1290 } 1291 1292 1293 Type* lhs_type = this->lhs_->type(); 1294 Type* rhs_type = this->rhs_->type(); 1295 1296 if (!this->lhs_->is_addressable() 1297 && !Index_expression::is_map_index(this->lhs_)) 1298 { 1299 if (!lhs_type->is_error()) 1300 this->report_error(_("invalid left hand side of assignment")); 1301 this->set_is_error(); 1302 return; 1303 } 1304 1305 if (this->op_ != OPERATOR_LSHIFTEQ && this->op_ != OPERATOR_RSHIFTEQ) 1306 { 1307 if (!Type::are_compatible_for_binop(lhs_type, rhs_type)) 1308 { 1309 this->report_error(_("incompatible type in binary expression")); 1310 return; 1311 } 1312 if (!Binary_expression::check_operator_type(this->get_binop(), lhs_type, 1313 rhs_type, this->location())) 1314 { 1315 this->set_is_error(); 1316 return; 1317 } 1318 if (this->op_ == OPERATOR_DIVEQ || this->op_ == OPERATOR_MODEQ) 1319 { 1320 Numeric_constant rconst; 1321 unsigned long rval; 1322 if (lhs_type->integer_type() != NULL 1323 && this->rhs_->numeric_constant_value(&rconst) 1324 && rconst.to_unsigned_long(&rval) == Numeric_constant::NC_UL_VALID 1325 && rval == 0) 1326 { 1327 this->report_error(_("integer division by zero")); 1328 return; 1329 } 1330 } 1331 } 1332 else 1333 { 1334 if (lhs_type->integer_type() == NULL) 1335 { 1336 this->report_error(_("shift of non-integer operand")); 1337 return; 1338 } 1339 1340 if (rhs_type->is_string_type() 1341 || (!rhs_type->is_abstract() 1342 && rhs_type->integer_type() == NULL)) 1343 { 1344 this->report_error(_("shift count not integer")); 1345 return; 1346 } 1347 1348 Numeric_constant nc; 1349 if (this->rhs_->numeric_constant_value(&nc)) 1350 { 1351 mpz_t val; 1352 if (!nc.to_int(&val)) 1353 { 1354 this->report_error(_("shift count not integer")); 1355 return; 1356 } 1357 if (mpz_sgn(val) < 0) 1358 this->report_error(_("negative shift count")); 1359 mpz_clear(val); 1360 } 1361 } 1362 } 1363 1364 // Lower an assignment operation statement to a regular assignment 1365 // statement. 1366 1367 Statement* 1368 Assignment_operation_statement::do_lower(Gogo* gogo, Named_object*, 1369 Block* enclosing, Statement_inserter*) 1370 { 1371 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 Block* b = new Block(enclosing, loc); 1376 Move_ordered_evals moe(b); 1377 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 int i; 1383 if (this->lhs_->must_eval_subexpressions_in_order(&i)) 1384 { 1385 Move_subexpressions ms(i, b); 1386 this->lhs_->traverse_subexpressions(&ms); 1387 } 1388 1389 Expression* lval = this->lhs_->copy(); 1390 1391 Expression* binop = Expression::make_binary(this->get_binop(), lval, 1392 this->rhs_, loc); 1393 Statement* s = Statement::make_assignment(this->lhs_, binop, loc); 1394 s->determine_types(gogo); 1395 if (b->statements()->empty()) 1396 { 1397 delete b; 1398 return s; 1399 } 1400 else 1401 { 1402 b->add_statement(s); 1403 return Statement::make_block_statement(b, loc); 1404 } 1405 } 1406 1407 // Dump the AST representation for an assignment operation statement 1408 1409 void 1410 Assignment_operation_statement::do_dump_statement( 1411 Ast_dump_context* ast_dump_context) const 1412 { 1413 ast_dump_context->print_indent(); 1414 ast_dump_context->dump_expression(this->lhs_); 1415 ast_dump_context->dump_operator(this->op_); 1416 ast_dump_context->dump_expression(this->rhs_); 1417 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 1418 } 1419 1420 // Make an assignment operation statement. 1421 1422 Statement* 1423 Statement::make_assignment_operation(Operator op, Expression* lhs, 1424 Expression* rhs, Location location) 1425 { 1426 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 Tuple_assignment_statement(Expression_list* lhs, Expression_list* rhs, 1437 Location location) 1438 : Statement(STATEMENT_TUPLE_ASSIGNMENT, location), 1439 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 do_get_backend(Translate_context*) 1457 { 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 Tuple_assignment_statement::do_traverse(Traverse* traverse) 1473 { 1474 if (this->traverse_expression_list(traverse, this->lhs_) == TRAVERSE_EXIT) 1475 return TRAVERSE_EXIT; 1476 return this->traverse_expression_list(traverse, this->rhs_); 1477 } 1478 1479 void 1480 Tuple_assignment_statement::do_determine_types(Gogo* gogo) 1481 { 1482 Expression_list::iterator pr = this->rhs_->begin(); 1483 for (Expression_list::iterator pl = this->lhs_->begin(); 1484 pl != this->lhs_->end(); 1485 ++pl, ++pr) 1486 { 1487 go_assert(pr != this->rhs_->end()); 1488 (*pl)->determine_type_no_context(gogo); 1489 Type* rhs_context_type = (*pl)->type(); 1490 if (rhs_context_type->is_sink_type()) 1491 rhs_context_type = NULL; 1492 Type_context context(rhs_context_type, false); 1493 (*pr)->determine_type(gogo, &context); 1494 } 1495 go_assert(pr == this->rhs_->end()); 1496 } 1497 1498 void 1499 Tuple_assignment_statement::do_check_types(Gogo*) 1500 { 1501 Expression_list::iterator pr = this->rhs_->begin(); 1502 for (Expression_list::iterator pl = this->lhs_->begin(); 1503 pl != this->lhs_->end(); 1504 ++pl, ++pr) 1505 { 1506 go_assert(pr != this->rhs_->end()); 1507 if (!Assignment_statement::check_assignment_types(*pl, (*pr)->type(), 1508 this->location())) 1509 this->set_is_error(); 1510 } 1511 go_assert(pr == this->rhs_->end()); 1512 } 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 Tuple_assignment_statement::do_lower(Gogo* gogo, Named_object*, 1519 Block* enclosing, Statement_inserter*) 1520 { 1521 Location loc = this->location(); 1522 1523 if (this->classification() == STATEMENT_ERROR) 1524 return Statement::make_error_statement(loc); 1525 1526 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 Move_ordered_evals moe(b); 1531 for (Expression_list::iterator plhs = this->lhs_->begin(); 1532 plhs != this->lhs_->end(); 1533 ++plhs) 1534 Expression::traverse(&*plhs, &moe); 1535 1536 std::vector<Temporary_statement*> temps; 1537 temps.reserve(this->lhs_->size()); 1538 1539 Expression_list::const_iterator prhs = this->rhs_->begin(); 1540 for (Expression_list::const_iterator plhs = this->lhs_->begin(); 1541 plhs != this->lhs_->end(); 1542 ++plhs, ++prhs) 1543 { 1544 go_assert(prhs != this->rhs_->end()); 1545 1546 if ((*plhs)->is_error_expression() 1547 || (*plhs)->type()->is_error() 1548 || (*prhs)->is_error_expression() 1549 || (*prhs)->type()->is_error()) 1550 continue; 1551 1552 if ((*plhs)->is_sink_expression()) 1553 { 1554 if ((*prhs)->type()->is_nil_type()) 1555 this->report_error(_("use of untyped nil")); 1556 else 1557 b->add_statement(Statement::make_statement(*prhs, true)); 1558 continue; 1559 } 1560 1561 Temporary_statement* temp = Statement::make_temporary((*plhs)->type(), 1562 *prhs, loc); 1563 b->add_statement(temp); 1564 temps.push_back(temp); 1565 1566 } 1567 go_assert(prhs == this->rhs_->end()); 1568 1569 prhs = this->rhs_->begin(); 1570 std::vector<Temporary_statement*>::const_iterator ptemp = temps.begin(); 1571 for (Expression_list::const_iterator plhs = this->lhs_->begin(); 1572 plhs != this->lhs_->end(); 1573 ++plhs, ++prhs) 1574 { 1575 if ((*plhs)->is_error_expression() 1576 || (*plhs)->type()->is_error() 1577 || (*prhs)->is_error_expression() 1578 || (*prhs)->type()->is_error()) 1579 continue; 1580 1581 if ((*plhs)->is_sink_expression()) 1582 continue; 1583 1584 Expression* ref = Expression::make_temporary_reference(*ptemp, loc); 1585 Statement* s = Statement::make_assignment(*plhs, ref, loc); 1586 s->determine_types(gogo); 1587 b->add_statement(s); 1588 ++ptemp; 1589 } 1590 go_assert(ptemp == temps.end() || saw_errors()); 1591 1592 return Statement::make_block_statement(b, loc); 1593 } 1594 1595 // Dump the AST representation for a tuple assignment statement. 1596 1597 void 1598 Tuple_assignment_statement::do_dump_statement( 1599 Ast_dump_context* ast_dump_context) const 1600 { 1601 ast_dump_context->print_indent(); 1602 ast_dump_context->dump_expression_list(this->lhs_); 1603 ast_dump_context->ostream() << " = "; 1604 ast_dump_context->dump_expression_list(this->rhs_); 1605 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 1606 } 1607 1608 // Make a tuple assignment statement. 1609 1610 Statement* 1611 Statement::make_tuple_assignment(Expression_list* lhs, Expression_list* rhs, 1612 Location location) 1613 { 1614 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 Tuple_map_assignment_statement(Expression* val, Expression* present, 1624 Expression* map_index, 1625 Location location) 1626 : Statement(STATEMENT_TUPLE_MAP_ASSIGNMENT, location), 1627 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 do_get_backend(Translate_context*) 1645 { 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 Tuple_map_assignment_statement::do_traverse(Traverse* traverse) 1663 { 1664 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT 1665 || this->traverse_expression(traverse, &this->present_) == TRAVERSE_EXIT) 1666 return TRAVERSE_EXIT; 1667 return this->traverse_expression(traverse, &this->map_index_); 1668 } 1669 1670 void 1671 Tuple_map_assignment_statement::do_determine_types(Gogo* gogo) 1672 { 1673 this->val_->determine_type_no_context(gogo); 1674 this->present_->determine_type_no_context(gogo); 1675 this->map_index_->determine_type_no_context(gogo); 1676 } 1677 1678 void 1679 Tuple_map_assignment_statement::do_check_types(Gogo*) 1680 { 1681 Expression* map_expr = this->map_index_; 1682 Map_type* map_type; 1683 if (map_expr->map_index_expression() != NULL) 1684 map_type = map_expr->map_index_expression()->get_map_type(); 1685 else if (map_expr->index_expression() != NULL) 1686 map_type = map_expr->index_expression()->left()->type()->map_type(); 1687 else 1688 { 1689 this->report_error(_("expected map index on right hand side")); 1690 return; 1691 } 1692 if (map_type == NULL || map_type->is_error()) 1693 { 1694 go_assert(saw_errors()); 1695 this->set_is_error(); 1696 return; 1697 } 1698 1699 if (!Assignment_statement::check_assignment_types(this->val_, 1700 map_type->val_type(), 1701 this->location())) 1702 this->set_is_error(); 1703 if (!Assignment_statement::check_assignment_types(this->present_, 1704 Type::make_boolean_type(), 1705 this->location())) 1706 this->set_is_error(); 1707 } 1708 1709 // Lower a tuple map assignment. 1710 1711 Statement* 1712 Tuple_map_assignment_statement::do_lower(Gogo* gogo, Named_object*, 1713 Block* enclosing, Statement_inserter*) 1714 { 1715 Location loc = this->location(); 1716 1717 if (this->classification() == STATEMENT_ERROR) 1718 return Statement::make_error_statement(loc); 1719 1720 Map_index_expression* map_index = this->map_index_->map_index_expression(); 1721 go_assert(map_index != NULL); 1722 Map_type* map_type = map_index->get_map_type(); 1723 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 Type_conversion_expression* ce = map_index->index()->conversion_expression(); 1728 if (ce != NULL && ce->type()->is_string_type() 1729 && ce->expr()->type()->is_slice_type()) 1730 ce->set_no_copy(true); 1731 1732 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 Move_ordered_evals moe(b); 1737 this->val_->traverse_subexpressions(&moe); 1738 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 Temporary_statement* key_temp = 1745 Statement::make_temporary(map_type->key_type(), map_index->index(), loc); 1746 b->add_statement(key_temp); 1747 1748 // var val_ptr_temp *VAL_TYPE 1749 Type* val_ptr_type = Type::make_pointer_type(map_type->val_type()); 1750 Temporary_statement* val_ptr_temp = Statement::make_temporary(val_ptr_type, 1751 NULL, loc); 1752 b->add_statement(val_ptr_temp); 1753 1754 // var present_temp bool 1755 Temporary_statement* present_temp = 1756 Statement::make_temporary((this->present_->type()->is_boolean_type() 1757 ? this->present_->type() 1758 : Type::lookup_bool_type()), 1759 NULL, loc); 1760 b->add_statement(present_temp); 1761 1762 // val_ptr_temp, present_temp = mapaccess2(DESCRIPTOR, MAP, &key_temp) 1763 Expression* a1 = Expression::make_type_descriptor(map_type, loc); 1764 Expression* a2 = map_index->map(); 1765 Temporary_reference_expression* ref = 1766 Expression::make_temporary_reference(key_temp, loc); 1767 Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc); 1768 Expression* a4 = map_type->fat_zero_value(gogo); 1769 Call_expression* call; 1770 if (a4 == NULL) 1771 { 1772 Runtime::Function code; 1773 Map_type::Map_alg alg = map_type->algorithm(gogo); 1774 switch (alg) 1775 { 1776 case Map_type::MAP_ALG_FAST32: 1777 case Map_type::MAP_ALG_FAST32PTR: 1778 { 1779 code = Runtime::MAPACCESS2_FAST32; 1780 Type* uint32_type = Type::lookup_integer_type("uint32"); 1781 Type* uint32_ptr_type = Type::make_pointer_type(uint32_type); 1782 a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3, 1783 loc); 1784 a3 = Expression::make_dereference(a3, 1785 Expression::NIL_CHECK_NOT_NEEDED, 1786 loc); 1787 break; 1788 } 1789 case Map_type::MAP_ALG_FAST64: 1790 case Map_type::MAP_ALG_FAST64PTR: 1791 { 1792 code = Runtime::MAPACCESS2_FAST64; 1793 Type* uint64_type = Type::lookup_integer_type("uint64"); 1794 Type* uint64_ptr_type = Type::make_pointer_type(uint64_type); 1795 a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3, 1796 loc); 1797 a3 = Expression::make_dereference(a3, 1798 Expression::NIL_CHECK_NOT_NEEDED, 1799 loc); 1800 break; 1801 } 1802 case Map_type::MAP_ALG_FASTSTR: 1803 code = Runtime::MAPACCESS2_FASTSTR; 1804 a3 = ref; 1805 break; 1806 default: 1807 code = Runtime::MAPACCESS2; 1808 break; 1809 } 1810 call = Runtime::make_call(gogo, code, loc, 3, a1, a2, a3); 1811 } 1812 else 1813 call = Runtime::make_call(gogo, Runtime::MAPACCESS2_FAT, loc, 4, 1814 a1, a2, a3, a4); 1815 ref = Expression::make_temporary_reference(val_ptr_temp, loc); 1816 ref->set_is_lvalue(); 1817 Expression* res = Expression::make_call_result(call, 0); 1818 res = Expression::make_unsafe_cast(val_ptr_type, res, loc); 1819 Statement* s = Statement::make_assignment(ref, res, loc); 1820 s->determine_types(gogo); 1821 b->add_statement(s); 1822 ref = Expression::make_temporary_reference(present_temp, loc); 1823 ref->set_is_lvalue(); 1824 res = Expression::make_call_result(call, 1); 1825 s = Statement::make_assignment(ref, res, loc); 1826 s->determine_types(gogo); 1827 b->add_statement(s); 1828 1829 // val = *val__ptr_temp 1830 ref = Expression::make_temporary_reference(val_ptr_temp, loc); 1831 Expression* ind = 1832 Expression::make_dereference(ref, Expression::NIL_CHECK_NOT_NEEDED, loc); 1833 s = Statement::make_assignment(this->val_, ind, loc); 1834 s->determine_types(gogo); 1835 b->add_statement(s); 1836 1837 // present = present_temp 1838 ref = Expression::make_temporary_reference(present_temp, loc); 1839 s = Statement::make_assignment(this->present_, ref, loc); 1840 s->determine_types(gogo); 1841 b->add_statement(s); 1842 1843 return Statement::make_block_statement(b, loc); 1844 } 1845 1846 // Dump the AST representation for a tuple map assignment statement. 1847 1848 void 1849 Tuple_map_assignment_statement::do_dump_statement( 1850 Ast_dump_context* ast_dump_context) const 1851 { 1852 ast_dump_context->print_indent(); 1853 ast_dump_context->dump_expression(this->val_); 1854 ast_dump_context->ostream() << ", "; 1855 ast_dump_context->dump_expression(this->present_); 1856 ast_dump_context->ostream() << " = "; 1857 ast_dump_context->dump_expression(this->map_index_); 1858 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 1859 } 1860 1861 // Make a map assignment statement which returns a pair of values. 1862 1863 Statement* 1864 Statement::make_tuple_map_assignment(Expression* val, Expression* present, 1865 Expression* map_index, 1866 Location location) 1867 { 1868 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 Tuple_receive_assignment_statement(Expression* val, Expression* closed, 1877 Expression* channel, Location location) 1878 : Statement(STATEMENT_TUPLE_RECEIVE_ASSIGNMENT, location), 1879 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 do_get_backend(Translate_context*) 1897 { 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 Tuple_receive_assignment_statement::do_traverse(Traverse* traverse) 1915 { 1916 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT 1917 || this->traverse_expression(traverse, &this->closed_) == TRAVERSE_EXIT) 1918 return TRAVERSE_EXIT; 1919 return this->traverse_expression(traverse, &this->channel_); 1920 } 1921 1922 void 1923 Tuple_receive_assignment_statement::do_determine_types(Gogo* gogo) 1924 { 1925 this->val_->determine_type_no_context(gogo); 1926 this->closed_->determine_type_no_context(gogo); 1927 this->channel_->determine_type_no_context(gogo); 1928 } 1929 1930 void 1931 Tuple_receive_assignment_statement::do_check_types(Gogo*) 1932 { 1933 Channel_type* ct = this->channel_->type()->channel_type(); 1934 if (ct == NULL) 1935 { 1936 this->report_error(_("expected channel")); 1937 return; 1938 } 1939 if (!ct->may_receive()) 1940 { 1941 this->report_error(_("invalid receive on send-only channel")); 1942 return; 1943 } 1944 1945 if (!Assignment_statement::check_assignment_types(this->val_, 1946 ct->element_type(), 1947 this->location())) 1948 this->set_is_error(); 1949 if (!Assignment_statement::check_assignment_types(this->closed_, 1950 Type::make_boolean_type(), 1951 this->location())) 1952 this->set_is_error(); 1953 } 1954 1955 // Lower to a function call. 1956 1957 Statement* 1958 Tuple_receive_assignment_statement::do_lower(Gogo* gogo, Named_object*, 1959 Block* enclosing, 1960 Statement_inserter*) 1961 { 1962 Location loc = this->location(); 1963 1964 if (this->classification() == STATEMENT_ERROR) 1965 return Statement::make_error_statement(loc); 1966 1967 Channel_type* channel_type = this->channel_->type()->channel_type(); 1968 go_assert(channel_type != NULL && channel_type->may_receive()); 1969 1970 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 Move_ordered_evals moe(b); 1975 this->val_->traverse_subexpressions(&moe); 1976 this->closed_->traverse_subexpressions(&moe); 1977 1978 // var val_temp ELEMENT_TYPE 1979 Temporary_statement* val_temp = 1980 Statement::make_temporary(channel_type->element_type(), NULL, loc); 1981 b->add_statement(val_temp); 1982 1983 // var closed_temp bool 1984 Temporary_statement* closed_temp = 1985 Statement::make_temporary((this->closed_->type()->is_boolean_type() 1986 ? this->closed_->type() 1987 : Type::lookup_bool_type()), 1988 NULL, loc); 1989 b->add_statement(closed_temp); 1990 1991 // closed_temp = chanrecv2(channel, &val_temp) 1992 Temporary_reference_expression* ref = 1993 Expression::make_temporary_reference(val_temp, loc); 1994 Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc); 1995 Expression* call = Runtime::make_call(gogo, Runtime::CHANRECV2, 1996 loc, 2, this->channel_, p2); 1997 ref = Expression::make_temporary_reference(closed_temp, loc); 1998 ref->set_is_lvalue(); 1999 Statement* s = Statement::make_assignment(ref, call, loc); 2000 s->determine_types(gogo); 2001 b->add_statement(s); 2002 2003 // val = val_temp 2004 ref = Expression::make_temporary_reference(val_temp, loc); 2005 s = Statement::make_assignment(this->val_, ref, loc); 2006 s->determine_types(gogo); 2007 b->add_statement(s); 2008 2009 // closed = closed_temp 2010 ref = Expression::make_temporary_reference(closed_temp, loc); 2011 s = Statement::make_assignment(this->closed_, ref, loc); 2012 s->determine_types(gogo); 2013 b->add_statement(s); 2014 2015 return Statement::make_block_statement(b, loc); 2016 } 2017 2018 // Dump the AST representation for a tuple receive statement. 2019 2020 void 2021 Tuple_receive_assignment_statement::do_dump_statement( 2022 Ast_dump_context* ast_dump_context) const 2023 { 2024 ast_dump_context->print_indent(); 2025 ast_dump_context->dump_expression(this->val_); 2026 ast_dump_context->ostream() << ", "; 2027 ast_dump_context->dump_expression(this->closed_); 2028 ast_dump_context->ostream() << " <- "; 2029 ast_dump_context->dump_expression(this->channel_); 2030 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 2031 } 2032 2033 // Make a nonblocking receive statement. 2034 2035 Statement* 2036 Statement::make_tuple_receive_assignment(Expression* val, Expression* closed, 2037 Expression* channel, 2038 Location location) 2039 { 2040 return new Tuple_receive_assignment_statement(val, closed, channel, 2041 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 Tuple_type_guard_assignment_statement(Expression* val, Expression* ok, 2051 Expression* expr, Type* type, 2052 Location location) 2053 : Statement(STATEMENT_TUPLE_TYPE_GUARD_ASSIGNMENT, location), 2054 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 do_get_backend(Translate_context*) 2072 { 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 Tuple_type_guard_assignment_statement::do_traverse(Traverse* traverse) 2098 { 2099 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT 2100 || this->traverse_expression(traverse, &this->ok_) == TRAVERSE_EXIT 2101 || this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT) 2102 return TRAVERSE_EXIT; 2103 return this->traverse_expression(traverse, &this->expr_); 2104 } 2105 2106 void 2107 Tuple_type_guard_assignment_statement::do_determine_types(Gogo* gogo) 2108 { 2109 this->val_->determine_type_no_context(gogo); 2110 this->ok_->determine_type_no_context(gogo); 2111 this->expr_->determine_type_no_context(gogo); 2112 } 2113 2114 void 2115 Tuple_type_guard_assignment_statement::do_check_types(Gogo*) 2116 { 2117 Type* expr_type = this->expr_->type(); 2118 if (expr_type->interface_type() == NULL) 2119 { 2120 if (!expr_type->is_error() && !this->type_->is_error()) 2121 this->report_error(_("type assertion only valid for interface types")); 2122 return; 2123 } 2124 2125 if (!Assignment_statement::check_assignment_types(this->val_, this->type_, 2126 this->location())) 2127 this->set_is_error(); 2128 if (!Assignment_statement::check_assignment_types(this->ok_, 2129 Type::make_boolean_type(), 2130 this->location())) 2131 this->set_is_error(); 2132 } 2133 2134 // Lower to a function call. 2135 2136 Statement* 2137 Tuple_type_guard_assignment_statement::do_lower(Gogo* gogo, Named_object*, 2138 Block* enclosing, 2139 Statement_inserter*) 2140 { 2141 Location loc = this->location(); 2142 2143 if (this->classification() == STATEMENT_ERROR) 2144 return Statement::make_error_statement(loc); 2145 2146 Type* expr_type = this->expr_->type(); 2147 go_assert(expr_type->interface_type() != NULL); 2148 2149 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 Move_ordered_evals moe(b); 2154 this->val_->traverse_subexpressions(&moe); 2155 this->ok_->traverse_subexpressions(&moe); 2156 2157 bool expr_is_empty = expr_type->interface_type()->is_empty(); 2158 Call_expression* call; 2159 if (this->type_->interface_type() != NULL) 2160 { 2161 if (this->type_->interface_type()->is_empty()) 2162 call = Runtime::make_call(gogo, 2163 (expr_is_empty 2164 ? Runtime::IFACEE2E2 2165 : Runtime::IFACEI2E2), 2166 loc, 1, this->expr_); 2167 else 2168 call = this->lower_to_type(gogo, 2169 (expr_is_empty 2170 ? Runtime::IFACEE2I2 2171 : Runtime::IFACEI2I2)); 2172 } 2173 else if (this->type_->points_to() != NULL) 2174 call = this->lower_to_type(gogo, 2175 (expr_is_empty 2176 ? Runtime::IFACEE2T2P 2177 : Runtime::IFACEI2T2P)); 2178 else 2179 { 2180 this->lower_to_object_type(gogo, b, 2181 (expr_is_empty 2182 ? Runtime::IFACEE2T2 2183 : Runtime::IFACEI2T2)); 2184 call = NULL; 2185 } 2186 2187 if (call != NULL) 2188 { 2189 Expression* res = Expression::make_call_result(call, 0); 2190 res = Expression::make_unsafe_cast(this->type_, res, loc); 2191 Statement* s = Statement::make_assignment(this->val_, res, loc); 2192 s->determine_types(gogo); 2193 b->add_statement(s); 2194 2195 res = Expression::make_call_result(call, 1); 2196 if (!this->ok_->type()->is_boolean_type()) 2197 res = Expression::make_cast(Type::lookup_bool_type(), res, loc); 2198 s = Statement::make_assignment(this->ok_, res, loc); 2199 s->determine_types(gogo); 2200 b->add_statement(s); 2201 } 2202 2203 return Statement::make_block_statement(b, loc); 2204 } 2205 2206 // Lower a conversion to a non-empty interface type or a pointer type. 2207 2208 Call_expression* 2209 Tuple_type_guard_assignment_statement::lower_to_type(Gogo* gogo, 2210 Runtime::Function code) 2211 { 2212 Location loc = this->location(); 2213 return Runtime::make_call(gogo, code, loc, 2, 2214 Expression::make_type_descriptor(this->type_, loc), 2215 this->expr_); 2216 } 2217 2218 // Lower a conversion to a non-interface non-pointer type. 2219 2220 void 2221 Tuple_type_guard_assignment_statement::lower_to_object_type( 2222 Gogo* gogo, 2223 Block* b, 2224 Runtime::Function code) 2225 { 2226 Location loc = this->location(); 2227 2228 // var val_temp TYPE 2229 Temporary_statement* val_temp = Statement::make_temporary(this->type_, 2230 NULL, loc); 2231 b->add_statement(val_temp); 2232 2233 // var ok_temp bool 2234 Temporary_statement* ok_temp = NULL; 2235 if (!this->ok_->is_sink_expression()) 2236 { 2237 ok_temp = Statement::make_temporary((this->ok_->type()->is_boolean_type() 2238 ? this->ok_->type() 2239 : Type::lookup_bool_type()), 2240 NULL, loc); 2241 b->add_statement(ok_temp); 2242 } 2243 2244 // ok_temp = CODE(type_descriptor, expr, &val_temp) 2245 Expression* p1 = Expression::make_type_descriptor(this->type_, loc); 2246 Expression* ref = Expression::make_temporary_reference(val_temp, loc); 2247 Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc); 2248 Expression* call = Runtime::make_call(gogo, code, loc, 3, 2249 p1, this->expr_, p3); 2250 Statement* s; 2251 if (ok_temp == NULL) 2252 s = Statement::make_statement(call, true); 2253 else 2254 { 2255 Expression* ok_ref = Expression::make_temporary_reference(ok_temp, loc); 2256 s = Statement::make_assignment(ok_ref, call, loc); 2257 } 2258 s->determine_types(gogo); 2259 b->add_statement(s); 2260 2261 // val = val_temp 2262 ref = Expression::make_temporary_reference(val_temp, loc); 2263 s = Statement::make_assignment(this->val_, ref, loc); 2264 s->determine_types(gogo); 2265 b->add_statement(s); 2266 2267 // ok = ok_temp 2268 if (ok_temp != NULL) 2269 { 2270 ref = Expression::make_temporary_reference(ok_temp, loc); 2271 s = Statement::make_assignment(this->ok_, ref, loc); 2272 s->determine_types(gogo); 2273 b->add_statement(s); 2274 } 2275 } 2276 2277 // Dump the AST representation for a tuple type guard statement. 2278 2279 void 2280 Tuple_type_guard_assignment_statement::do_dump_statement( 2281 Ast_dump_context* ast_dump_context) const 2282 { 2283 ast_dump_context->print_indent(); 2284 ast_dump_context->dump_expression(this->val_); 2285 ast_dump_context->ostream() << ", "; 2286 ast_dump_context->dump_expression(this->ok_); 2287 ast_dump_context->ostream() << " = "; 2288 ast_dump_context->dump_expression(this->expr_); 2289 ast_dump_context->ostream() << " . "; 2290 ast_dump_context->dump_type(this->type_); 2291 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 2292 } 2293 2294 // Make an assignment from a type guard to a pair of variables. 2295 2296 Statement* 2297 Statement::make_tuple_type_guard_assignment(Expression* val, Expression* ok, 2298 Expression* expr, Type* type, 2299 Location location) 2300 { 2301 return new Tuple_type_guard_assignment_statement(val, ok, expr, type, 2302 location); 2303 } 2304 2305 // Class Expression_statement. 2306 2307 // Constructor. 2308 2309 Expression_statement::Expression_statement(Expression* expr, bool is_ignored) 2310 : Statement(STATEMENT_EXPRESSION, expr->location()), 2311 expr_(expr), is_ignored_(is_ignored) 2312 { 2313 } 2314 2315 // Determine types. 2316 2317 void 2318 Expression_statement::do_determine_types(Gogo* gogo) 2319 { 2320 this->expr_->determine_type_no_context(gogo); 2321 } 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 Expression_statement::do_check_types(Gogo*) 2329 { 2330 if (!this->is_ignored_) 2331 this->expr_->discarding_value(); 2332 } 2333 2334 // An expression statement is only a terminating statement if it is 2335 // a call to panic. 2336 2337 bool 2338 Expression_statement::do_may_fall_through() const 2339 { 2340 // The builtin function panic does not return. 2341 const Call_expression* call = this->expr_->call_expression(); 2342 if (call == NULL) 2343 return true; 2344 const Builtin_call_expression* bce = call->builtin_call_expression(); 2345 return bce == NULL || bce->code() != Builtin_call_expression::BUILTIN_PANIC; 2346 } 2347 2348 // Export an expression statement. 2349 2350 void 2351 Expression_statement::do_export_statement(Export_function_body* efb) 2352 { 2353 this->expr_->export_expression(efb); 2354 } 2355 2356 // Convert to backend representation. 2357 2358 Bstatement* 2359 Expression_statement::do_get_backend(Translate_context* context) 2360 { 2361 Bexpression* bexpr = this->expr_->get_backend(context); 2362 Bfunction* bfunction = context->function()->func_value()->get_decl(); 2363 return context->backend()->expression_statement(bfunction, bexpr); 2364 } 2365 2366 // Dump the AST representation for an expression statement 2367 2368 void 2369 Expression_statement::do_dump_statement(Ast_dump_context* ast_dump_context) 2370 const 2371 { 2372 ast_dump_context->print_indent(); 2373 ast_dump_context->dump_expression(expr_); 2374 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 2375 } 2376 2377 // Make an expression statement from an Expression. 2378 2379 Statement* 2380 Statement::make_statement(Expression* expr, bool is_ignored) 2381 { 2382 return new Expression_statement(expr, is_ignored); 2383 } 2384 2385 // Export data for a block. 2386 2387 void 2388 Block_statement::do_export_statement(Export_function_body* efb) 2389 { 2390 Block_statement::export_block(efb, this->block_, 2391 this->is_lowered_for_statement_); 2392 } 2393 2394 void 2395 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 char buf[50]; 2400 efb->write_c_string("{"); 2401 if (is_lowered_for_statement) 2402 efb->write_c_string(" /*for*/"); 2403 snprintf(buf, sizeof buf, " //%d\n", 2404 Linemap::location_to_line(block->start_location())); 2405 efb->write_c_string(buf); 2406 2407 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 efb->decrement_indent(); 2411 efb->indent(); 2412 efb->write_c_string("}"); 2413 // Increment back to the value the caller thinks it has. 2414 efb->increment_indent(); 2415 } 2416 2417 // Import a block statement, returning the block. 2418 2419 Block* 2420 Block_statement::do_import(Import_function_body* ifb, Location loc, 2421 bool* is_lowered_for_statement) 2422 { 2423 go_assert(ifb->match_c_string("{")); 2424 *is_lowered_for_statement = false; 2425 if (ifb->match_c_string(" /*for*/")) 2426 { 2427 ifb->advance(8); 2428 *is_lowered_for_statement = true; 2429 } 2430 size_t nl = ifb->body().find('\n', ifb->off()); 2431 if (nl == std::string::npos) 2432 { 2433 if (!ifb->saw_error()) 2434 go_error_at(ifb->location(), 2435 "import error: no newline after %<{%> at %lu", 2436 static_cast<unsigned long>(ifb->off())); 2437 ifb->set_saw_error(); 2438 return NULL; 2439 } 2440 ifb->set_off(nl + 1); 2441 ifb->increment_indent(); 2442 Block* block = new Block(ifb->block(), loc); 2443 ifb->begin_block(block); 2444 bool ok = Block::import_block(block, ifb, loc); 2445 ifb->finish_block(); 2446 ifb->decrement_indent(); 2447 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 Block_statement::do_get_backend(Translate_context* context) 2456 { 2457 Bblock* bblock = this->block_->get_backend(context); 2458 return context->backend()->block_statement(bblock); 2459 } 2460 2461 // Dump the AST for a block statement 2462 2463 void 2464 Block_statement::do_dump_statement(Ast_dump_context*) const 2465 { 2466 // block statement braces are dumped when traversing. 2467 } 2468 2469 // Make a block statement. 2470 2471 Block_statement* 2472 Statement::make_block_statement(Block* block, Location location) 2473 { 2474 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 Inc_dec_statement(bool is_inc, Expression* expr) 2483 : Statement(STATEMENT_INCDEC, expr->location()), 2484 expr_(expr), is_inc_(is_inc) 2485 { } 2486 2487 protected: 2488 int 2489 do_traverse(Traverse* traverse) 2490 { 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 do_get_backend(Translate_context*) 2503 { 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 Inc_dec_statement::do_determine_types(Gogo* gogo) 2517 { 2518 this->expr_->determine_type_no_context(gogo); 2519 } 2520 2521 void 2522 Inc_dec_statement::do_check_types(Gogo*) 2523 { 2524 if (!this->expr_->is_addressable() 2525 && !Index_expression::is_map_index(this->expr_)) 2526 { 2527 if (!this->expr_->type()->is_error()) 2528 this->report_error(_("invalid left hand side of assignment")); 2529 this->set_is_error(); 2530 return; 2531 } 2532 if (!this->expr_->type()->is_numeric_type()) 2533 { 2534 this->report_error(_("increment or decrement of non-numeric type")); 2535 return; 2536 } 2537 } 2538 2539 // Lower to += or -=. 2540 2541 Statement* 2542 Inc_dec_statement::do_lower(Gogo*, Named_object*, Block*, Statement_inserter*) 2543 { 2544 Location loc = this->location(); 2545 Expression* oexpr = Expression::make_integer_ul(1, this->expr_->type(), loc); 2546 Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ; 2547 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 Inc_dec_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 2554 { 2555 ast_dump_context->print_indent(); 2556 ast_dump_context->dump_expression(expr_); 2557 ast_dump_context->ostream() << (is_inc_? "++": "--") << dsuffix(location()) << std::endl; 2558 } 2559 2560 // Make an increment statement. 2561 2562 Statement* 2563 Statement::make_inc_statement(Expression* expr) 2564 { 2565 return new Inc_dec_statement(true, expr); 2566 } 2567 2568 // Make a decrement statement. 2569 2570 Statement* 2571 Statement::make_dec_statement(Expression* expr) 2572 { 2573 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 Thunk_statement::Thunk_statement(Statement_classification classification, 2582 Call_expression* call, 2583 Location location) 2584 : Statement(classification, location), 2585 call_(call) 2586 { 2587 } 2588 2589 // Return whether this is a simple statement which does not require a 2590 // thunk. 2591 2592 bool 2593 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 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 if (this->classification() == STATEMENT_DEFER) 2603 return false; 2604 2605 // We can only permit a single parameter of pointer type. 2606 const Typed_identifier_list* parameters = fntype->parameters(); 2607 if (parameters != NULL 2608 && (parameters->size() > 1 2609 || (parameters->size() == 1 2610 && parameters->begin()->type()->points_to() == NULL))) 2611 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 const Typed_identifier_list* results = fntype->results(); 2619 if (results != NULL 2620 && (results->size() > 1 2621 || (results->size() == 1 2622 && !results->begin()->type()->is_basic_type() 2623 && results->begin()->type()->points_to() == NULL))) 2624 return false; 2625 2626 // If this calls something that is not a simple function, then we 2627 // need a thunk. 2628 Expression* fn = this->call_->call_expression()->fn(); 2629 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 if (fn->func_expression()->closure() != NULL) 2635 return false; 2636 2637 return true; 2638 } 2639 2640 // Traverse a thunk statement. 2641 2642 int 2643 Thunk_statement::do_traverse(Traverse* traverse) 2644 { 2645 return this->traverse_expression(traverse, &this->call_); 2646 } 2647 2648 // Determine types in a thunk statement. 2649 2650 void 2651 Thunk_statement::do_determine_types(Gogo* gogo) 2652 { 2653 this->call_->determine_type_no_context(gogo); 2654 } 2655 2656 // Check types in a thunk statement. 2657 2658 void 2659 Thunk_statement::do_check_types(Gogo*) 2660 { 2661 if (!this->call_->discarding_value()) 2662 { 2663 this->set_is_error(); 2664 return; 2665 } 2666 Call_expression* ce = this->call_->call_expression(); 2667 if (ce == NULL) 2668 { 2669 if (!this->call_->is_error_expression()) 2670 this->report_error("expected call expression"); 2671 this->set_is_error(); 2672 return; 2673 } 2674 } 2675 2676 // The Traverse class used to find and simplify thunk statements. 2677 2678 class Simplify_thunk_traverse : public Traverse 2679 { 2680 public: 2681 Simplify_thunk_traverse(Gogo* gogo) 2682 : Traverse(traverse_functions | traverse_blocks), 2683 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 Simplify_thunk_traverse::function(Named_object* no) 2703 { 2704 go_assert(this->function_ == NULL); 2705 this->function_ = no; 2706 int t = no->func_value()->traverse(this); 2707 this->function_ = NULL; 2708 if (t == TRAVERSE_EXIT) 2709 return t; 2710 return TRAVERSE_SKIP_COMPONENTS; 2711 } 2712 2713 // Look for thunks in a block. 2714 2715 int 2716 Simplify_thunk_traverse::block(Block* b) 2717 { 2718 // The parser ensures that thunk statements always appear at the end 2719 // of a block. 2720 if (b->statements()->size() < 1) 2721 return TRAVERSE_CONTINUE; 2722 Thunk_statement* stat = b->statements()->back()->thunk_statement(); 2723 if (stat == NULL) 2724 return TRAVERSE_CONTINUE; 2725 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 Gogo::simplify_thunk_statements() 2734 { 2735 Simplify_thunk_traverse thunk_traverse(this); 2736 this->traverse(&thunk_traverse); 2737 } 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 Thunk_statement::is_constant_function() const 2744 { 2745 Call_expression* ce = this->call_->call_expression(); 2746 Function_type* fntype = ce->get_function_type(); 2747 if (fntype == NULL) 2748 { 2749 go_assert(saw_errors()); 2750 return false; 2751 } 2752 if (fntype->is_builtin()) 2753 return true; 2754 Expression* fn = ce->fn(); 2755 if (fn->func_expression() != NULL) 2756 return fn->func_expression()->closure() == NULL; 2757 if (fn->interface_field_reference_expression() != NULL) 2758 return true; 2759 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 Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function, 2773 Block* block) 2774 { 2775 if (this->classification() == STATEMENT_ERROR) 2776 return false; 2777 if (this->call_->is_error_expression()) 2778 return false; 2779 2780 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 function->func_value()->defer_stack(this->location()); 2787 } 2788 2789 Call_expression* ce = this->call_->call_expression(); 2790 Function_type* fntype = ce->get_function_type(); 2791 if (fntype == NULL) 2792 { 2793 go_assert(saw_errors()); 2794 this->set_is_error(); 2795 return false; 2796 } 2797 if (this->is_simple(fntype)) 2798 return false; 2799 2800 Struct_type* struct_type = this->build_struct(fntype); 2801 2802 Expression* fn = ce->fn(); 2803 Interface_field_reference_expression* interface_method = 2804 fn->interface_field_reference_expression(); 2805 Bound_method_expression* bme = fn->bound_method_expression(); 2806 2807 Location location = this->location(); 2808 2809 bool is_constant_function = this->is_constant_function(); 2810 Temporary_statement* fn_temp = NULL; 2811 if (!is_constant_function) 2812 { 2813 fn_temp = Statement::make_temporary(NULL, fn, location); 2814 block->insert_statement_before(block->statements()->size() - 1, fn_temp); 2815 fn = Expression::make_temporary_reference(fn_temp, location); 2816 } 2817 2818 std::string thunk_name = gogo->thunk_name(); 2819 2820 // Build the thunk. 2821 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 Expression_list* vals = new Expression_list(); 2829 if (!is_constant_function) 2830 vals->push_back(fn); 2831 2832 if (interface_method != NULL) 2833 vals->push_back(interface_method->expr()); 2834 if (bme != NULL) 2835 vals->push_back(bme->first_argument()); 2836 2837 if (ce->args() != NULL) 2838 { 2839 for (Expression_list::const_iterator p = ce->args()->begin(); 2840 p != ce->args()->end(); 2841 ++p) 2842 { 2843 if ((*p)->is_constant()) 2844 continue; 2845 vals->push_back(*p); 2846 } 2847 } 2848 2849 // Build the struct. 2850 Expression* constructor = 2851 Expression::make_struct_composite_literal(struct_type, vals, location); 2852 2853 // Allocate the initialized struct on the heap. 2854 constructor = Expression::make_heap_expression(constructor, location); 2855 if ((Node::make_node(this)->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE) 2856 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 Expression* param = constructor; 2862 if (!is_constant_function && this->classification() == STATEMENT_GO) 2863 { 2864 fn = Expression::make_temporary_reference(fn_temp, location); 2865 Expression* nil = Expression::make_nil(location); 2866 Expression* isnil = Expression::make_binary(OPERATOR_EQEQ, fn, nil, 2867 location); 2868 Expression* crash = Runtime::make_call(gogo, Runtime::PANIC_GO_NIL, 2869 location, 0); 2870 crash = Expression::make_conditional(isnil, crash, 2871 Expression::make_nil(location), 2872 location); 2873 param = Expression::make_compound(crash, constructor, location); 2874 } 2875 2876 // Look up the thunk. 2877 Named_object* named_thunk = gogo->lookup(thunk_name, NULL); 2878 go_assert(named_thunk != NULL && named_thunk->is_function()); 2879 2880 // Build the call. 2881 Expression* func = Expression::make_func_reference(named_thunk, NULL, 2882 location); 2883 Expression_list* params = new Expression_list(); 2884 params->push_back(param); 2885 Call_expression* call = Expression::make_call(func, params, false, location); 2886 2887 // Build the simple go or defer statement. 2888 Statement* s; 2889 if (this->classification() == STATEMENT_GO) 2890 s = Statement::make_go_statement(call, location); 2891 else if (this->classification() == STATEMENT_DEFER) 2892 { 2893 s = Statement::make_defer_statement(call, location); 2894 if ((Node::make_node(this)->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE) 2895 s->defer_statement()->set_on_stack(); 2896 } 2897 else 2898 go_unreachable(); 2899 2900 // The current block should end with the go statement. 2901 go_assert(block->statements()->size() >= 1); 2902 go_assert(block->statements()->back() == this); 2903 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 s->determine_types(gogo); 2908 2909 // Sanity check. 2910 gogo->check_types_in_block(block); 2911 2912 // Return true to tell the block not to keep looking at statements. 2913 return true; 2914 } 2915 2916 // Set the name to use for thunk parameter N. 2917 2918 void 2919 Thunk_statement::thunk_field_param(int n, char* buf, size_t buflen) 2920 { 2921 snprintf(buf, buflen, "a%d", n); 2922 } 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 Thunk_statement::build_struct(Function_type* fntype) 2929 { 2930 Location location = this->location(); 2931 2932 Struct_field_list* fields = new Struct_field_list(); 2933 2934 Call_expression* ce = this->call_->call_expression(); 2935 Expression* fn = ce->fn(); 2936 2937 if (!this->is_constant_function()) 2938 { 2939 // The function to call. 2940 fields->push_back(Struct_field(Typed_identifier("fn", fntype, 2941 location))); 2942 } 2943 2944 // If this thunk statement calls a method on an interface, we pass 2945 // the interface object to the thunk. 2946 Interface_field_reference_expression* interface_method = 2947 fn->interface_field_reference_expression(); 2948 if (interface_method != NULL) 2949 { 2950 Typed_identifier tid("object", interface_method->expr()->type(), 2951 location); 2952 fields->push_back(Struct_field(tid)); 2953 } 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 Bound_method_expression* bme = fn->bound_method_expression(); 2959 if (bme != NULL) 2960 { 2961 Typed_identifier tid("object", bme->first_argument()->type(), location); 2962 fields->push_back(Struct_field(tid)); 2963 } 2964 2965 const Expression_list* args = ce->args(); 2966 if (args != NULL) 2967 { 2968 int i = 0; 2969 for (Expression_list::const_iterator p = args->begin(); 2970 p != args->end(); 2971 ++p, ++i) 2972 { 2973 if ((*p)->is_constant()) 2974 continue; 2975 2976 char buf[50]; 2977 this->thunk_field_param(i, buf, sizeof buf); 2978 fields->push_back(Struct_field(Typed_identifier(buf, (*p)->type(), 2979 location))); 2980 } 2981 } 2982 2983 Struct_type *st = Type::make_struct_type(fields, location); 2984 st->set_is_struct_incomparable(); 2985 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 Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name, 2993 Struct_type* struct_type) 2994 { 2995 Location location = this->location(); 2996 2997 Call_expression* ce = this->call_->call_expression(); 2998 2999 bool may_call_recover = false; 3000 if (this->classification() == STATEMENT_DEFER) 3001 { 3002 Func_expression* fn = ce->fn()->func_expression(); 3003 if (fn == NULL) 3004 may_call_recover = true; 3005 else 3006 { 3007 const Named_object* no = fn->named_object(); 3008 if (!no->is_function()) 3009 may_call_recover = true; 3010 else 3011 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 const char* const parameter_name = "__go_thunk_parameter"; 3018 Typed_identifier_list* thunk_parameters = new Typed_identifier_list(); 3019 Type* pointer_to_struct_type = Type::make_pointer_type(struct_type); 3020 thunk_parameters->push_back(Typed_identifier(parameter_name, 3021 pointer_to_struct_type, 3022 location)); 3023 3024 Typed_identifier_list* thunk_results = NULL; 3025 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 thunk_results = new Typed_identifier_list(); 3031 thunk_results->push_back(Typed_identifier("", Type::lookup_bool_type(), 3032 location)); 3033 } 3034 3035 Function_type* thunk_type = Type::make_function_type(NULL, thunk_parameters, 3036 thunk_results, 3037 location); 3038 3039 // Start building the thunk. 3040 Named_object* function = gogo->start_function(thunk_name, thunk_type, true, 3041 location); 3042 3043 gogo->start_block(location); 3044 3045 // For a defer statement, start with a call to 3046 // __go_set_defer_retaddr. */ 3047 Label* retaddr_label = NULL; 3048 if (may_call_recover) 3049 { 3050 retaddr_label = gogo->add_label_reference("retaddr", location, false); 3051 Expression* arg = Expression::make_label_addr(retaddr_label, location); 3052 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 gogo->start_block(location); 3058 gogo->add_statement(Statement::make_goto_statement(retaddr_label, 3059 location)); 3060 Block* then_block = gogo->finish_block(location); 3061 then_block->determine_types(gogo); 3062 3063 Statement* s = Statement::make_if_statement(call, then_block, NULL, 3064 location); 3065 s->determine_types(gogo); 3066 gogo->add_statement(s); 3067 3068 function->func_value()->set_calls_defer_retaddr(); 3069 } 3070 3071 // Get a reference to the parameter. 3072 Named_object* named_parameter = gogo->lookup(parameter_name, NULL); 3073 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 Expression* thunk_parameter = Expression::make_var_reference(named_parameter, 3078 location); 3079 thunk_parameter = 3080 Expression::make_dereference(thunk_parameter, 3081 Expression::NIL_CHECK_NOT_NEEDED, 3082 location); 3083 3084 Interface_field_reference_expression* interface_method = 3085 ce->fn()->interface_field_reference_expression(); 3086 Bound_method_expression* bme = ce->fn()->bound_method_expression(); 3087 3088 Expression* func_to_call; 3089 unsigned int next_index; 3090 if (this->is_constant_function()) 3091 { 3092 func_to_call = ce->fn(); 3093 next_index = 0; 3094 } 3095 else 3096 { 3097 func_to_call = Expression::make_field_reference(thunk_parameter, 3098 0, location); 3099 next_index = 1; 3100 } 3101 3102 if (interface_method != NULL) 3103 { 3104 // The main program passes the interface object. 3105 go_assert(next_index == 0); 3106 Expression* r = Expression::make_field_reference(thunk_parameter, 0, 3107 location); 3108 const std::string& name(interface_method->name()); 3109 func_to_call = Expression::make_interface_field_reference(r, name, 3110 location); 3111 next_index = 1; 3112 } 3113 3114 if (bme != NULL) 3115 { 3116 // This is a call to a method. 3117 go_assert(next_index == 0); 3118 Expression* r = Expression::make_field_reference(thunk_parameter, 0, 3119 location); 3120 func_to_call = Expression::make_bound_method(r, bme->method(), 3121 bme->function(), location); 3122 next_index = 1; 3123 } 3124 3125 Expression_list* call_params = new Expression_list(); 3126 const Struct_field_list* fields = struct_type->fields(); 3127 Struct_field_list::const_iterator p = fields->begin(); 3128 for (unsigned int i = 0; i < next_index; ++i) 3129 ++p; 3130 bool is_recover_call = ce->is_recover_call(); 3131 Expression* recover_arg = NULL; 3132 3133 const Expression_list* args = ce->args(); 3134 if (args != NULL) 3135 { 3136 for (Expression_list::const_iterator arg = args->begin(); 3137 arg != args->end(); 3138 ++arg) 3139 { 3140 Expression* param; 3141 if ((*arg)->is_constant()) 3142 param = *arg; 3143 else 3144 { 3145 Expression* thunk_param = 3146 Expression::make_var_reference(named_parameter, location); 3147 thunk_param = 3148 Expression::make_dereference(thunk_param, 3149 Expression::NIL_CHECK_NOT_NEEDED, 3150 location); 3151 param = Expression::make_field_reference(thunk_param, 3152 next_index, 3153 location); 3154 ++next_index; 3155 } 3156 3157 if (!is_recover_call) 3158 call_params->push_back(param); 3159 else 3160 { 3161 go_assert(call_params->empty()); 3162 recover_arg = param; 3163 } 3164 } 3165 } 3166 3167 if (call_params->empty()) 3168 { 3169 delete call_params; 3170 call_params = NULL; 3171 } 3172 3173 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 call->set_varargs_are_lowered(); 3181 3182 Statement* call_statement = Statement::make_statement(call, true); 3183 3184 call_statement->determine_types(gogo); 3185 gogo->add_statement(call_statement); 3186 3187 // If this is a defer statement, the label comes immediately after 3188 // the call. 3189 if (may_call_recover) 3190 { 3191 gogo->add_label_definition("retaddr", location); 3192 3193 Expression_list* vals = new Expression_list(); 3194 vals->push_back(Expression::make_boolean(false, location)); 3195 Statement* s = Statement::make_return_statement(function, vals, 3196 location); 3197 s->determine_types(gogo); 3198 gogo->add_statement(s); 3199 } 3200 3201 Block* b = gogo->finish_block(location); 3202 3203 gogo->add_block(b, location); 3204 3205 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 call_statement->determine_types(gogo); 3210 3211 gogo->add_conversions_in_block(b); 3212 3213 if (may_call_recover 3214 || recover_arg != NULL 3215 || this->classification() == STATEMENT_GO) 3216 { 3217 // Dig up the call expression, which may have been changed 3218 // during lowering. 3219 go_assert(call_statement->classification() == STATEMENT_EXPRESSION); 3220 Expression_statement* es = 3221 static_cast<Expression_statement*>(call_statement); 3222 ce = es->expr()->call_expression(); 3223 if (ce == NULL) 3224 go_assert(saw_errors()); 3225 else 3226 { 3227 if (may_call_recover) 3228 ce->set_is_deferred(); 3229 if (this->classification() == STATEMENT_GO) 3230 ce->set_is_concurrent(); 3231 if (recover_arg != NULL) 3232 ce->set_recover_arg(recover_arg); 3233 } 3234 } 3235 3236 gogo->flatten_block(function, b); 3237 3238 // That is all the thunk has to do. 3239 gogo->finish_function(location); 3240 } 3241 3242 // Get the function and argument expressions. 3243 3244 bool 3245 Thunk_statement::get_fn_and_arg(Expression** pfn, Expression** parg) 3246 { 3247 if (this->call_->is_error_expression()) 3248 return false; 3249 3250 Call_expression* ce = this->call_->call_expression(); 3251 3252 Expression* fn = ce->fn(); 3253 Func_expression* fe = fn->func_expression(); 3254 go_assert(fe != NULL); 3255 *pfn = Expression::make_func_code_reference(fe->named_object(), 3256 fe->location()); 3257 3258 const Expression_list* args = ce->args(); 3259 if (args == NULL || args->empty()) 3260 *parg = Expression::make_nil(this->location()); 3261 else 3262 { 3263 go_assert(args->size() == 1); 3264 *parg = args->front(); 3265 } 3266 3267 return true; 3268 } 3269 3270 // Class Go_statement. 3271 3272 Bstatement* 3273 Go_statement::do_get_backend(Translate_context* context) 3274 { 3275 Expression* fn; 3276 Expression* arg; 3277 if (!this->get_fn_and_arg(&fn, &arg)) 3278 return context->backend()->error_statement(); 3279 3280 Gogo* gogo = context->gogo(); 3281 Expression* call = Runtime::make_call(gogo, Runtime::GO, this->location(), 2, 3282 fn, arg); 3283 call->determine_type_no_context(gogo); 3284 Bexpression* bcall = call->get_backend(context); 3285 Bfunction* bfunction = context->function()->func_value()->get_decl(); 3286 return context->backend()->expression_statement(bfunction, bcall); 3287 } 3288 3289 // Dump the AST representation for go statement. 3290 3291 void 3292 Go_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 3293 { 3294 ast_dump_context->print_indent(); 3295 ast_dump_context->ostream() << "go "; 3296 ast_dump_context->dump_expression(this->call()); 3297 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 3298 } 3299 3300 // Make a go statement. 3301 3302 Statement* 3303 Statement::make_go_statement(Call_expression* call, Location location) 3304 { 3305 return new Go_statement(call, location); 3306 } 3307 3308 // Class Defer_statement. 3309 3310 Bstatement* 3311 Defer_statement::do_get_backend(Translate_context* context) 3312 { 3313 Expression* fn; 3314 Expression* arg; 3315 if (!this->get_fn_and_arg(&fn, &arg)) 3316 return context->backend()->error_statement(); 3317 3318 Gogo* gogo = context->gogo(); 3319 Location loc = this->location(); 3320 Expression* ds = context->function()->func_value()->defer_stack(loc); 3321 3322 Expression* call; 3323 if (this->on_stack_) 3324 { 3325 if (gogo->debug_optimization()) 3326 go_debug(loc, "stack allocated defer"); 3327 3328 Type* defer_type = Defer_statement::defer_struct_type(); 3329 Expression* defer = Expression::make_allocation(defer_type, loc); 3330 defer->allocation_expression()->set_allocate_on_stack(); 3331 defer->allocation_expression()->set_no_zero(); 3332 call = Runtime::make_call(gogo, Runtime::DEFERPROCSTACK, loc, 4, 3333 defer, ds, fn, arg); 3334 } 3335 else 3336 call = Runtime::make_call(gogo, Runtime::DEFERPROC, loc, 3, 3337 ds, fn, arg); 3338 call->determine_type_no_context(gogo); 3339 Bexpression* bcall = call->get_backend(context); 3340 Bfunction* bfunction = context->function()->func_value()->get_decl(); 3341 return context->backend()->expression_statement(bfunction, bcall); 3342 } 3343 3344 Type* 3345 Defer_statement::defer_struct_type() 3346 { 3347 Type* ptr_type = Type::make_pointer_type(Type::make_void_type()); 3348 Type* uintptr_type = Type::lookup_integer_type("uintptr"); 3349 Type* bool_type = Type::make_boolean_type(); 3350 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 "heap", bool_type); 3360 } 3361 3362 // Dump the AST representation for defer statement. 3363 3364 void 3365 Defer_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 3366 { 3367 ast_dump_context->print_indent(); 3368 ast_dump_context->ostream() << "defer "; 3369 ast_dump_context->dump_expression(this->call()); 3370 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 3371 } 3372 3373 // Make a defer statement. 3374 3375 Statement* 3376 Statement::make_defer_statement(Call_expression* call, 3377 Location location) 3378 { 3379 return new Defer_statement(call, location); 3380 } 3381 3382 // Class Return_statement. 3383 3384 void 3385 Return_statement::do_determine_types(Gogo* gogo) 3386 { 3387 if (this->types_are_determined_) 3388 return; 3389 this->types_are_determined_ = true; 3390 3391 size_t vals_count = this->vals_ == NULL ? 0 : this->vals_->size(); 3392 if (vals_count == 0) 3393 return; 3394 3395 Function::Results* results = 3396 this->function_->func_value()->result_variables(); 3397 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 if (results_count > 1 3402 && vals_count == 1 3403 && this->vals_->front()->call_expression() != NULL) 3404 { 3405 Call_expression* call = this->vals_->front()->call_expression(); 3406 call->set_expected_result_count(results_count); 3407 call->determine_type_no_context(gogo); 3408 delete this->vals_; 3409 this->vals_ = new Expression_list(); 3410 for (size_t i = 0; i < results_count; ++i) 3411 this->vals_->push_back(Expression::make_call_result(call, i)); 3412 vals_count = results_count; 3413 } 3414 3415 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 for (Expression_list::const_iterator pe = this->vals_->begin(); 3420 pe != this->vals_->end(); 3421 ++pe) 3422 (*pe)->determine_type_no_context(gogo); 3423 return; 3424 } 3425 3426 Expression_list::const_iterator pe = this->vals_->begin(); 3427 for (Function::Results::const_iterator pr = results->begin(); 3428 pr != results->end(); 3429 ++pr, ++pe) 3430 { 3431 Type* rvtype = (*pr)->result_var_value()->type(); 3432 Type_context context(rvtype, false); 3433 (*pe)->determine_type(gogo, &context); 3434 } 3435 } 3436 3437 void 3438 Return_statement::do_check_types(Gogo*) 3439 { 3440 size_t vals_count = this->vals_ == NULL ? 0 : this->vals_->size(); 3441 Function::Results* results = 3442 this->function_->func_value()->result_variables(); 3443 size_t results_count = results == NULL ? 0 : results->size(); 3444 3445 if (vals_count == 0) 3446 { 3447 if (results_count > 0 3448 && !this->function_->func_value()->results_are_named()) 3449 this->report_error(_("not enough arguments to return")); 3450 return; 3451 } 3452 3453 if (results_count == 0) 3454 { 3455 this->report_error(_("return with value in function " 3456 "with no return type")); 3457 delete this->vals_; 3458 this->vals_ = NULL; 3459 return; 3460 } 3461 3462 if (vals_count < results_count) 3463 { 3464 this->report_error(_("not enough arguments to return")); 3465 return; 3466 } 3467 3468 if (vals_count > results_count) 3469 { 3470 this->report_error(_("too many values in return statement")); 3471 return; 3472 } 3473 3474 Expression_list::const_iterator pe = this->vals_->begin(); 3475 int i = 1; 3476 for (Function::Results::const_iterator pr = results->begin(); 3477 pr != results->end(); 3478 ++pr, ++pe, ++i) 3479 { 3480 Named_object* rv = *pr; 3481 Expression* e = *pe; 3482 3483 std::string reason; 3484 if (!Type::are_assignable(rv->result_var_value()->type(), e->type(), 3485 &reason)) 3486 { 3487 if (reason.empty()) 3488 go_error_at(e->location(), 3489 "incompatible type for return value %d", i); 3490 else 3491 go_error_at(e->location(), 3492 "incompatible type for return value %d (%s)", 3493 i, reason.c_str()); 3494 this->set_is_error(); 3495 } 3496 } 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 Return_statement::do_lower(Gogo* gogo, Named_object*, 3508 Block* enclosing, Statement_inserter*) 3509 { 3510 Location loc = this->location(); 3511 3512 if (this->classification() == STATEMENT_ERROR) 3513 return Statement::make_error_statement(loc); 3514 3515 if (this->is_lowered_) 3516 return this; 3517 3518 Expression_list* vals = this->vals_; 3519 this->vals_ = NULL; 3520 this->is_lowered_ = true; 3521 3522 size_t vals_count = vals == NULL ? 0 : vals->size(); 3523 3524 if (vals_count == 0) 3525 return this; 3526 3527 Function::Results* results = 3528 this->function_->func_value()->result_variables(); 3529 size_t results_count = results == NULL ? 0 : results->size(); 3530 3531 go_assert(vals_count == results_count); 3532 3533 Block* b = new Block(enclosing, loc); 3534 3535 Expression_list* lhs = new Expression_list(); 3536 Expression_list* rhs = new Expression_list(); 3537 3538 Expression_list::const_iterator pe = vals->begin(); 3539 for (Function::Results::const_iterator pr = results->begin(); 3540 pr != results->end(); 3541 ++pr, ++pe) 3542 { 3543 Named_object* rv = *pr; 3544 Expression* e = *pe; 3545 Expression* ve = Expression::make_var_reference(rv, e->location()); 3546 lhs->push_back(ve); 3547 rhs->push_back(e); 3548 } 3549 3550 if (lhs->size() == 1) 3551 { 3552 Statement* s = Statement::make_assignment(lhs->front(), rhs->front(), 3553 loc); 3554 s->determine_types(gogo); 3555 b->add_statement(s); 3556 delete lhs; 3557 delete rhs; 3558 } 3559 else 3560 { 3561 Statement* s = Statement::make_tuple_assignment(lhs, rhs, loc); 3562 s->determine_types(gogo); 3563 b->add_statement(s); 3564 } 3565 3566 b->add_statement(this); 3567 3568 delete vals; 3569 3570 return Statement::make_block_statement(b, loc); 3571 } 3572 3573 // Convert a return statement to the backend representation. 3574 3575 Bstatement* 3576 Return_statement::do_get_backend(Translate_context* context) 3577 { 3578 Location loc = this->location(); 3579 3580 Function* function = context->function()->func_value(); 3581 Function::Results* results = function->result_variables(); 3582 std::vector<Bexpression*> retvals; 3583 if (results != NULL && !results->empty()) 3584 { 3585 retvals.reserve(results->size()); 3586 for (Function::Results::const_iterator p = results->begin(); 3587 p != results->end(); 3588 p++) 3589 { 3590 Expression* vr = Expression::make_var_reference(*p, loc); 3591 retvals.push_back(vr->get_backend(context)); 3592 } 3593 } 3594 3595 return context->backend()->return_statement(function->get_decl(), 3596 retvals, loc); 3597 } 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 Return_statement::do_export_statement(Export_function_body* efb) 3605 { 3606 efb->write_c_string("return"); 3607 } 3608 3609 // Dump the AST representation for a return statement. 3610 3611 void 3612 Return_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 3613 { 3614 ast_dump_context->print_indent(); 3615 ast_dump_context->ostream() << "return " ; 3616 ast_dump_context->dump_expression_list(this->vals_); 3617 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 3618 } 3619 3620 // Make a return statement. 3621 3622 Return_statement* 3623 Statement::make_return_statement(Named_object* function, Expression_list* vals, 3624 Location location) 3625 { 3626 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 Statement::make_return_from_call(Named_object* function, Call_expression* call, 3633 Location location) 3634 { 3635 size_t rc = call->result_count(); 3636 if (rc == 0) 3637 return Statement::make_statement(call, true); 3638 else 3639 { 3640 Expression_list* vals = new Expression_list(); 3641 if (rc == 1) 3642 vals->push_back(call); 3643 else 3644 { 3645 for (size_t i = 0; i < rc; ++i) 3646 vals->push_back(Expression::make_call_result(call, i)); 3647 } 3648 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 Bc_statement(bool is_break, Unnamed_label* label, Location location) 3658 : Statement(STATEMENT_BREAK_OR_CONTINUE, location), 3659 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 do_traverse(Traverse*) 3669 { return TRAVERSE_CONTINUE; } 3670 3671 bool 3672 do_may_fall_through() const 3673 { return false; } 3674 3675 Bstatement* 3676 do_get_backend(Translate_context* context) 3677 { 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 Bc_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 3693 { 3694 ast_dump_context->print_indent(); 3695 ast_dump_context->ostream() << (this->is_break_ ? "break" : "continue"); 3696 if (this->label_ != NULL) 3697 { 3698 ast_dump_context->ostream() << " "; 3699 ast_dump_context->dump_label_name(this->label_); 3700 } 3701 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 3702 } 3703 3704 // Make a break statement. 3705 3706 Statement* 3707 Statement::make_break_statement(Unnamed_label* label, Location location) 3708 { 3709 return new Bc_statement(true, label, location); 3710 } 3711 3712 // Make a continue statement. 3713 3714 Statement* 3715 Statement::make_continue_statement(Unnamed_label* label, 3716 Location location) 3717 { 3718 return new Bc_statement(false, label, location); 3719 } 3720 3721 // Class Goto_statement. 3722 3723 int 3724 Goto_statement::do_traverse(Traverse*) 3725 { 3726 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 Goto_statement::do_check_types(Gogo*) 3734 { 3735 if (!this->label_->is_defined()) 3736 { 3737 go_error_at(this->location(), "reference to undefined label %qs", 3738 Gogo::message_name(this->label_->name()).c_str()); 3739 this->set_is_error(); 3740 } 3741 } 3742 3743 // Convert the goto statement to the backend representation. 3744 3745 Bstatement* 3746 Goto_statement::do_get_backend(Translate_context* context) 3747 { 3748 Blabel* blabel = this->label_->get_backend_label(context); 3749 return context->backend()->goto_statement(blabel, this->location()); 3750 } 3751 3752 // Export a goto statement. 3753 3754 void 3755 Goto_statement::do_export_statement(Export_function_body *efb) 3756 { 3757 efb->write_c_string("goto "); 3758 efb->write_string(this->label_->name()); 3759 } 3760 3761 // Import a goto or goto unnamed statement. 3762 3763 Statement* 3764 Goto_statement::do_import(Import_function_body* ifb, Location loc) 3765 { 3766 ifb->require_c_string("goto "); 3767 std::string id = ifb->read_identifier(); 3768 if (id[0] != '$') 3769 { 3770 Function* fn = ifb->function()->func_value(); 3771 Label* label = fn->add_label_reference(ifb->gogo(), id, loc, false); 3772 return Statement::make_goto_statement(label, loc); 3773 } 3774 else 3775 { 3776 if (id[1] != 'l') 3777 { 3778 if (!ifb->saw_error()) 3779 go_error_at(loc, 3780 ("invalid export data for %qs: " 3781 "bad unnamed label at %lu"), 3782 ifb->name().c_str(), 3783 static_cast<unsigned long>(ifb->off())); 3784 ifb->set_saw_error(); 3785 return Statement::make_error_statement(loc); 3786 } 3787 const char* p = id.c_str(); 3788 char* end; 3789 long idx = strtol(p + 2, &end, 10); 3790 if (*end != '\0' || idx > 0x7fffffff) 3791 { 3792 if (!ifb->saw_error()) 3793 go_error_at(loc, 3794 ("invalid export data for %qs: " 3795 "bad unnamed label index at %lu"), 3796 ifb->name().c_str(), 3797 static_cast<unsigned long>(ifb->off())); 3798 ifb->set_saw_error(); 3799 return Statement::make_error_statement(loc); 3800 } 3801 3802 Unnamed_label* label = ifb->unnamed_label(idx, loc); 3803 return Statement::make_goto_unnamed_statement(label, loc); 3804 } 3805 } 3806 3807 // Dump the AST representation for a goto statement. 3808 3809 void 3810 Goto_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 3811 { 3812 ast_dump_context->print_indent(); 3813 ast_dump_context->ostream() << "goto " << this->label_->name() << dsuffix(location()) << std::endl; 3814 } 3815 3816 // Make a goto statement. 3817 3818 Statement* 3819 Statement::make_goto_statement(Label* label, Location location) 3820 { 3821 return new Goto_statement(label, location); 3822 } 3823 3824 // Class Goto_unnamed_statement. 3825 3826 int 3827 Goto_unnamed_statement::do_traverse(Traverse*) 3828 { 3829 return TRAVERSE_CONTINUE; 3830 } 3831 3832 // Convert the goto unnamed statement to the backend representation. 3833 3834 Bstatement* 3835 Goto_unnamed_statement::do_get_backend(Translate_context* context) 3836 { 3837 return this->label_->get_goto(context, this->location()); 3838 } 3839 3840 // Export a goto unnamed statement. 3841 3842 void 3843 Goto_unnamed_statement::do_export_statement(Export_function_body *efb) 3844 { 3845 unsigned int index = efb->unnamed_label_index(this->label_); 3846 char buf[100]; 3847 snprintf(buf, sizeof buf, "goto $l%u", index); 3848 efb->write_c_string(buf); 3849 } 3850 3851 // Dump the AST representation for an unnamed goto statement 3852 3853 void 3854 Goto_unnamed_statement::do_dump_statement( 3855 Ast_dump_context* ast_dump_context) const 3856 { 3857 ast_dump_context->print_indent(); 3858 ast_dump_context->ostream() << "goto "; 3859 ast_dump_context->dump_label_name(this->label_); 3860 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 3861 } 3862 3863 // Make a goto statement to an unnamed label. 3864 3865 Statement* 3866 Statement::make_goto_unnamed_statement(Unnamed_label* label, 3867 Location location) 3868 { 3869 return new Goto_unnamed_statement(label, location); 3870 } 3871 3872 // Class Label_statement. 3873 3874 // Traversal. 3875 3876 int 3877 Label_statement::do_traverse(Traverse*) 3878 { 3879 return TRAVERSE_CONTINUE; 3880 } 3881 3882 // Return the backend representation of the statement defining this 3883 // label. 3884 3885 Bstatement* 3886 Label_statement::do_get_backend(Translate_context* context) 3887 { 3888 if (this->label_->is_dummy_label()) 3889 { 3890 Bexpression* bce = context->backend()->boolean_constant_expression(false); 3891 Bfunction* bfunction = context->function()->func_value()->get_decl(); 3892 return context->backend()->expression_statement(bfunction, bce); 3893 } 3894 Blabel* blabel = this->label_->get_backend_label(context); 3895 return context->backend()->label_definition_statement(blabel); 3896 } 3897 3898 // Export a label. 3899 3900 void 3901 Label_statement::do_export_statement(Export_function_body* efb) 3902 { 3903 if (this->label_->is_dummy_label()) 3904 return; 3905 // We use a leading colon, not a trailing one, to simplify import. 3906 efb->write_c_string(":"); 3907 efb->write_string(this->label_->name()); 3908 } 3909 3910 // Import a label or an unnamed label. 3911 3912 Statement* 3913 Label_statement::do_import(Import_function_body* ifb, Location loc) 3914 { 3915 ifb->require_c_string(":"); 3916 std::string id = ifb->read_identifier(); 3917 if (id[0] != '$') 3918 { 3919 Function* fn = ifb->function()->func_value(); 3920 Label* label = fn->add_label_definition(ifb->gogo(), id, loc); 3921 return Statement::make_label_statement(label, loc); 3922 } 3923 else 3924 { 3925 if (id[1] != 'l') 3926 { 3927 if (!ifb->saw_error()) 3928 go_error_at(loc, 3929 ("invalid export data for %qs: " 3930 "bad unnamed label at %lu"), 3931 ifb->name().c_str(), 3932 static_cast<unsigned long>(ifb->off())); 3933 ifb->set_saw_error(); 3934 return Statement::make_error_statement(loc); 3935 } 3936 const char* p = id.c_str(); 3937 char* end; 3938 long idx = strtol(p + 2, &end, 10); 3939 if (*end != '\0' || idx > 0x7fffffff) 3940 { 3941 if (!ifb->saw_error()) 3942 go_error_at(loc, 3943 ("invalid export data for %qs: " 3944 "bad unnamed label index at %lu"), 3945 ifb->name().c_str(), 3946 static_cast<unsigned long>(ifb->off())); 3947 ifb->set_saw_error(); 3948 return Statement::make_error_statement(loc); 3949 } 3950 3951 Unnamed_label* label = ifb->unnamed_label(idx, loc); 3952 return Statement::make_unnamed_label_statement(label); 3953 } 3954 } 3955 3956 // Dump the AST for a label definition statement. 3957 3958 void 3959 Label_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 3960 { 3961 ast_dump_context->print_indent(); 3962 ast_dump_context->ostream() << this->label_->name() << ":" << dsuffix(location()) << std::endl; 3963 } 3964 3965 // Make a label statement. 3966 3967 Statement* 3968 Statement::make_label_statement(Label* label, Location location) 3969 { 3970 return new Label_statement(label, location); 3971 } 3972 3973 // Class Unnamed_label_statement. 3974 3975 Unnamed_label_statement::Unnamed_label_statement(Unnamed_label* label) 3976 : Statement(STATEMENT_UNNAMED_LABEL, label->location()), 3977 label_(label) 3978 { } 3979 3980 int 3981 Unnamed_label_statement::do_traverse(Traverse*) 3982 { 3983 return TRAVERSE_CONTINUE; 3984 } 3985 3986 // Get the backend definition for this unnamed label statement. 3987 3988 Bstatement* 3989 Unnamed_label_statement::do_get_backend(Translate_context* context) 3990 { 3991 return this->label_->get_definition(context); 3992 } 3993 3994 // Export an unnamed label. 3995 3996 void 3997 Unnamed_label_statement::do_export_statement(Export_function_body* efb) 3998 { 3999 unsigned int index = efb->unnamed_label_index(this->label_); 4000 char buf[50]; 4001 // We use a leading colon, not a trailing one, to simplify import. 4002 snprintf(buf, sizeof buf, ":$l%u", index); 4003 efb->write_c_string(buf); 4004 } 4005 4006 // Dump the AST representation for an unnamed label definition statement. 4007 4008 void 4009 Unnamed_label_statement::do_dump_statement(Ast_dump_context* ast_dump_context) 4010 const 4011 { 4012 ast_dump_context->print_indent(); 4013 ast_dump_context->dump_label_name(this->label_); 4014 ast_dump_context->ostream() << ":" << dsuffix(location()) << std::endl; 4015 } 4016 4017 // Make an unnamed label statement. 4018 4019 Statement* 4020 Statement::make_unnamed_label_statement(Unnamed_label* label) 4021 { 4022 return new Unnamed_label_statement(label); 4023 } 4024 4025 // Class If_statement. 4026 4027 // Traversal. 4028 4029 int 4030 If_statement::do_traverse(Traverse* traverse) 4031 { 4032 if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT 4033 || this->then_block_->traverse(traverse) == TRAVERSE_EXIT) 4034 return TRAVERSE_EXIT; 4035 if (this->else_block_ != NULL) 4036 { 4037 if (this->else_block_->traverse(traverse) == TRAVERSE_EXIT) 4038 return TRAVERSE_EXIT; 4039 } 4040 return TRAVERSE_CONTINUE; 4041 } 4042 4043 void 4044 If_statement::do_determine_types(Gogo* gogo) 4045 { 4046 Type_context context(Type::lookup_bool_type(), false); 4047 this->cond_->determine_type(gogo, &context); 4048 this->then_block_->determine_types(gogo); 4049 if (this->else_block_ != NULL) 4050 this->else_block_->determine_types(gogo); 4051 } 4052 4053 // Check types. 4054 4055 void 4056 If_statement::do_check_types(Gogo*) 4057 { 4058 Type* type = this->cond_->type(); 4059 if (type->is_error()) 4060 this->set_is_error(); 4061 else if (!type->is_boolean_type()) 4062 this->report_error(_("expected boolean expression")); 4063 } 4064 4065 // Whether the overall statement may fall through. 4066 4067 bool 4068 If_statement::do_may_fall_through() const 4069 { 4070 return (this->else_block_ == NULL 4071 || this->then_block_->may_fall_through() 4072 || this->else_block_->may_fall_through()); 4073 } 4074 4075 // Get the backend representation. 4076 4077 Bstatement* 4078 If_statement::do_get_backend(Translate_context* context) 4079 { 4080 go_assert(this->cond_->type()->is_boolean_type() 4081 || this->cond_->type()->is_error()); 4082 Bexpression* cond = this->cond_->get_backend(context); 4083 Bblock* then_block = this->then_block_->get_backend(context); 4084 Bblock* else_block = (this->else_block_ == NULL 4085 ? NULL 4086 : this->else_block_->get_backend(context)); 4087 Bfunction* bfunction = context->function()->func_value()->get_decl(); 4088 return context->backend()->if_statement(bfunction, 4089 cond, then_block, else_block, 4090 this->location()); 4091 } 4092 4093 // Export an if statement. 4094 4095 void 4096 If_statement::do_export_statement(Export_function_body* efb) 4097 { 4098 efb->write_c_string("if "); 4099 this->cond_->export_expression(efb); 4100 efb->write_c_string(" "); 4101 Block_statement::export_block(efb, this->then_block_, false); 4102 if (this->else_block_ != NULL) 4103 { 4104 efb->write_c_string(" else "); 4105 Block_statement::export_block(efb, this->else_block_, false); 4106 } 4107 } 4108 4109 // Import an if statement. 4110 4111 Statement* 4112 If_statement::do_import(Import_function_body* ifb, Location loc) 4113 { 4114 ifb->require_c_string("if "); 4115 4116 Expression* cond = Expression::import_expression(ifb, loc); 4117 ifb->require_c_string(" "); 4118 4119 if (!ifb->match_c_string("{")) 4120 { 4121 if (!ifb->saw_error()) 4122 go_error_at(ifb->location(), 4123 "import error for %qs: no block for if statement at %lu", 4124 ifb->name().c_str(), 4125 static_cast<unsigned long>(ifb->off())); 4126 ifb->set_saw_error(); 4127 return Statement::make_error_statement(loc); 4128 } 4129 4130 bool is_lowered_for_statement; 4131 Block* then_block = Block_statement::do_import(ifb, loc, 4132 &is_lowered_for_statement); 4133 if (then_block == NULL) 4134 return Statement::make_error_statement(loc); 4135 if (is_lowered_for_statement) 4136 { 4137 if (!ifb->saw_error()) 4138 go_error_at(ifb->location(), 4139 ("import error for %qs: " 4140 "unexpected lowered for in if statement at %lu"), 4141 ifb->name().c_str(), 4142 static_cast<unsigned long>(ifb->off())); 4143 ifb->set_saw_error(); 4144 return Statement::make_error_statement(loc); 4145 } 4146 4147 Block* else_block = NULL; 4148 if (ifb->match_c_string(" else ")) 4149 { 4150 ifb->advance(6); 4151 if (!ifb->match_c_string("{")) 4152 { 4153 if (!ifb->saw_error()) 4154 go_error_at(ifb->location(), 4155 ("import error for %qs: no else block " 4156 "for if statement at %lu"), 4157 ifb->name().c_str(), 4158 static_cast<unsigned long>(ifb->off())); 4159 ifb->set_saw_error(); 4160 return Statement::make_error_statement(loc); 4161 } 4162 4163 else_block = Block_statement::do_import(ifb, loc, 4164 &is_lowered_for_statement); 4165 if (else_block == NULL) 4166 return Statement::make_error_statement(loc); 4167 if (is_lowered_for_statement) 4168 { 4169 if (!ifb->saw_error()) 4170 go_error_at(ifb->location(), 4171 ("import error for %qs: " 4172 "unexpected lowered for in if statement at %lu"), 4173 ifb->name().c_str(), 4174 static_cast<unsigned long>(ifb->off())); 4175 ifb->set_saw_error(); 4176 return Statement::make_error_statement(loc); 4177 } 4178 } 4179 4180 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 If_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 4187 { 4188 ast_dump_context->print_indent(); 4189 ast_dump_context->ostream() << "if "; 4190 ast_dump_context->dump_expression(this->cond_); 4191 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 4192 if (ast_dump_context->dump_subblocks()) 4193 { 4194 ast_dump_context->dump_block(this->then_block_); 4195 if (this->else_block_ != NULL) 4196 { 4197 ast_dump_context->print_indent(); 4198 ast_dump_context->ostream() << "else" << std::endl; 4199 ast_dump_context->dump_block(this->else_block_); 4200 } 4201 } 4202 } 4203 4204 // Make an if statement. 4205 4206 Statement* 4207 Statement::make_if_statement(Expression* cond, Block* then_block, 4208 Block* else_block, Location location) 4209 { 4210 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 Case_clauses::Hash_integer_value::operator()(Expression* pe) const 4224 { 4225 Numeric_constant nc; 4226 mpz_t ival; 4227 if (!pe->numeric_constant_value(&nc) || !nc.to_int(&ival)) 4228 go_unreachable(); 4229 size_t ret = mpz_get_ui(ival); 4230 mpz_clear(ival); 4231 return ret; 4232 } 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 Case_clauses::Eq_integer_value::operator()(Expression* a, Expression* b) const 4245 { 4246 Numeric_constant anc; 4247 mpz_t aval; 4248 Numeric_constant bnc; 4249 mpz_t bval; 4250 if (!a->numeric_constant_value(&anc) 4251 || !anc.to_int(&aval) 4252 || !b->numeric_constant_value(&bnc) 4253 || !bnc.to_int(&bval)) 4254 go_unreachable(); 4255 bool ret = mpz_cmp(aval, bval) == 0; 4256 mpz_clear(aval); 4257 mpz_clear(bval); 4258 return ret; 4259 } 4260 4261 // Class Case_clauses::Case_clause. 4262 4263 // Traversal. 4264 4265 int 4266 Case_clauses::Case_clause::traverse(Traverse* traverse) 4267 { 4268 if (this->cases_ != NULL 4269 && (traverse->traverse_mask() 4270 & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0) 4271 { 4272 if (this->cases_->traverse(traverse) == TRAVERSE_EXIT) 4273 return TRAVERSE_EXIT; 4274 } 4275 if (this->statements_ != NULL) 4276 { 4277 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 Case_clauses::Case_clause::is_constant() const 4287 { 4288 if (this->cases_ != NULL) 4289 { 4290 for (Expression_list::const_iterator p = this->cases_->begin(); 4291 p != this->cases_->end(); 4292 ++p) 4293 if (!(*p)->is_constant() || (*p)->type()->integer_type() == NULL) 4294 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 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 Location loc = this->location_; 4311 Unnamed_label* next_case_label; 4312 if (this->cases_ == NULL || this->cases_->empty()) 4313 { 4314 go_assert(this->is_default_); 4315 next_case_label = NULL; 4316 } 4317 else 4318 { 4319 Expression* cond = NULL; 4320 4321 for (Expression_list::const_iterator p = this->cases_->begin(); 4322 p != this->cases_->end(); 4323 ++p) 4324 { 4325 Expression* ref = Expression::make_temporary_reference(val_temp, 4326 loc); 4327 Expression* this_cond = Expression::make_binary(OPERATOR_EQEQ, ref, 4328 *p, loc); 4329 if (cond == NULL) 4330 cond = this_cond; 4331 else 4332 cond = Expression::make_binary(OPERATOR_OROR, cond, this_cond, loc); 4333 } 4334 4335 Block* then_block = new Block(b, loc); 4336 next_case_label = new Unnamed_label(Linemap::unknown_location()); 4337 Statement* s = Statement::make_goto_unnamed_statement(next_case_label, 4338 loc); 4339 then_block->add_statement(s); 4340 4341 // if !COND { goto NEXT_CASE_LABEL } 4342 cond = Expression::make_unary(OPERATOR_NOT, cond, loc); 4343 s = Statement::make_if_statement(cond, then_block, NULL, loc); 4344 s->determine_types(gogo); 4345 b->add_statement(s); 4346 } 4347 4348 if (start_label != NULL) 4349 b->add_statement(Statement::make_unnamed_label_statement(start_label)); 4350 4351 if (this->statements_ != NULL) 4352 b->add_statement(Statement::make_block_statement(this->statements_, loc)); 4353 4354 Statement* s = Statement::make_goto_unnamed_statement(finish_label, loc); 4355 b->add_statement(s); 4356 4357 if (next_case_label != NULL) 4358 b->add_statement(Statement::make_unnamed_label_statement(next_case_label)); 4359 } 4360 4361 // Determine types. 4362 4363 void 4364 Case_clauses::Case_clause::determine_types(Gogo* gogo, Type* type) 4365 { 4366 if (this->cases_ != NULL) 4367 { 4368 Type_context case_context(type, false); 4369 for (Expression_list::iterator p = this->cases_->begin(); 4370 p != this->cases_->end(); 4371 ++p) 4372 (*p)->determine_type(gogo, &case_context); 4373 } 4374 if (this->statements_ != NULL) 4375 this->statements_->determine_types(gogo); 4376 } 4377 4378 // Check types. Returns false if there was an error. 4379 4380 bool 4381 Case_clauses::Case_clause::check_types(Type* type) 4382 { 4383 if (this->cases_ != NULL) 4384 { 4385 for (Expression_list::iterator p = this->cases_->begin(); 4386 p != this->cases_->end(); 4387 ++p) 4388 { 4389 std::string reason; 4390 if (!Type::are_compatible_for_comparison(true, type, (*p)->type(), 4391 &reason)) 4392 { 4393 go_error_at(this->location_, "%s", reason.c_str()); 4394 return false; 4395 } 4396 } 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 Case_clauses::Case_clause::may_fall_through() const 4407 { 4408 if (this->statements_ == NULL) 4409 return true; 4410 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 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 if (this->cases_ != NULL) 4428 { 4429 go_assert(!this->is_default_); 4430 for (Expression_list::const_iterator p = this->cases_->begin(); 4431 p != this->cases_->end(); 4432 ++p) 4433 { 4434 Expression* e = *p; 4435 if (e->classification() != Expression::EXPRESSION_INTEGER) 4436 { 4437 Numeric_constant nc; 4438 mpz_t ival; 4439 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 go_assert(saw_errors()); 4444 continue; 4445 } 4446 go_assert(nc.type() != NULL); 4447 e = Expression::make_integer_z(&ival, nc.type(), e->location()); 4448 mpz_clear(ival); 4449 } 4450 4451 std::pair<Case_constants::iterator, bool> ins = 4452 case_constants->insert(e); 4453 if (!ins.second) 4454 { 4455 // Value was already present. 4456 go_error_at(this->location_, "duplicate case in switch"); 4457 e = Expression::make_error(this->location_); 4458 } 4459 cases->push_back(e->get_backend(context)); 4460 } 4461 } 4462 4463 Bstatement* statements; 4464 if (this->statements_ == NULL) 4465 statements = NULL; 4466 else 4467 { 4468 Bblock* bblock = this->statements_->get_backend(context); 4469 statements = context->backend()->block_statement(bblock); 4470 } 4471 4472 Bstatement* break_stat; 4473 if (this->is_fallthrough_) 4474 break_stat = NULL; 4475 else 4476 break_stat = break_label->get_goto(context, this->location_); 4477 4478 if (statements == NULL) 4479 return break_stat; 4480 else if (break_stat == NULL) 4481 return statements; 4482 else 4483 return context->backend()->compound_statement(statements, break_stat); 4484 } 4485 4486 // Dump the AST representation for a case clause 4487 4488 void 4489 Case_clauses::Case_clause::dump_clause(Ast_dump_context* ast_dump_context) 4490 const 4491 { 4492 ast_dump_context->print_indent(); 4493 if (this->is_default_) 4494 { 4495 ast_dump_context->ostream() << "default:"; 4496 } 4497 else 4498 { 4499 ast_dump_context->ostream() << "case "; 4500 ast_dump_context->dump_expression_list(this->cases_); 4501 ast_dump_context->ostream() << ":" ; 4502 } 4503 ast_dump_context->dump_block(this->statements_); 4504 if (this->is_fallthrough_) 4505 { 4506 ast_dump_context->print_indent(); 4507 ast_dump_context->ostream() << " (fallthrough)" << dsuffix(location()) << std::endl; 4508 } 4509 } 4510 4511 // Class Case_clauses. 4512 4513 // Traversal. 4514 4515 int 4516 Case_clauses::traverse(Traverse* traverse) 4517 { 4518 for (Clauses::iterator p = this->clauses_.begin(); 4519 p != this->clauses_.end(); 4520 ++p) 4521 { 4522 if (p->traverse(traverse) == TRAVERSE_EXIT) 4523 return TRAVERSE_EXIT; 4524 } 4525 return TRAVERSE_CONTINUE; 4526 } 4527 4528 // Check whether all the case expressions are constant. 4529 4530 bool 4531 Case_clauses::is_constant() const 4532 { 4533 for (Clauses::const_iterator p = this->clauses_.begin(); 4534 p != this->clauses_.end(); 4535 ++p) 4536 if (!p->is_constant()) 4537 return false; 4538 return true; 4539 } 4540 4541 // Lower case clauses for a nonconstant switch. 4542 4543 void 4544 Case_clauses::lower(Gogo* gogo, Block* b, Temporary_statement* val_temp, 4545 Unnamed_label* break_label) const 4546 { 4547 // The default case. 4548 const Case_clause* default_case = NULL; 4549 4550 // The label for the fallthrough of the previous case. 4551 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 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 Unnamed_label* default_finish_label = NULL; 4561 4562 for (Clauses::const_iterator p = this->clauses_.begin(); 4563 p != this->clauses_.end(); 4564 ++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 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 Unnamed_label* finish_label = break_label; 4573 4574 last_fallthrough_label = NULL; 4575 if (p->is_fallthrough() && p + 1 != this->clauses_.end()) 4576 { 4577 finish_label = new Unnamed_label(p->location()); 4578 last_fallthrough_label = finish_label; 4579 } 4580 4581 if (!p->is_default()) 4582 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 if (default_case != NULL) 4594 default_case->lower(gogo, b, val_temp, default_start_label, 4595 default_finish_label); 4596 } 4597 4598 // Determine types. 4599 4600 void 4601 Case_clauses::determine_types(Gogo* gogo, Type* type) 4602 { 4603 for (Clauses::iterator p = this->clauses_.begin(); 4604 p != this->clauses_.end(); 4605 ++p) 4606 p->determine_types(gogo, type); 4607 } 4608 4609 // Check types. Returns false if there was an error. 4610 4611 bool 4612 Case_clauses::check_types(Type* type) 4613 { 4614 bool ret = true; 4615 for (Clauses::iterator p = this->clauses_.begin(); 4616 p != this->clauses_.end(); 4617 ++p) 4618 { 4619 if (!p->check_types(type)) 4620 ret = false; 4621 } 4622 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 Case_clauses::may_fall_through() const 4630 { 4631 bool found_default = false; 4632 for (Clauses::const_iterator p = this->clauses_.begin(); 4633 p != this->clauses_.end(); 4634 ++p) 4635 { 4636 if (p->may_fall_through() && !p->is_fallthrough()) 4637 return true; 4638 if (p->is_default()) 4639 found_default = true; 4640 } 4641 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 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 Case_constants case_constants; 4654 4655 size_t c = this->clauses_.size(); 4656 all_cases->resize(c); 4657 all_statements->resize(c); 4658 4659 size_t i = 0; 4660 for (Clauses::const_iterator p = this->clauses_.begin(); 4661 p != this->clauses_.end(); 4662 ++p, ++i) 4663 { 4664 std::vector<Bexpression*> cases; 4665 Bstatement* stat = p->get_backend(context, break_label, &case_constants, 4666 &cases); 4667 // The final clause can't fall through. 4668 if (i == c - 1 && p->is_fallthrough()) 4669 { 4670 go_assert(saw_errors()); 4671 stat = context->backend()->error_statement(); 4672 } 4673 (*all_cases)[i].swap(cases); 4674 (*all_statements)[i] = stat; 4675 } 4676 } 4677 4678 // Dump the AST representation for case clauses (from a switch statement) 4679 4680 void 4681 Case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const 4682 { 4683 for (Clauses::const_iterator p = this->clauses_.begin(); 4684 p != this->clauses_.end(); 4685 ++p) 4686 p->dump_clause(ast_dump_context); 4687 } 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 Constant_switch_statement(Expression* val, Case_clauses* clauses, 4696 Unnamed_label* break_label, 4697 Location location) 4698 : Statement(STATEMENT_CONSTANT_SWITCH, location), 4699 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 Constant_switch_statement::do_traverse(Traverse* traverse) 4725 { 4726 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT) 4727 return TRAVERSE_EXIT; 4728 return this->clauses_->traverse(traverse); 4729 } 4730 4731 // Convert to GENERIC. 4732 4733 Bstatement* 4734 Constant_switch_statement::do_get_backend(Translate_context* context) 4735 { 4736 Bexpression* switch_val_expr = this->val_->get_backend(context); 4737 4738 Unnamed_label* break_label = this->break_label_; 4739 if (break_label == NULL) 4740 break_label = new Unnamed_label(this->location()); 4741 4742 std::vector<std::vector<Bexpression*> > all_cases; 4743 std::vector<Bstatement*> all_statements; 4744 this->clauses_->get_backend(context, break_label, &all_cases, 4745 &all_statements); 4746 4747 Bfunction* bfunction = context->function()->func_value()->get_decl(); 4748 Bstatement* switch_statement; 4749 switch_statement = context->backend()->switch_statement(bfunction, 4750 switch_val_expr, 4751 all_cases, 4752 all_statements, 4753 this->location()); 4754 Bstatement* ldef = break_label->get_definition(context); 4755 return context->backend()->compound_statement(switch_statement, ldef); 4756 } 4757 4758 // Dump the AST representation for a constant switch statement. 4759 4760 void 4761 Constant_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) 4762 const 4763 { 4764 ast_dump_context->print_indent(); 4765 ast_dump_context->ostream() << "switch "; 4766 ast_dump_context->dump_expression(this->val_); 4767 4768 if (ast_dump_context->dump_subblocks()) 4769 { 4770 ast_dump_context->ostream() << " {" << std::endl; 4771 this->clauses_->dump_clauses(ast_dump_context); 4772 ast_dump_context->ostream() << "}"; 4773 } 4774 4775 ast_dump_context->ostream() << std::endl; 4776 } 4777 4778 // Class Switch_statement. 4779 4780 // Traversal. 4781 4782 int 4783 Switch_statement::do_traverse(Traverse* traverse) 4784 { 4785 if (this->val_ != NULL) 4786 { 4787 if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT) 4788 return TRAVERSE_EXIT; 4789 } 4790 return this->clauses_->traverse(traverse); 4791 } 4792 4793 void 4794 Switch_statement::do_determine_types(Gogo* gogo) 4795 { 4796 if (this->val_ != NULL) 4797 this->val_->determine_type_no_context(gogo); 4798 this->clauses_->determine_types(gogo, 4799 (this->val_ == NULL 4800 ? NULL 4801 : this->val_->type())); 4802 } 4803 4804 void 4805 Switch_statement::do_check_types(Gogo*) 4806 { 4807 if (this->val_ != NULL 4808 && (this->val_->is_error_expression() 4809 || this->val_->type()->is_error())) 4810 return; 4811 4812 if (this->val_ != NULL 4813 && !this->val_->type()->is_comparable() 4814 && !Type::are_compatible_for_comparison(true, this->val_->type(), 4815 Type::make_nil_type(), NULL)) 4816 { 4817 go_error_at(this->val_->location(), 4818 "cannot switch on value whose type may not be compared"); 4819 this->set_is_error(); 4820 return; 4821 } 4822 4823 Type* type; 4824 if (this->val_ != NULL) 4825 type = this->val_->type(); 4826 else 4827 type = Type::make_boolean_type(); 4828 if (!this->clauses_->check_types(type)) 4829 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 Switch_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing, 4837 Statement_inserter*) 4838 { 4839 Location loc = this->location(); 4840 4841 if (this->val_ != NULL 4842 && (this->val_->is_error_expression() 4843 || this->val_->type()->is_error())) 4844 { 4845 go_assert(saw_errors()); 4846 return Statement::make_error_statement(loc); 4847 } 4848 4849 if (this->val_ != NULL 4850 && this->val_->type()->integer_type() != NULL 4851 && !this->clauses_->empty() 4852 && this->clauses_->is_constant()) 4853 return new Constant_switch_statement(this->val_, this->clauses_, 4854 this->break_label_, loc); 4855 4856 Block* b = new Block(enclosing, loc); 4857 4858 if (this->clauses_->empty()) 4859 { 4860 Expression* val = this->val_; 4861 if (val == NULL) 4862 val = Expression::make_boolean(true, loc); 4863 return Statement::make_statement(val, true); 4864 } 4865 4866 // var val_temp VAL_TYPE = VAL 4867 Expression* val = this->val_; 4868 if (val == NULL) 4869 val = Expression::make_boolean(true, loc); 4870 4871 Type* type = val->type(); 4872 if (type->is_abstract()) 4873 type = type->make_non_abstract_type(); 4874 Temporary_statement* val_temp = Statement::make_temporary(type, val, loc); 4875 b->add_statement(val_temp); 4876 4877 this->clauses_->lower(gogo, b, val_temp, this->break_label()); 4878 4879 Statement* s = Statement::make_unnamed_label_statement(this->break_label_); 4880 b->add_statement(s); 4881 4882 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 Switch_statement::break_label() 4890 { 4891 if (this->break_label_ == NULL) 4892 this->break_label_ = new Unnamed_label(this->location()); 4893 return this->break_label_; 4894 } 4895 4896 // Dump the AST representation for a switch statement. 4897 4898 void 4899 Switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 4900 { 4901 ast_dump_context->print_indent(); 4902 ast_dump_context->ostream() << "switch "; 4903 if (this->val_ != NULL) 4904 { 4905 ast_dump_context->dump_expression(this->val_); 4906 } 4907 if (ast_dump_context->dump_subblocks()) 4908 { 4909 ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl; 4910 this->clauses_->dump_clauses(ast_dump_context); 4911 ast_dump_context->print_indent(); 4912 ast_dump_context->ostream() << "}"; 4913 } 4914 ast_dump_context->ostream() << std::endl; 4915 } 4916 4917 // Return whether this switch may fall through. 4918 4919 bool 4920 Switch_statement::do_may_fall_through() const 4921 { 4922 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 if (this->break_label_ != NULL) 4928 return true; 4929 4930 return this->clauses_->may_fall_through(); 4931 } 4932 4933 // Make a switch statement. 4934 4935 Switch_statement* 4936 Statement::make_switch_statement(Expression* val, Location location) 4937 { 4938 return new Switch_statement(val, location); 4939 } 4940 4941 // Class Type_case_clauses::Type_case_clause. 4942 4943 // Traversal. 4944 4945 int 4946 Type_case_clauses::Type_case_clause::traverse(Traverse* traverse) 4947 { 4948 if (!this->is_default_ 4949 && ((traverse->traverse_mask() 4950 & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0) 4951 && Type::traverse(this->type_, traverse) == TRAVERSE_EXIT) 4952 return TRAVERSE_EXIT; 4953 if (this->statements_ != NULL) 4954 return this->statements_->traverse(traverse); 4955 return TRAVERSE_CONTINUE; 4956 } 4957 4958 void 4959 Type_case_clauses::Type_case_clause::determine_types(Gogo* gogo) 4960 { 4961 if (this->statements_ != NULL) 4962 this->statements_->determine_types(gogo); 4963 } 4964 4965 bool 4966 Type_case_clauses::Type_case_clause::check_types(Type* switch_val_type) 4967 { 4968 if (!this->is_default_) 4969 { 4970 Type* type = this->type_; 4971 std::string reason; 4972 if (switch_val_type->interface_type() != NULL 4973 && !type->is_nil_constant_as_type() 4974 && type->interface_type() == NULL 4975 && !switch_val_type->interface_type()->implements_interface(type, 4976 &reason)) 4977 { 4978 if (reason.empty()) 4979 go_error_at(this->location_, "impossible type switch case"); 4980 else 4981 go_error_at(this->location_, "impossible type switch case (%s)", 4982 reason.c_str()); 4983 return false; 4984 } 4985 } 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 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 Location loc = this->location_; 5003 5004 Unnamed_label* next_case_label = NULL; 5005 if (!this->is_default_) 5006 { 5007 Type* type = this->type_; 5008 5009 Expression* ref = Expression::make_temporary_reference(descriptor_temp, 5010 loc); 5011 5012 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 if (type->is_nil_constant_as_type()) 5017 cond = Expression::make_binary(OPERATOR_EQEQ, ref, 5018 Expression::make_nil(loc), 5019 loc); 5020 else if (type->interface_type() == NULL) 5021 { 5022 if (!gogo->need_eqtype()) 5023 cond = Expression::make_binary(OPERATOR_EQEQ, ref, 5024 Expression::make_type_descriptor(type, loc), 5025 loc); 5026 else 5027 cond = Runtime::make_call(gogo, Runtime::EQTYPE, loc, 2, 5028 Expression::make_type_descriptor(type, loc), 5029 ref); 5030 } 5031 else 5032 cond = Runtime::make_call(gogo, Runtime::IFACET2IP, loc, 2, 5033 Expression::make_type_descriptor(type, loc), 5034 ref); 5035 5036 Unnamed_label* dest; 5037 if (!this->is_fallthrough_) 5038 { 5039 // if !COND { goto NEXT_CASE_LABEL } 5040 next_case_label = new Unnamed_label(Linemap::unknown_location()); 5041 dest = next_case_label; 5042 cond = Expression::make_unary(OPERATOR_NOT, cond, loc); 5043 } 5044 else 5045 { 5046 // if COND { goto STMTS_LABEL } 5047 go_assert(stmts_label != NULL); 5048 if (*stmts_label == NULL) 5049 *stmts_label = new Unnamed_label(Linemap::unknown_location()); 5050 dest = *stmts_label; 5051 } 5052 Block* then_block = new Block(b, loc); 5053 Statement* s = Statement::make_goto_unnamed_statement(dest, loc); 5054 then_block->add_statement(s); 5055 s = Statement::make_if_statement(cond, then_block, NULL, loc); 5056 s->determine_types(gogo); 5057 b->add_statement(s); 5058 } 5059 5060 if (this->statements_ != NULL 5061 || (!this->is_fallthrough_ 5062 && stmts_label != NULL 5063 && *stmts_label != NULL)) 5064 { 5065 go_assert(!this->is_fallthrough_); 5066 if (stmts_label != NULL && *stmts_label != NULL) 5067 { 5068 go_assert(!this->is_default_); 5069 if (this->statements_ != NULL) 5070 (*stmts_label)->set_location(this->statements_->start_location()); 5071 Statement* s = Statement::make_unnamed_label_statement(*stmts_label); 5072 b->add_statement(s); 5073 *stmts_label = NULL; 5074 } 5075 if (this->statements_ != NULL) 5076 b->add_statement(Statement::make_block_statement(this->statements_, 5077 loc)); 5078 } 5079 5080 if (this->is_fallthrough_) 5081 go_assert(next_case_label == NULL); 5082 else 5083 { 5084 Location gloc = (this->statements_ == NULL 5085 ? loc 5086 : this->statements_->end_location()); 5087 b->add_statement(Statement::make_goto_unnamed_statement(break_label, 5088 gloc)); 5089 if (next_case_label != NULL) 5090 { 5091 Statement* s = 5092 Statement::make_unnamed_label_statement(next_case_label); 5093 b->add_statement(s); 5094 } 5095 } 5096 } 5097 5098 // Return true if this type clause may fall through to the statements 5099 // following the switch. 5100 5101 bool 5102 Type_case_clauses::Type_case_clause::may_fall_through() const 5103 { 5104 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 if (this->statements_ == NULL) 5115 return true; 5116 return this->statements_->may_fall_through(); 5117 } 5118 5119 // Dump the AST representation for a type case clause 5120 5121 void 5122 Type_case_clauses::Type_case_clause::dump_clause( 5123 Ast_dump_context* ast_dump_context) const 5124 { 5125 ast_dump_context->print_indent(); 5126 if (this->is_default_) 5127 { 5128 ast_dump_context->ostream() << "default:"; 5129 } 5130 else 5131 { 5132 ast_dump_context->ostream() << "case "; 5133 ast_dump_context->dump_type(this->type_); 5134 ast_dump_context->ostream() << ":" ; 5135 } 5136 ast_dump_context->dump_block(this->statements_); 5137 if (this->is_fallthrough_) 5138 { 5139 ast_dump_context->print_indent(); 5140 ast_dump_context->ostream() << " (fallthrough)" << std::endl; 5141 } 5142 } 5143 5144 // Class Type_case_clauses. 5145 5146 // Traversal. 5147 5148 int 5149 Type_case_clauses::traverse(Traverse* traverse) 5150 { 5151 for (Type_clauses::iterator p = this->clauses_.begin(); 5152 p != this->clauses_.end(); 5153 ++p) 5154 { 5155 if (p->traverse(traverse) == TRAVERSE_EXIT) 5156 return TRAVERSE_EXIT; 5157 } 5158 return TRAVERSE_CONTINUE; 5159 } 5160 5161 void 5162 Type_case_clauses::determine_types(Gogo* gogo) 5163 { 5164 for (Type_clauses::iterator p = this->clauses_.begin(); 5165 p != this->clauses_.end(); 5166 ++p) 5167 p->determine_types(gogo); 5168 } 5169 5170 bool 5171 Type_case_clauses::check_types(Type* switch_val_type) 5172 { 5173 bool ret = true; 5174 for (Type_clauses::iterator p = this->clauses_.begin(); 5175 p != this->clauses_.end(); 5176 ++p) 5177 { 5178 if (!p->check_types(switch_val_type)) 5179 ret = false; 5180 } 5181 return ret; 5182 } 5183 5184 // Check for duplicate types. 5185 5186 void 5187 Type_case_clauses::check_duplicates() const 5188 { 5189 typedef Unordered_set_hash(const Type*, Type_hash_identical, 5190 Type_identical) Types_seen; 5191 Types_seen types_seen; 5192 for (Type_clauses::const_iterator p = this->clauses_.begin(); 5193 p != this->clauses_.end(); 5194 ++p) 5195 { 5196 Type* t = p->type(); 5197 if (t == NULL) 5198 continue; 5199 if (t->is_nil_constant_as_type()) 5200 t = Type::make_nil_type(); 5201 std::pair<Types_seen::iterator, bool> ins = types_seen.insert(t); 5202 if (!ins.second) 5203 go_error_at(p->location(), "duplicate type in switch"); 5204 } 5205 } 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 Type_case_clauses::lower(Gogo* gogo, Block* b, 5213 Temporary_statement* descriptor_temp, 5214 Unnamed_label* break_label) const 5215 { 5216 const Type_case_clause* default_case = NULL; 5217 5218 Unnamed_label* stmts_label = NULL; 5219 for (Type_clauses::const_iterator p = this->clauses_.begin(); 5220 p != this->clauses_.end(); 5221 ++p) 5222 { 5223 if (!p->is_default()) 5224 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 go_assert(stmts_label == NULL); 5233 5234 if (default_case != NULL) 5235 default_case->lower(gogo, b, descriptor_temp, break_label, NULL); 5236 } 5237 5238 // Return true if these clauses may fall through to the statements 5239 // following the switch statement. 5240 5241 bool 5242 Type_case_clauses::may_fall_through() const 5243 { 5244 bool found_default = false; 5245 for (Type_clauses::const_iterator p = this->clauses_.begin(); 5246 p != this->clauses_.end(); 5247 ++p) 5248 { 5249 if (p->may_fall_through()) 5250 return true; 5251 if (p->is_default()) 5252 found_default = true; 5253 } 5254 return !found_default; 5255 } 5256 5257 // Dump the AST representation for case clauses (from a switch statement) 5258 5259 void 5260 Type_case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const 5261 { 5262 for (Type_clauses::const_iterator p = this->clauses_.begin(); 5263 p != this->clauses_.end(); 5264 ++p) 5265 p->dump_clause(ast_dump_context); 5266 } 5267 5268 // Class Type_switch_statement. 5269 5270 // Traversal. 5271 5272 int 5273 Type_switch_statement::do_traverse(Traverse* traverse) 5274 { 5275 if (this->traverse_expression(traverse, &this->expr_) == TRAVERSE_EXIT) 5276 return TRAVERSE_EXIT; 5277 if (this->clauses_ != NULL) 5278 return this->clauses_->traverse(traverse); 5279 return TRAVERSE_CONTINUE; 5280 } 5281 5282 void 5283 Type_switch_statement::do_determine_types(Gogo* gogo) 5284 { 5285 this->expr_->determine_type_no_context(gogo); 5286 this->clauses_->determine_types(gogo); 5287 } 5288 5289 void 5290 Type_switch_statement::do_check_types(Gogo*) 5291 { 5292 if (this->clauses_ != NULL) 5293 this->clauses_->check_duplicates(); 5294 5295 Type* expr_type = this->expr_->type(); 5296 if (expr_type->interface_type() == NULL) 5297 { 5298 if (!expr_type->is_error()) 5299 this->report_error(_("cannot type switch on non-interface value")); 5300 this->set_is_error(); 5301 } 5302 5303 if (!this->clauses_->check_types(expr_type)) 5304 this->set_is_error(); 5305 } 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 Type_switch_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing, 5315 Statement_inserter*) 5316 { 5317 const Location loc = this->location(); 5318 5319 if (this->classification() == STATEMENT_ERROR) 5320 return Statement::make_error_statement(loc); 5321 5322 Block* b = new Block(enclosing, loc); 5323 5324 Temporary_statement* val_temp = 5325 Statement::make_temporary(NULL, this->expr_, loc); 5326 b->add_statement(val_temp); 5327 5328 // var descriptor_temp DESCRIPTOR_TYPE 5329 Type* descriptor_type = Type::make_type_descriptor_ptr_type(); 5330 Temporary_statement* descriptor_temp = 5331 Statement::make_temporary(descriptor_type, NULL, loc); 5332 b->add_statement(descriptor_temp); 5333 5334 // descriptor_temp = ifacetype(val_temp) 5335 Expression* ref = Expression::make_temporary_reference(val_temp, loc); 5336 Expression* td = Expression::get_interface_type_descriptor(ref); 5337 Temporary_reference_expression* lhs = 5338 Expression::make_temporary_reference(descriptor_temp, loc); 5339 lhs->set_is_lvalue(); 5340 Statement* s = Statement::make_assignment(lhs, td, loc); 5341 s->determine_types(gogo); 5342 b->add_statement(s); 5343 5344 if (this->clauses_ != NULL) 5345 this->clauses_->lower(gogo, b, descriptor_temp, this->break_label()); 5346 5347 s = Statement::make_unnamed_label_statement(this->break_label_); 5348 b->add_statement(s); 5349 5350 return Statement::make_block_statement(b, loc); 5351 } 5352 5353 // Return whether this switch may fall through. 5354 5355 bool 5356 Type_switch_statement::do_may_fall_through() const 5357 { 5358 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 if (this->break_label_ != NULL) 5364 return true; 5365 5366 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 Type_switch_statement::break_label() 5374 { 5375 if (this->break_label_ == NULL) 5376 this->break_label_ = new Unnamed_label(this->location()); 5377 return this->break_label_; 5378 } 5379 5380 // Dump the AST representation for a type switch statement 5381 5382 void 5383 Type_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) 5384 const 5385 { 5386 ast_dump_context->print_indent(); 5387 ast_dump_context->ostream() << "switch "; 5388 ast_dump_context->dump_expression(this->expr_); 5389 ast_dump_context->ostream() << " .(type)"; 5390 if (ast_dump_context->dump_subblocks()) 5391 { 5392 ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl; 5393 this->clauses_->dump_clauses(ast_dump_context); 5394 ast_dump_context->ostream() << "}"; 5395 } 5396 ast_dump_context->ostream() << std::endl; 5397 } 5398 5399 // Make a type switch statement. 5400 5401 Type_switch_statement* 5402 Statement::make_type_switch_statement(Expression* expr, Location location) 5403 { 5404 return new Type_switch_statement(expr, location); 5405 } 5406 5407 // Class Send_statement. 5408 5409 // Traversal. 5410 5411 int 5412 Send_statement::do_traverse(Traverse* traverse) 5413 { 5414 if (this->traverse_expression(traverse, &this->channel_) == TRAVERSE_EXIT) 5415 return TRAVERSE_EXIT; 5416 return this->traverse_expression(traverse, &this->val_); 5417 } 5418 5419 // Determine types. 5420 5421 void 5422 Send_statement::do_determine_types(Gogo* gogo) 5423 { 5424 this->channel_->determine_type_no_context(gogo); 5425 Type* type = this->channel_->type(); 5426 Type_context context; 5427 if (type->channel_type() != NULL) 5428 context.type = type->channel_type()->element_type(); 5429 this->val_->determine_type(gogo, &context); 5430 } 5431 5432 // Check types. 5433 5434 void 5435 Send_statement::do_check_types(Gogo*) 5436 { 5437 Type* type = this->channel_->type(); 5438 if (type->is_error()) 5439 { 5440 this->set_is_error(); 5441 return; 5442 } 5443 Channel_type* channel_type = type->channel_type(); 5444 if (channel_type == NULL) 5445 { 5446 go_error_at(this->location(), "left operand of %<<-%> must be channel"); 5447 this->set_is_error(); 5448 return; 5449 } 5450 Type* element_type = channel_type->element_type(); 5451 if (!Type::are_assignable(element_type, this->val_->type(), NULL)) 5452 { 5453 this->report_error(_("incompatible types in send")); 5454 return; 5455 } 5456 if (!channel_type->may_send()) 5457 { 5458 this->report_error(_("invalid send on receive-only channel")); 5459 return; 5460 } 5461 } 5462 5463 // Flatten a send statement. We may need a temporary for interface 5464 // conversion. 5465 5466 Statement* 5467 Send_statement::do_flatten(Gogo*, Named_object*, Block*, 5468 Statement_inserter* inserter) 5469 { 5470 if (this->channel_->is_error_expression() 5471 || this->channel_->type()->is_error_type()) 5472 { 5473 go_assert(saw_errors()); 5474 return Statement::make_error_statement(this->location()); 5475 } 5476 5477 Type* element_type = this->channel_->type()->channel_type()->element_type(); 5478 if (!Type::are_identical(element_type, this->val_->type(), 5479 Type::COMPARE_ERRORS | Type::COMPARE_TAGS, 5480 NULL) 5481 && this->val_->type()->interface_type() != NULL 5482 && !this->val_->is_multi_eval_safe()) 5483 { 5484 Temporary_statement* temp = 5485 Statement::make_temporary(NULL, this->val_, this->location()); 5486 inserter->insert(temp); 5487 this->val_ = Expression::make_temporary_reference(temp, 5488 this->location()); 5489 } 5490 return this; 5491 } 5492 5493 // Add explicit type conversions. 5494 5495 void 5496 Send_statement::do_add_conversions() 5497 { 5498 Type* lt = this->channel_->type()->channel_type()->element_type(); 5499 Type* rt = this->val_->type(); 5500 if (!Type::are_identical(lt, rt, 0, NULL) 5501 && lt->interface_type() != NULL) 5502 this->val_ = Expression::make_cast(lt, this->val_, this->location()); 5503 } 5504 5505 // Convert a send statement to the backend representation. 5506 5507 Bstatement* 5508 Send_statement::do_get_backend(Translate_context* context) 5509 { 5510 Gogo* gogo = context->gogo(); 5511 Location loc = this->location(); 5512 5513 Channel_type* channel_type = this->channel_->type()->channel_type(); 5514 Type* element_type = channel_type->element_type(); 5515 Expression* val = Expression::convert_for_assignment(gogo, 5516 element_type, 5517 this->val_, loc); 5518 5519 bool can_take_address; 5520 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 case Type::TYPE_ARRAY: 5540 can_take_address = !element_type->is_slice_type(); 5541 break; 5542 5543 default: 5544 case Type::TYPE_ERROR: 5545 case Type::TYPE_VOID: 5546 case Type::TYPE_SINK: 5547 case Type::TYPE_NIL: 5548 case Type::TYPE_NAMED: 5549 case Type::TYPE_FORWARD: 5550 go_assert(saw_errors()); 5551 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 if (can_take_address 5558 && val->var_expression() == NULL 5559 && val->temporary_reference_expression() == NULL) 5560 can_take_address = false; 5561 5562 Bstatement* btemp = NULL; 5563 if (can_take_address) 5564 { 5565 // The function doesn't change the value, so just take its 5566 // address directly. 5567 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 Temporary_statement* temp = Statement::make_temporary(element_type, 5576 val, loc); 5577 Expression* ref = Expression::make_temporary_reference(temp, loc); 5578 val = Expression::make_unary(OPERATOR_AND, ref, loc); 5579 btemp = temp->get_backend(context); 5580 } 5581 5582 Expression* call = Runtime::make_call(gogo, Runtime::CHANSEND, loc, 2, 5583 this->channel_, val); 5584 call->determine_type_no_context(gogo); 5585 gogo->lower_expression(context->function(), NULL, &call); 5586 Bexpression* bcall = call->get_backend(context); 5587 Bfunction* bfunction = context->function()->func_value()->get_decl(); 5588 Bstatement* s = context->backend()->expression_statement(bfunction, bcall); 5589 5590 if (btemp == NULL) 5591 return s; 5592 else 5593 return context->backend()->compound_statement(btemp, s); 5594 } 5595 5596 // Dump the AST representation for a send statement 5597 5598 void 5599 Send_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 5600 { 5601 ast_dump_context->print_indent(); 5602 ast_dump_context->dump_expression(this->channel_); 5603 ast_dump_context->ostream() << " <- "; 5604 ast_dump_context->dump_expression(this->val_); 5605 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 5606 } 5607 5608 // Make a send statement. 5609 5610 Send_statement* 5611 Statement::make_send_statement(Expression* channel, Expression* val, 5612 Location location) 5613 { 5614 return new Send_statement(channel, val, location); 5615 } 5616 5617 // Class Select_clauses::Select_clause. 5618 5619 // Traversal. 5620 5621 int 5622 Select_clauses::Select_clause::traverse(Traverse* traverse) 5623 { 5624 if (!this->is_lowered_ 5625 && (traverse->traverse_mask() 5626 & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0) 5627 { 5628 if (this->channel_ != NULL) 5629 { 5630 if (Expression::traverse(&this->channel_, traverse) == TRAVERSE_EXIT) 5631 return TRAVERSE_EXIT; 5632 } 5633 if (this->val_ != NULL) 5634 { 5635 if (Expression::traverse(&this->val_, traverse) == TRAVERSE_EXIT) 5636 return TRAVERSE_EXIT; 5637 } 5638 if (this->closed_ != NULL) 5639 { 5640 if (Expression::traverse(&this->closed_, traverse) == TRAVERSE_EXIT) 5641 return TRAVERSE_EXIT; 5642 } 5643 } 5644 if (this->statements_ != NULL) 5645 { 5646 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 Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function, 5657 Block* b, Temporary_statement* scases, 5658 int index, Temporary_statement* recvok) 5659 { 5660 Location loc = this->location_; 5661 5662 this->set_case_index(index); 5663 5664 if (this->is_default_) 5665 { 5666 go_assert(this->channel_ == NULL && this->val_ == NULL); 5667 this->is_lowered_ = true; 5668 return; 5669 } 5670 5671 Expression* scase = Expression::make_temporary_reference(scases, loc); 5672 Expression* index_expr = Expression::make_integer_sl(index, NULL, loc); 5673 scase = Expression::make_array_index(scase, index_expr, NULL, NULL, loc); 5674 5675 // Evaluate the channel before the select statement. 5676 Temporary_statement* channel_temp = Statement::make_temporary(NULL, 5677 this->channel_, 5678 loc); 5679 b->add_statement(channel_temp); 5680 Expression* chanref = Expression::make_temporary_reference(channel_temp, 5681 loc); 5682 5683 if (this->is_send_) 5684 this->lower_send(gogo, b, scase, chanref); 5685 else 5686 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 this->is_lowered_ = true; 5691 this->val_ = NULL; 5692 } 5693 5694 // Lower a send clause in a select statement. 5695 5696 void 5697 Select_clauses::Select_clause::lower_send(Gogo* gogo, Block* b, 5698 Expression* scase, 5699 Expression* chanref) 5700 { 5701 Location loc = this->location_; 5702 5703 Channel_type* ct = this->channel_->type()->channel_type(); 5704 if (ct == NULL) 5705 return; 5706 5707 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 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 val->set_value_escapes(); 5719 b->add_statement(val); 5720 5721 Expression* valref = Expression::make_temporary_reference(val, loc); 5722 Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc); 5723 Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type()); 5724 valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc); 5725 5726 this->set_case(gogo, b, scase, chanref, valaddr); 5727 } 5728 5729 // Lower a receive clause in a select statement. 5730 5731 void 5732 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 Location loc = this->location_; 5738 5739 Channel_type* ct = this->channel_->type()->channel_type(); 5740 if (ct == NULL) 5741 return; 5742 5743 Type* valtype = ct->element_type(); 5744 Temporary_statement* val = Statement::make_temporary(valtype, NULL, loc); 5745 b->add_statement(val); 5746 5747 Expression* valref = Expression::make_temporary_reference(val, loc); 5748 Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc); 5749 Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type()); 5750 valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc); 5751 5752 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 Block* init = NULL; 5759 5760 if (this->var_ != NULL) 5761 { 5762 go_assert(this->val_ == NULL); 5763 valref = Expression::make_temporary_reference(val, loc); 5764 this->var_->var_value()->set_init(valref); 5765 this->var_->var_value()->clear_type_from_chan_element(); 5766 } 5767 else if (this->val_ != NULL && !this->val_->is_sink_expression()) 5768 { 5769 init = new Block(b, loc); 5770 valref = Expression::make_temporary_reference(val, loc); 5771 Statement* s = Statement::make_assignment(this->val_, valref, loc); 5772 s->determine_types(gogo); 5773 init->add_statement(s); 5774 } 5775 5776 if (this->closedvar_ != NULL) 5777 { 5778 go_assert(this->closed_ == NULL); 5779 Expression* cref = Expression::make_temporary_reference(recvok, loc); 5780 this->closedvar_->var_value()->set_init(cref); 5781 } 5782 else if (this->closed_ != NULL && !this->closed_->is_sink_expression()) 5783 { 5784 if (init == NULL) 5785 init = new Block(b, loc); 5786 Expression* cref = Expression::make_temporary_reference(recvok, loc); 5787 Statement* s = Statement::make_assignment(this->closed_, cref, loc); 5788 s->determine_types(gogo); 5789 init->add_statement(s); 5790 } 5791 5792 if (init != NULL) 5793 { 5794 gogo->lower_block(function, init); 5795 5796 if (this->statements_ != NULL) 5797 init->add_statement(Statement::make_block_statement(this->statements_, 5798 loc)); 5799 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 Select_clauses::Select_clause::set_case(Gogo* gogo, 5808 Block* b, 5809 Expression* scase, 5810 Expression* chanref, 5811 Expression* elem) 5812 { 5813 Location loc = this->location_; 5814 Struct_type* scase_type = scase->type()->struct_type(); 5815 5816 int field_index = 0; 5817 go_assert(scase_type->field(field_index)->is_field_name("c")); 5818 Expression* ref = Expression::make_field_reference(scase, field_index, loc); 5819 Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type()); 5820 chanref = Expression::make_unsafe_cast(unsafe_pointer_type, chanref, loc); 5821 Statement* s = Statement::make_assignment(ref, chanref, loc); 5822 s->determine_types(gogo); 5823 b->add_statement(s); 5824 5825 if (elem != NULL) 5826 { 5827 field_index = 1; 5828 go_assert(scase_type->field(field_index)->is_field_name("elem")); 5829 ref = Expression::make_field_reference(scase->copy(), field_index, loc); 5830 s = Statement::make_assignment(ref, elem, loc); 5831 s->determine_types(gogo); 5832 b->add_statement(s); 5833 } 5834 } 5835 5836 // Determine types. 5837 5838 void 5839 Select_clauses::Select_clause::determine_types(Gogo* gogo) 5840 { 5841 if (this->channel_ != NULL) 5842 this->channel_->determine_type_no_context(gogo); 5843 if (this->val_ != NULL) 5844 this->val_->determine_type_no_context(gogo); 5845 if (this->closed_ != NULL) 5846 this->closed_->determine_type_no_context(gogo); 5847 if (this->var_ != NULL && this->var_->is_variable()) 5848 this->var_->var_value()->determine_type(gogo); 5849 if (this->closedvar_ != NULL && this->closedvar_->is_variable()) 5850 this->closedvar_->var_value()->determine_type(gogo); 5851 if (this->statements_ != NULL) 5852 this->statements_->determine_types(gogo); 5853 } 5854 5855 // Check types. 5856 5857 void 5858 Select_clauses::Select_clause::check_types() 5859 { 5860 if (this->is_default_) 5861 return; 5862 5863 Channel_type* ct = this->channel_->type()->channel_type(); 5864 if (ct == NULL) 5865 { 5866 go_error_at(this->channel_->location(), "expected channel"); 5867 return; 5868 } 5869 5870 if (this->is_send_ && !ct->may_send()) 5871 go_error_at(this->location(), "invalid send on receive-only channel"); 5872 else if (!this->is_send_ && !ct->may_receive()) 5873 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 Select_clauses::Select_clause::may_fall_through() const 5881 { 5882 if (this->statements_ == NULL) 5883 return true; 5884 return this->statements_->may_fall_through(); 5885 } 5886 5887 // Return the backend representation for the statements to execute. 5888 5889 Bstatement* 5890 Select_clauses::Select_clause::get_statements_backend( 5891 Translate_context* context) 5892 { 5893 if (this->statements_ == NULL) 5894 return NULL; 5895 Bblock* bblock = this->statements_->get_backend(context); 5896 return context->backend()->block_statement(bblock); 5897 } 5898 5899 // Dump the AST representation for a select case clause 5900 5901 void 5902 Select_clauses::Select_clause::dump_clause( 5903 Ast_dump_context* ast_dump_context) const 5904 { 5905 ast_dump_context->print_indent(); 5906 if (this->is_default_) 5907 { 5908 ast_dump_context->ostream() << "default:"; 5909 } 5910 else 5911 { 5912 ast_dump_context->ostream() << "case " ; 5913 if (this->is_send_) 5914 { 5915 ast_dump_context->dump_expression(this->channel_); 5916 ast_dump_context->ostream() << " <- " ; 5917 if (this->val_ != NULL) 5918 ast_dump_context->dump_expression(this->val_); 5919 } 5920 else 5921 { 5922 if (this->val_ != NULL) 5923 ast_dump_context->dump_expression(this->val_); 5924 if (this->closed_ != NULL) 5925 { 5926 // FIXME: can val_ == NULL and closed_ ! = NULL? 5927 ast_dump_context->ostream() << " , " ; 5928 ast_dump_context->dump_expression(this->closed_); 5929 } 5930 if (this->closedvar_ != NULL || this->var_ != NULL) 5931 ast_dump_context->ostream() << " := " ; 5932 5933 ast_dump_context->ostream() << " <- " ; 5934 ast_dump_context->dump_expression(this->channel_); 5935 } 5936 ast_dump_context->ostream() << ":" ; 5937 } 5938 ast_dump_context->dump_block(this->statements_); 5939 } 5940 5941 // Class Select_clauses. 5942 5943 // Whether there is a default case. 5944 5945 bool 5946 Select_clauses::has_default() const 5947 { 5948 for (Clauses::const_iterator p = this->clauses_.begin(); 5949 p != this->clauses_.end(); 5950 ++p) 5951 if (p->is_default()) 5952 return true; 5953 return false; 5954 } 5955 5956 // Traversal. 5957 5958 int 5959 Select_clauses::traverse(Traverse* traverse) 5960 { 5961 for (Clauses::iterator p = this->clauses_.begin(); 5962 p != this->clauses_.end(); 5963 ++p) 5964 { 5965 if (p->traverse(traverse) == TRAVERSE_EXIT) 5966 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 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 int send_count = 0; 5983 int recv_count = 0; 5984 bool has_default = false; 5985 for (Clauses::iterator p = this->clauses_.begin(); 5986 p != this->clauses_.end(); 5987 ++p) 5988 { 5989 if (p->is_default()) 5990 has_default = true; 5991 else if (p->is_send()) 5992 ++send_count; 5993 else 5994 ++recv_count; 5995 } 5996 5997 *p_send_count = send_count; 5998 *p_recv_count = recv_count; 5999 6000 int send_index = 0; 6001 int recv_index = send_count; 6002 for (Clauses::iterator p = this->clauses_.begin(); 6003 p != this->clauses_.end(); 6004 ++p) 6005 { 6006 int index; 6007 if (p->is_default()) 6008 index = -1; 6009 else if (p->is_send()) 6010 { 6011 index = send_index; 6012 ++send_index; 6013 } 6014 else 6015 { 6016 index = recv_index; 6017 ++recv_index; 6018 } 6019 6020 p->lower(gogo, function, b, scases, index, recvok); 6021 } 6022 6023 go_assert(send_index == send_count); 6024 go_assert(recv_index == send_count + recv_count); 6025 go_assert(static_cast<size_t>(recv_index + (has_default ? 1 : 0)) 6026 == this->size()); 6027 } 6028 6029 // Determine types. 6030 6031 void 6032 Select_clauses::determine_types(Gogo* gogo) 6033 { 6034 for (Clauses::iterator p = this->clauses_.begin(); 6035 p != this->clauses_.end(); 6036 ++p) 6037 p->determine_types(gogo); 6038 } 6039 6040 // Check types. 6041 6042 void 6043 Select_clauses::check_types() 6044 { 6045 for (Clauses::iterator p = this->clauses_.begin(); 6046 p != this->clauses_.end(); 6047 ++p) 6048 p->check_types(); 6049 } 6050 6051 // Return whether these select clauses fall through to the statement 6052 // following the overall select statement. 6053 6054 bool 6055 Select_clauses::may_fall_through() const 6056 { 6057 for (Clauses::const_iterator p = this->clauses_.begin(); 6058 p != this->clauses_.end(); 6059 ++p) 6060 if (p->may_fall_through()) 6061 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 Select_clauses::get_backend(Translate_context* context, 6071 Temporary_statement* index, 6072 Unnamed_label *break_label, 6073 Location location) 6074 { 6075 size_t count = this->clauses_.size(); 6076 std::vector<std::vector<Bexpression*> > cases(count + 1); 6077 std::vector<Bstatement*> clauses(count + 1); 6078 6079 Type* int_type = Type::lookup_integer_type("int"); 6080 6081 int i = 0; 6082 for (Clauses::iterator p = this->clauses_.begin(); 6083 p != this->clauses_.end(); 6084 ++p, ++i) 6085 { 6086 Expression* index_expr = Expression::make_integer_sl(p->case_index(), 6087 int_type, 6088 location); 6089 cases[i].push_back(index_expr->get_backend(context)); 6090 6091 Bstatement* s = p->get_statements_backend(context); 6092 Location gloc = (p->statements() == NULL 6093 ? p->location() 6094 : p->statements()->end_location()); 6095 Bstatement* g = break_label->get_goto(context, gloc); 6096 6097 if (s == NULL) 6098 clauses[i] = g; 6099 else 6100 clauses[i] = context->backend()->compound_statement(s, g); 6101 } 6102 6103 Expression* ref = Expression::make_temporary_reference(index, location); 6104 Bexpression* bindex = ref->get_backend(context); 6105 6106 Bfunction* bfunction = context->function()->func_value()->get_decl(); 6107 6108 if (count == 0) 6109 return context->backend()->expression_statement(bfunction, bindex); 6110 6111 Gogo* gogo = context->gogo(); 6112 Expression* crash = Runtime::make_call(gogo, Runtime::UNREACHABLE, 6113 location, 0); 6114 crash->determine_type_no_context(gogo); 6115 Bexpression* bcrash = crash->get_backend(context); 6116 clauses[count] = context->backend()->expression_statement(bfunction, bcrash); 6117 6118 std::vector<Bstatement*> statements; 6119 statements.reserve(2); 6120 6121 Bstatement* switch_stmt = context->backend()->switch_statement(bfunction, 6122 bindex, 6123 cases, 6124 clauses, 6125 location); 6126 statements.push_back(switch_stmt); 6127 6128 Bstatement* ldef = break_label->get_definition(context); 6129 statements.push_back(ldef); 6130 6131 return context->backend()->statement_list(statements); 6132 } 6133 6134 // Dump the AST representation for select clauses. 6135 6136 void 6137 Select_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const 6138 { 6139 for (Clauses::const_iterator p = this->clauses_.begin(); 6140 p != this->clauses_.end(); 6141 ++p) 6142 p->dump_clause(ast_dump_context); 6143 } 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 Select_statement::break_label() 6152 { 6153 if (this->break_label_ == NULL) 6154 this->break_label_ = new Unnamed_label(this->location()); 6155 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 Select_statement::do_lower(Gogo* gogo, Named_object* function, 6165 Block* enclosing, Statement_inserter*) 6166 { 6167 if (this->is_lowered_) 6168 return this; 6169 6170 Location loc = this->location(); 6171 6172 Block* b = new Block(enclosing, loc); 6173 6174 int ncases = this->clauses_->size(); 6175 bool has_default = this->clauses_->has_default(); 6176 6177 // Zero-case select. Just block the execution. 6178 if (ncases == 0) 6179 { 6180 Expression* call = Runtime::make_call(gogo, Runtime::BLOCK, loc, 0); 6181 Statement *s = Statement::make_statement(call, false); 6182 s->determine_types(gogo); 6183 b->add_statement(s); 6184 this->is_lowered_ = true; 6185 return Statement::make_block_statement(b, loc); 6186 } 6187 6188 // One-case select. It is mostly just to run the case. 6189 if (ncases == 1) 6190 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 if (ncases == 2 && has_default) 6195 return this->lower_two_case(gogo, b); 6196 6197 // We don't allocate an entry in scases for the default case. 6198 if (has_default) 6199 --ncases; 6200 6201 Type* scase_type = Channel_type::select_case_type(); 6202 Expression* ncases_expr = 6203 Expression::make_integer_ul(ncases, NULL, 6204 Linemap::predeclared_location()); 6205 Array_type* scases_type = Type::make_array_type(scase_type, ncases_expr); 6206 scases_type->set_is_array_incomparable(); 6207 6208 Temporary_statement* scases = Statement::make_temporary(scases_type, NULL, 6209 loc); 6210 b->add_statement(scases); 6211 6212 Expression* ncases2_expr = 6213 Expression::make_integer_ul(ncases * 2, NULL, 6214 Linemap::predeclared_location()); 6215 Type* uint16_type = Type::lookup_integer_type("uint16"); 6216 Array_type* order_type = Type::make_array_type(uint16_type, ncases2_expr); 6217 order_type->set_is_array_incomparable(); 6218 6219 Temporary_statement* order = Statement::make_temporary(order_type, NULL, 6220 loc); 6221 b->add_statement(order); 6222 6223 Type* int_type = Type::lookup_integer_type("int"); 6224 this->index_ = Statement::make_temporary(int_type, NULL, loc); 6225 b->add_statement(this->index_); 6226 6227 Type* bool_type = Type::lookup_bool_type(); 6228 Temporary_statement* recvok = Statement::make_temporary(bool_type, NULL, 6229 loc); 6230 b->add_statement(recvok); 6231 6232 // Initialize the scases array. 6233 int send_count; 6234 int recv_count; 6235 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 Expression* scases_ref = Expression::make_temporary_reference(scases, loc); 6242 scases_ref = Expression::make_unary(OPERATOR_AND, scases_ref, loc); 6243 Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type()); 6244 scases_ref = Expression::make_cast(unsafe_pointer_type, scases_ref, loc); 6245 6246 Expression* order_ref = Expression::make_temporary_reference(order, loc); 6247 order_ref = Expression::make_unary(OPERATOR_AND, order_ref, loc); 6248 order_ref = Expression::make_cast(unsafe_pointer_type, order_ref, loc); 6249 6250 Expression* send_count_expr = Expression::make_integer_sl(send_count, 6251 int_type, 6252 loc); 6253 Expression* recv_count_expr = Expression::make_integer_sl(recv_count, 6254 int_type, 6255 loc); 6256 Expression* block_expr = Expression::make_boolean(!has_default, loc); 6257 6258 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 Expression* result = Expression::make_call_result(call, 0); 6264 Expression* ref = Expression::make_temporary_reference(this->index_, loc); 6265 Statement* s = Statement::make_assignment(ref, result, loc); 6266 s->determine_types(gogo); 6267 b->add_statement(s); 6268 6269 result = Expression::make_call_result(call, 1); 6270 ref = Expression::make_temporary_reference(recvok, loc); 6271 s = Statement::make_assignment(ref, result, loc); 6272 s->determine_types(gogo); 6273 b->add_statement(s); 6274 6275 this->is_lowered_ = true; 6276 b->add_statement(this); 6277 6278 return Statement::make_block_statement(b, loc); 6279 } 6280 6281 // Lower a one-case select statement. 6282 6283 Statement* 6284 Select_statement::lower_one_case(Gogo* gogo, Block* b) 6285 { 6286 Select_clauses::Select_clause& scase = this->clauses_->at(0); 6287 Location loc = this->location(); 6288 Expression* chan = scase.channel(); 6289 if (chan != NULL) 6290 { 6291 // Lower this to 6292 // if chan == nil { block() }; send/recv; body 6293 Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc); 6294 b->add_statement(chantmp); 6295 Expression* chanref = Expression::make_temporary_reference(chantmp, loc); 6296 6297 Expression* nil = Expression::make_nil(loc); 6298 Expression* cond = Expression::make_binary(OPERATOR_EQEQ, chanref, nil, loc); 6299 Block* bnil = new Block(b, loc); 6300 Expression* call = Runtime::make_call(gogo, Runtime::BLOCK, loc, 0); 6301 Statement* s = Statement::make_statement(call, false); 6302 s->determine_types(gogo); 6303 bnil->add_statement(s); 6304 Statement* ifs = Statement::make_if_statement(cond, bnil, NULL, loc); 6305 ifs->determine_types(gogo); 6306 b->add_statement(ifs); 6307 6308 chanref = chanref->copy(); 6309 Location cloc = scase.location(); 6310 if (scase.is_send()) 6311 { 6312 s = Statement::make_send_statement(chanref, scase.val(), cloc); 6313 s->determine_types(gogo); 6314 b->add_statement(s); 6315 } 6316 else 6317 { 6318 if (scase.closed() == NULL && scase.closedvar() == NULL) 6319 { 6320 // Simple receive. 6321 Expression* recv = Expression::make_receive(chanref, cloc); 6322 if (scase.val() != NULL) 6323 s = Statement::make_assignment(scase.val(), recv, cloc); 6324 else if (scase.var() != NULL) 6325 { 6326 Temporary_statement *ts = 6327 Statement::make_temporary(NULL, recv, cloc); 6328 Expression* ref = 6329 Expression::make_temporary_reference(ts, cloc); 6330 s = ts; 6331 scase.var()->var_value()->set_init(ref); 6332 scase.var()->var_value()->clear_type_from_chan_element(); 6333 } 6334 else 6335 s = Statement::make_statement(recv, false); 6336 s->determine_types(gogo); 6337 b->add_statement(s); 6338 } 6339 else 6340 { 6341 // Tuple receive. 6342 Expression* lhs; 6343 if (scase.val() != NULL) 6344 lhs = scase.val(); 6345 else 6346 { 6347 Type* valtype = chan->type()->channel_type()->element_type(); 6348 Temporary_statement *ts = 6349 Statement::make_temporary(valtype, NULL, cloc); 6350 lhs = Expression::make_temporary_reference(ts, cloc); 6351 b->add_statement(ts); 6352 } 6353 6354 Expression* lhs2; 6355 if (scase.closed() != NULL) 6356 lhs2 = scase.closed(); 6357 else 6358 { 6359 Type* booltype = Type::make_boolean_type(); 6360 Temporary_statement *ts = 6361 Statement::make_temporary(booltype, NULL, cloc); 6362 lhs2 = Expression::make_temporary_reference(ts, cloc); 6363 b->add_statement(ts); 6364 } 6365 6366 s = Statement::make_tuple_receive_assignment(lhs, lhs2, chanref, cloc); 6367 s->determine_types(gogo); 6368 b->add_statement(s); 6369 6370 if (scase.var() != NULL) 6371 { 6372 scase.var()->var_value()->set_init(lhs->copy()); 6373 scase.var()->var_value()->clear_type_from_chan_element(); 6374 } 6375 6376 if (scase.closedvar() != NULL) 6377 scase.closedvar()->var_value()->set_init(lhs2->copy()); 6378 } 6379 } 6380 } 6381 6382 Statement* bs = 6383 Statement::make_block_statement(scase.statements(), scase.location()); 6384 b->add_statement(bs); 6385 6386 Statement* label = 6387 Statement::make_unnamed_label_statement(this->break_label()); 6388 b->add_statement(label); 6389 6390 this->is_lowered_ = true; 6391 return Statement::make_block_statement(b, loc); 6392 } 6393 6394 // Lower a two-case select statement with one default case. 6395 6396 Statement* 6397 Select_statement::lower_two_case(Gogo* gogo, Block* b) 6398 { 6399 Select_clauses::Select_clause& chancase = 6400 (this->clauses_->at(0).is_default() 6401 ? this->clauses_->at(1) 6402 : this->clauses_->at(0)); 6403 Select_clauses::Select_clause& defcase = 6404 (this->clauses_->at(0).is_default() 6405 ? this->clauses_->at(0) 6406 : this->clauses_->at(1)); 6407 Location loc = this->location(); 6408 Expression* chan = chancase.channel(); 6409 Type* valtype = chan->type()->channel_type()->element_type(); 6410 6411 Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc); 6412 b->add_statement(chantmp); 6413 Expression* chanref = Expression::make_temporary_reference(chantmp, loc); 6414 6415 Block* bchan; 6416 Expression* cond; 6417 if (chancase.is_send()) 6418 { 6419 // if selectnbsend(chan, &val) { body } else { default body } 6420 6421 Temporary_statement* ts = 6422 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 ts->set_value_escapes(); 6426 b->add_statement(ts); 6427 6428 Expression* ref = Expression::make_temporary_reference(ts, loc); 6429 Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc); 6430 cond = Runtime::make_call(gogo, Runtime::SELECTNBSEND, loc, 2, 6431 chanref, addr); 6432 bchan = chancase.statements(); 6433 } 6434 else 6435 { 6436 Temporary_statement* ts = Statement::make_temporary(valtype, NULL, loc); 6437 b->add_statement(ts); 6438 6439 Expression* ref = Expression::make_temporary_reference(ts, loc); 6440 Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc); 6441 6442 // selected, ok = selectnbrecv(&lhs, chan) 6443 Call_expression* call = Runtime::make_call(gogo, Runtime::SELECTNBRECV, 6444 loc, 2, addr, chanref); 6445 6446 Temporary_statement* selected_temp = 6447 Statement::make_temporary(Type::make_boolean_type(), 6448 Expression::make_call_result(call, 0), 6449 loc); 6450 selected_temp->determine_types(gogo); 6451 b->add_statement(selected_temp); 6452 6453 Temporary_statement* ok_temp = 6454 Statement::make_temporary(Type::make_boolean_type(), 6455 Expression::make_call_result(call, 1), 6456 loc); 6457 ok_temp->determine_types(gogo); 6458 b->add_statement(ok_temp); 6459 6460 cond = Expression::make_temporary_reference(selected_temp, loc); 6461 6462 Location cloc = chancase.location(); 6463 bchan = new Block(b, loc); 6464 if (chancase.val() != NULL && !chancase.val()->is_sink_expression()) 6465 { 6466 Statement* as = Statement::make_assignment(chancase.val(), 6467 ref->copy(), 6468 cloc); 6469 as->determine_types(gogo); 6470 bchan->add_statement(as); 6471 } 6472 else if (chancase.var() != NULL) 6473 { 6474 chancase.var()->var_value()->set_init(ref->copy()); 6475 chancase.var()->var_value()->clear_type_from_chan_element(); 6476 } 6477 6478 if (chancase.closed() != NULL && !chancase.closed()->is_sink_expression()) 6479 { 6480 Expression* okref = Expression::make_temporary_reference(ok_temp, 6481 cloc); 6482 Statement* as = Statement::make_assignment(chancase.closed(), 6483 okref, cloc); 6484 as->determine_types(gogo); 6485 bchan->add_statement(as); 6486 } 6487 else if (chancase.closedvar() != NULL) 6488 { 6489 Expression* okref = Expression::make_temporary_reference(ok_temp, 6490 cloc); 6491 chancase.closedvar()->var_value()->set_init(okref); 6492 } 6493 6494 Statement* bs = Statement::make_block_statement(chancase.statements(), 6495 cloc); 6496 bchan->add_statement(bs); 6497 } 6498 6499 Statement* ifs = 6500 Statement::make_if_statement(cond, bchan, defcase.statements(), loc); 6501 ifs->determine_types(gogo); 6502 b->add_statement(ifs); 6503 6504 Statement* label = 6505 Statement::make_unnamed_label_statement(this->break_label()); 6506 b->add_statement(label); 6507 6508 this->is_lowered_ = true; 6509 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 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 if (this->break_label_ != NULL) 6521 return true; 6522 return this->clauses_->may_fall_through(); 6523 } 6524 6525 // Return the backend representation for a select statement. 6526 6527 Bstatement* 6528 Select_statement::do_get_backend(Translate_context* context) 6529 { 6530 return this->clauses_->get_backend(context, this->index_, 6531 this->break_label(), this->location()); 6532 } 6533 6534 // Dump the AST representation for a select statement. 6535 6536 void 6537 Select_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 6538 { 6539 ast_dump_context->print_indent(); 6540 ast_dump_context->ostream() << "select"; 6541 if (ast_dump_context->dump_subblocks()) 6542 { 6543 ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl; 6544 this->clauses_->dump_clauses(ast_dump_context); 6545 ast_dump_context->print_indent(); 6546 ast_dump_context->ostream() << "}"; 6547 } 6548 ast_dump_context->ostream() << std::endl; 6549 } 6550 6551 // Make a select statement. 6552 6553 Select_statement* 6554 Statement::make_select_statement(Location location) 6555 { 6556 return new Select_statement(location); 6557 } 6558 6559 // Class For_statement. 6560 6561 // Traversal. 6562 6563 int 6564 For_statement::do_traverse(Traverse* traverse) 6565 { 6566 if (this->init_ != NULL) 6567 { 6568 if (this->init_->traverse(traverse) == TRAVERSE_EXIT) 6569 return TRAVERSE_EXIT; 6570 } 6571 if (this->cond_ != NULL) 6572 { 6573 if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT) 6574 return TRAVERSE_EXIT; 6575 } 6576 if (this->post_ != NULL) 6577 { 6578 if (this->post_->traverse(traverse) == TRAVERSE_EXIT) 6579 return TRAVERSE_EXIT; 6580 } 6581 return this->statements_->traverse(traverse); 6582 } 6583 6584 void 6585 For_statement::do_determine_types(Gogo* gogo) 6586 { 6587 if (this->init_ != NULL) 6588 this->init_->determine_types(gogo); 6589 if (this->cond_ != NULL) 6590 this->cond_->determine_type_no_context(gogo); 6591 if (this->post_ != NULL) 6592 this->post_->determine_types(gogo); 6593 this->statements_->determine_types(gogo); 6594 } 6595 6596 void 6597 For_statement::do_check_types(Gogo*) 6598 { 6599 if (this->cond_ != NULL) 6600 { 6601 Type* type = this->cond_->type(); 6602 if (type->is_error()) 6603 this->set_is_error(); 6604 else if (!type->is_boolean_type()) 6605 { 6606 go_error_at(this->cond_->location(), "expected boolean expression"); 6607 this->set_is_error(); 6608 } 6609 } 6610 } 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 For_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing, 6617 Statement_inserter*) 6618 { 6619 Location loc = this->location(); 6620 6621 if (this->classification() == STATEMENT_ERROR) 6622 return Statement::make_error_statement(loc); 6623 6624 Statement* s; 6625 Block* b = new Block(enclosing, this->location()); 6626 if (this->init_ != NULL) 6627 { 6628 s = Statement::make_block_statement(this->init_, 6629 this->init_->start_location()); 6630 b->add_statement(s); 6631 } 6632 6633 Unnamed_label* entry = NULL; 6634 if (this->cond_ != NULL) 6635 { 6636 entry = new Unnamed_label(this->location()); 6637 b->add_statement(Statement::make_goto_unnamed_statement(entry, loc)); 6638 } 6639 6640 Unnamed_label* top = new Unnamed_label(this->location()); 6641 top->set_derived_from(this); 6642 b->add_statement(Statement::make_unnamed_label_statement(top)); 6643 6644 s = Statement::make_block_statement(this->statements_, 6645 this->statements_->start_location()); 6646 b->add_statement(s); 6647 6648 Location end_loc = this->statements_->end_location(); 6649 6650 Unnamed_label* cont = this->continue_label_; 6651 if (cont != NULL) 6652 b->add_statement(Statement::make_unnamed_label_statement(cont)); 6653 6654 if (this->post_ != NULL) 6655 { 6656 s = Statement::make_block_statement(this->post_, 6657 this->post_->start_location()); 6658 b->add_statement(s); 6659 end_loc = this->post_->end_location(); 6660 } 6661 6662 if (this->cond_ == NULL) 6663 b->add_statement(Statement::make_goto_unnamed_statement(top, end_loc)); 6664 else 6665 { 6666 b->add_statement(Statement::make_unnamed_label_statement(entry)); 6667 6668 Location cond_loc = this->cond_->location(); 6669 Block* then_block = new Block(b, cond_loc); 6670 s = Statement::make_goto_unnamed_statement(top, cond_loc); 6671 then_block->add_statement(s); 6672 6673 s = Statement::make_if_statement(this->cond_, then_block, NULL, cond_loc); 6674 s->determine_types(gogo); 6675 b->add_statement(s); 6676 } 6677 6678 Unnamed_label* brk = this->break_label_; 6679 if (brk != NULL) 6680 b->add_statement(Statement::make_unnamed_label_statement(brk)); 6681 6682 b->set_end_location(end_loc); 6683 6684 Statement* bs = Statement::make_block_statement(b, loc); 6685 bs->block_statement()->set_is_lowered_for_statement(); 6686 return bs; 6687 } 6688 6689 // Return the break label, creating it if necessary. 6690 6691 Unnamed_label* 6692 For_statement::break_label() 6693 { 6694 if (this->break_label_ == NULL) 6695 this->break_label_ = new Unnamed_label(this->location()); 6696 return this->break_label_; 6697 } 6698 6699 // Return the continue LABEL_EXPR. 6700 6701 Unnamed_label* 6702 For_statement::continue_label() 6703 { 6704 if (this->continue_label_ == NULL) 6705 this->continue_label_ = new Unnamed_label(this->location()); 6706 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 For_statement::set_break_continue_labels(Unnamed_label* break_label, 6714 Unnamed_label* continue_label) 6715 { 6716 go_assert(this->break_label_ == NULL && this->continue_label_ == NULL); 6717 this->break_label_ = break_label; 6718 this->continue_label_ = continue_label; 6719 } 6720 6721 // Whether the overall statement may fall through. 6722 6723 bool 6724 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 if(this->cond_ != NULL) 6729 return true; 6730 if(this->break_label_ != NULL) 6731 return true; 6732 return false; 6733 } 6734 6735 // Dump the AST representation for a for statement. 6736 6737 void 6738 For_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 6739 { 6740 if (this->init_ != NULL && ast_dump_context->dump_subblocks()) 6741 { 6742 ast_dump_context->print_indent(); 6743 ast_dump_context->indent(); 6744 ast_dump_context->ostream() << "// INIT " << std::endl; 6745 ast_dump_context->dump_block(this->init_); 6746 ast_dump_context->unindent(); 6747 } 6748 ast_dump_context->print_indent(); 6749 ast_dump_context->ostream() << "for "; 6750 if (this->cond_ != NULL) 6751 ast_dump_context->dump_expression(this->cond_); 6752 6753 if (ast_dump_context->dump_subblocks()) 6754 { 6755 ast_dump_context->ostream() << " {" << std::endl; 6756 ast_dump_context->dump_block(this->statements_); 6757 if (this->init_ != NULL) 6758 { 6759 ast_dump_context->print_indent(); 6760 ast_dump_context->ostream() << "// POST " << std::endl; 6761 ast_dump_context->dump_block(this->post_); 6762 } 6763 ast_dump_context->unindent(); 6764 6765 ast_dump_context->print_indent(); 6766 ast_dump_context->ostream() << "}"; 6767 } 6768 6769 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 6770 } 6771 6772 // Make a for statement. 6773 6774 For_statement* 6775 Statement::make_for_statement(Block* init, Expression* cond, Block* post, 6776 Location location) 6777 { 6778 return new For_statement(init, cond, post, location); 6779 } 6780 6781 // Class For_range_statement. 6782 6783 // Traversal. 6784 6785 int 6786 For_range_statement::do_traverse(Traverse* traverse) 6787 { 6788 if (this->index_var_ != NULL) 6789 { 6790 if (this->traverse_expression(traverse, &this->index_var_) 6791 == TRAVERSE_EXIT) 6792 return TRAVERSE_EXIT; 6793 } 6794 if (this->value_var_ != NULL) 6795 { 6796 if (this->traverse_expression(traverse, &this->value_var_) 6797 == TRAVERSE_EXIT) 6798 return TRAVERSE_EXIT; 6799 } 6800 if (this->traverse_expression(traverse, &this->range_) == TRAVERSE_EXIT) 6801 return TRAVERSE_EXIT; 6802 return this->statements_->traverse(traverse); 6803 } 6804 6805 void 6806 For_range_statement::do_determine_types(Gogo* gogo) 6807 { 6808 if (this->index_var_ != NULL) 6809 this->index_var_->determine_type_no_context(gogo); 6810 if (this->value_var_ != NULL) 6811 this->value_var_->determine_type_no_context(gogo); 6812 this->range_->determine_type_no_context(gogo); 6813 this->statements_->determine_types(gogo); 6814 } 6815 6816 void 6817 For_range_statement::do_check_types(Gogo*) 6818 { 6819 Type* range_type = this->range_->type(); 6820 6821 Type* index_type; 6822 Type* value_type = NULL; 6823 6824 if (range_type->points_to() != NULL 6825 && range_type->points_to()->array_type() != NULL 6826 && !range_type->points_to()->is_slice_type()) 6827 range_type = range_type->points_to(); 6828 6829 if (range_type->array_type() != NULL) 6830 { 6831 index_type = Type::lookup_integer_type("int"); 6832 value_type = range_type->array_type()->element_type(); 6833 } 6834 else if (range_type->is_string_type()) 6835 { 6836 index_type = Type::lookup_integer_type("int"); 6837 value_type = Type::lookup_integer_type("rune"); 6838 } 6839 else if (range_type->map_type() != NULL) 6840 { 6841 index_type = range_type->map_type()->key_type(); 6842 value_type = range_type->map_type()->val_type(); 6843 } 6844 else if (range_type->channel_type() != NULL) 6845 { 6846 if (!range_type->channel_type()->may_receive()) 6847 this->report_error(_("invalid receive on send-only channel")); 6848 index_type = range_type->channel_type()->element_type(); 6849 if (this->value_var_ != NULL) 6850 { 6851 if (!this->value_var_->type()->is_error()) 6852 this->report_error(_("too many variables for range clause " 6853 "with channel")); 6854 this->set_is_error(); 6855 return; 6856 } 6857 } 6858 else 6859 { 6860 this->report_error(_("range clause must have " 6861 "array, slice, string, map, or channel type")); 6862 return; 6863 } 6864 6865 if (this->index_var_ != NULL 6866 && !Assignment_statement::check_assignment_types(this->index_var_, 6867 index_type, 6868 this->location())) 6869 this->set_is_error(); 6870 if (this->value_var_ != NULL 6871 && !Assignment_statement::check_assignment_types(this->value_var_, 6872 value_type, 6873 this->location())) 6874 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 For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing, 6883 Statement_inserter*) 6884 { 6885 if (this->classification() == STATEMENT_ERROR) 6886 return Statement::make_error_statement(this->location()); 6887 6888 Type* range_type = this->range_->type(); 6889 if (range_type->points_to() != NULL 6890 && range_type->points_to()->array_type() != NULL 6891 && !range_type->points_to()->is_slice_type()) 6892 range_type = range_type->points_to(); 6893 6894 Type* index_type; 6895 Type* value_type = NULL; 6896 if (range_type->array_type() != NULL) 6897 { 6898 index_type = Type::lookup_integer_type("int"); 6899 value_type = range_type->array_type()->element_type(); 6900 } 6901 else if (range_type->is_string_type()) 6902 { 6903 index_type = Type::lookup_integer_type("int"); 6904 value_type = Type::lookup_integer_type("rune"); 6905 } 6906 else if (range_type->map_type() != NULL) 6907 { 6908 index_type = range_type->map_type()->key_type(); 6909 value_type = range_type->map_type()->val_type(); 6910 } 6911 else if (range_type->channel_type() != NULL) 6912 { 6913 index_type = range_type->channel_type()->element_type(); 6914 go_assert(this->value_var_ == NULL); 6915 } 6916 else 6917 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 bool eval = true; 6925 if ((this->value_var_ == NULL || this->value_var_->is_sink_expression()) 6926 && range_type->array_type() != NULL 6927 && !range_type->is_slice_type() 6928 && Builtin_call_expression::array_len_is_constant(this->range_)) 6929 eval = false; 6930 6931 Location loc = this->location(); 6932 Block* temp_block = new Block(enclosing, loc); 6933 6934 Expression* orig_range_expr = this->range_; 6935 Named_object* range_object = NULL; 6936 Temporary_statement* range_temp = NULL; 6937 if (eval) 6938 { 6939 Var_expression* ve = this->range_->var_expression(); 6940 if (ve != NULL) 6941 range_object = ve->named_object(); 6942 else 6943 { 6944 range_temp = Statement::make_temporary(NULL, this->range_, loc); 6945 temp_block->add_statement(range_temp); 6946 this->range_ = NULL; 6947 } 6948 } 6949 6950 // Try to match "range clear" patterns and rewrite to simple runtime 6951 // calls. 6952 if (range_type->map_type() != NULL) 6953 { 6954 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 if (clear != NULL) 6961 { 6962 if (gogo->debug_optimization()) 6963 go_debug(loc, "map range clear"); 6964 clear->determine_types(gogo); 6965 temp_block->add_statement(clear); 6966 return Statement::make_block_statement(temp_block, loc); 6967 } 6968 } 6969 else if (range_type->array_type() != NULL) 6970 { 6971 // Slice or array. 6972 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 if (clear != NULL) 6979 { 6980 if (gogo->debug_optimization()) 6981 go_debug(loc, "array range clear"); 6982 clear->determine_types(gogo); 6983 temp_block->add_statement(clear); 6984 return Statement::make_block_statement(temp_block, loc); 6985 } 6986 } 6987 6988 Temporary_statement* index_temp = Statement::make_temporary(index_type, 6989 NULL, loc); 6990 temp_block->add_statement(index_temp); 6991 6992 Temporary_statement* value_temp = NULL; 6993 if (this->value_var_ != NULL && !this->value_var_->is_sink_expression()) 6994 { 6995 value_temp = Statement::make_temporary(value_type, NULL, loc); 6996 temp_block->add_statement(value_temp); 6997 } 6998 6999 Block* body = new Block(temp_block, loc); 7000 7001 Block* init; 7002 Expression* cond; 7003 Block* iter_init; 7004 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 if (range_type->is_slice_type()) 7015 this->lower_range_slice(gogo, temp_block, body, range_object, range_temp, 7016 index_temp, value_temp, &init, &cond, &iter_init, 7017 &post); 7018 else if (range_type->array_type() != NULL) 7019 this->lower_range_array(gogo, temp_block, body, range_object, range_temp, 7020 index_temp, value_temp, &init, &cond, &iter_init, 7021 &post); 7022 else if (range_type->is_string_type()) 7023 this->lower_range_string(gogo, temp_block, body, range_object, range_temp, 7024 index_temp, value_temp, &init, &cond, &iter_init, 7025 &post); 7026 else if (range_type->map_type() != NULL) 7027 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 else if (range_type->channel_type() != NULL) 7031 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 go_unreachable(); 7036 7037 if (iter_init != NULL) 7038 body->add_statement(Statement::make_block_statement(iter_init, loc)); 7039 7040 if (this->index_var_ != NULL) 7041 { 7042 Statement* assign; 7043 Expression* index_ref = 7044 Expression::make_temporary_reference(index_temp, loc); 7045 if (this->value_var_ == NULL || this->value_var_->is_sink_expression()) 7046 assign = Statement::make_assignment(this->index_var_, index_ref, loc); 7047 else 7048 { 7049 Expression_list* lhs = new Expression_list(); 7050 lhs->push_back(this->index_var_); 7051 lhs->push_back(this->value_var_); 7052 7053 Expression_list* rhs = new Expression_list(); 7054 rhs->push_back(index_ref); 7055 rhs->push_back(Expression::make_temporary_reference(value_temp, loc)); 7056 7057 assign = Statement::make_tuple_assignment(lhs, rhs, loc); 7058 } 7059 assign->determine_types(gogo); 7060 body->add_statement(assign); 7061 } 7062 7063 body->add_statement(Statement::make_block_statement(this->statements_, loc)); 7064 7065 body->set_end_location(this->statements_->end_location()); 7066 7067 For_statement* loop = Statement::make_for_statement(init, cond, post, 7068 this->location()); 7069 loop->add_statements(body); 7070 loop->determine_types(gogo); 7071 loop->set_break_continue_labels(this->break_label_, this->continue_label_); 7072 7073 temp_block->add_statement(loop); 7074 7075 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 For_range_statement::make_range_ref(Named_object* range_object, 7083 Temporary_statement* range_temp, 7084 Location loc) 7085 { 7086 if (range_object != NULL) 7087 return Expression::make_var_reference(range_object, loc); 7088 else 7089 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 For_range_statement::call_builtin(Gogo* gogo, const char* funcname, 7097 Expression* arg, 7098 Location loc) 7099 { 7100 Named_object* no = gogo->lookup_global(funcname); 7101 go_assert(no != NULL && no->is_function_declaration()); 7102 Expression* func = Expression::make_func_reference(no, NULL, loc); 7103 Expression_list* params = new Expression_list(); 7104 params->push_back(arg); 7105 return Expression::make_call(func, params, false, loc); 7106 } 7107 7108 // Lower a for range over an array. 7109 7110 void 7111 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 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 Block* init = new Block(enclosing, loc); 7141 7142 Expression* len_arg; 7143 if (range_object == NULL && range_temp == NULL) 7144 { 7145 // Don't evaluate this->range_, just get its length. 7146 len_arg = this->range_; 7147 } 7148 else 7149 { 7150 Expression* ref = this->make_range_ref(range_object, range_temp, loc); 7151 range_temp = Statement::make_temporary(NULL, ref, loc); 7152 range_temp->determine_types(gogo); 7153 init->add_statement(range_temp); 7154 len_arg = ref; 7155 } 7156 Expression* len_call = this->call_builtin(gogo, "len", len_arg, loc); 7157 Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(), 7158 len_call, loc); 7159 len_temp->determine_types(gogo); 7160 init->add_statement(len_temp); 7161 7162 Expression* zexpr = Expression::make_integer_ul(0, NULL, loc); 7163 7164 Temporary_reference_expression* tref = 7165 Expression::make_temporary_reference(index_temp, loc); 7166 tref->set_is_lvalue(); 7167 Statement* s = Statement::make_assignment(tref, zexpr, loc); 7168 s->determine_types(gogo); 7169 init->add_statement(s); 7170 7171 *pinit = init; 7172 7173 // Set *PCOND to 7174 // index_temp < len_temp 7175 7176 Expression* ref = Expression::make_temporary_reference(index_temp, loc); 7177 Expression* ref2 = Expression::make_temporary_reference(len_temp, loc); 7178 Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc); 7179 7180 *pcond = lt; 7181 7182 // Set *PITER_INIT to 7183 // value_temp = range[index_temp] 7184 7185 Block* iter_init = NULL; 7186 if (value_temp != NULL) 7187 { 7188 iter_init = new Block(body_block, loc); 7189 7190 ref = Expression::make_temporary_reference(range_temp, loc); 7191 ref2 = Expression::make_temporary_reference(index_temp, loc); 7192 Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc); 7193 7194 tref = Expression::make_temporary_reference(value_temp, loc); 7195 tref->set_is_lvalue(); 7196 s = Statement::make_assignment(tref, index, loc); 7197 s->determine_types(gogo); 7198 7199 iter_init->add_statement(s); 7200 } 7201 *piter_init = iter_init; 7202 7203 // Set *PPOST to 7204 // index_temp++ 7205 7206 Block* post = new Block(enclosing, loc); 7207 tref = Expression::make_temporary_reference(index_temp, loc); 7208 tref->set_is_lvalue(); 7209 s = Statement::make_inc_statement(tref); 7210 s->determine_types(gogo); 7211 post->add_statement(s); 7212 *ppost = post; 7213 } 7214 7215 // Lower a for range over a slice. 7216 7217 void 7218 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 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 Block* init = new Block(enclosing, loc); 7252 7253 Expression* ref = this->make_range_ref(range_object, range_temp, loc); 7254 Temporary_statement* for_temp = Statement::make_temporary(NULL, ref, loc); 7255 for_temp->determine_types(gogo); 7256 init->add_statement(for_temp); 7257 7258 ref = Expression::make_temporary_reference(for_temp, loc); 7259 Expression* len_call = this->call_builtin(gogo, "len", ref, loc); 7260 Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(), 7261 len_call, loc); 7262 len_temp->determine_types(gogo); 7263 init->add_statement(len_temp); 7264 7265 Expression* zexpr = Expression::make_integer_ul(0, NULL, loc); 7266 7267 Temporary_reference_expression* tref = 7268 Expression::make_temporary_reference(index_temp, loc); 7269 tref->set_is_lvalue(); 7270 Statement* s = Statement::make_assignment(tref, zexpr, loc); 7271 s->determine_types(gogo); 7272 init->add_statement(s); 7273 7274 *pinit = init; 7275 7276 // Set *PCOND to 7277 // index_temp < len_temp 7278 7279 ref = Expression::make_temporary_reference(index_temp, loc); 7280 Expression* ref2 = Expression::make_temporary_reference(len_temp, loc); 7281 Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc); 7282 7283 *pcond = lt; 7284 7285 // Set *PITER_INIT to 7286 // value_temp = range[index_temp] 7287 7288 Block* iter_init = NULL; 7289 if (value_temp != NULL) 7290 { 7291 iter_init = new Block(body_block, loc); 7292 7293 ref = Expression::make_temporary_reference(for_temp, loc); 7294 ref2 = Expression::make_temporary_reference(index_temp, loc); 7295 Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc); 7296 7297 tref = Expression::make_temporary_reference(value_temp, loc); 7298 tref->set_is_lvalue(); 7299 s = Statement::make_assignment(tref, index, loc); 7300 s->determine_types(gogo); 7301 7302 iter_init->add_statement(s); 7303 } 7304 *piter_init = iter_init; 7305 7306 // Set *PPOST to 7307 // index_temp++ 7308 7309 Block* post = new Block(enclosing, loc); 7310 tref = Expression::make_temporary_reference(index_temp, loc); 7311 tref->set_is_lvalue(); 7312 s = Statement::make_inc_statement(tref); 7313 s->determine_types(gogo); 7314 post->add_statement(s); 7315 *ppost = post; 7316 } 7317 7318 // Lower a for range over a string. 7319 7320 void 7321 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 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 Block* init = new Block(enclosing, loc); 7357 7358 Expression* ref = this->make_range_ref(range_object, range_temp, loc); 7359 Call_expression* call = this->call_builtin(gogo, "len", ref, loc); 7360 Temporary_statement* len_temp = 7361 Statement::make_temporary(index_temp->type(), call, loc); 7362 len_temp->determine_types(gogo); 7363 init->add_statement(len_temp); 7364 7365 Temporary_statement* next_index_temp = 7366 Statement::make_temporary(index_temp->type(), NULL, loc); 7367 init->add_statement(next_index_temp); 7368 7369 Temporary_reference_expression* index_ref = 7370 Expression::make_temporary_reference(index_temp, loc); 7371 index_ref->set_is_lvalue(); 7372 Expression* zexpr = Expression::make_integer_ul(0, index_temp->type(), loc); 7373 Statement* s = Statement::make_assignment(index_ref, zexpr, loc); 7374 s->determine_types(gogo); 7375 init->add_statement(s); 7376 7377 Type* rune_type; 7378 if (value_temp != NULL) 7379 rune_type = value_temp->type(); 7380 else 7381 { 7382 rune_type = Type::lookup_integer_type("rune"); 7383 value_temp = Statement::make_temporary(rune_type, NULL, loc); 7384 init->add_statement(value_temp); 7385 } 7386 7387 *pinit = init; 7388 7389 // Set *PCOND to 7390 // index_temp < len_temp 7391 7392 index_ref = Expression::make_temporary_reference(index_temp, loc); 7393 Expression* len_ref = 7394 Expression::make_temporary_reference(len_temp, loc); 7395 *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 Block* iter_init = new Block(body_block, loc); 7406 7407 ref = this->make_range_ref(range_object, range_temp, loc); 7408 index_ref = Expression::make_temporary_reference(index_temp, loc); 7409 ref = Expression::make_string_index(ref, index_ref, NULL, loc); 7410 ref = Expression::make_cast(rune_type, ref, loc); 7411 Temporary_reference_expression* value_ref = 7412 Expression::make_temporary_reference(value_temp, loc); 7413 value_ref->set_is_lvalue(); 7414 s = Statement::make_assignment(value_ref, ref, loc); 7415 s->determine_types(gogo); 7416 iter_init->add_statement(s); 7417 7418 value_ref = Expression::make_temporary_reference(value_temp, loc); 7419 Expression* rune_self = Expression::make_integer_ul(0x80, rune_type, loc); 7420 Expression* cond = Expression::make_binary(OPERATOR_LT, value_ref, rune_self, 7421 loc); 7422 7423 Block* then_block = new Block(iter_init, loc); 7424 7425 Temporary_reference_expression* lhs = 7426 Expression::make_temporary_reference(next_index_temp, loc); 7427 lhs->set_is_lvalue(); 7428 index_ref = Expression::make_temporary_reference(index_temp, loc); 7429 Expression* one = Expression::make_integer_ul(1, index_temp->type(), loc); 7430 Expression* sum = Expression::make_binary(OPERATOR_PLUS, index_ref, one, 7431 loc); 7432 s = Statement::make_assignment(lhs, sum, loc); 7433 s->determine_types(gogo); 7434 then_block->add_statement(s); 7435 7436 Block* else_block = new Block(iter_init, loc); 7437 7438 ref = this->make_range_ref(range_object, range_temp, loc); 7439 index_ref = Expression::make_temporary_reference(index_temp, loc); 7440 call = Runtime::make_call(gogo, Runtime::DECODERUNE, loc, 2, ref, index_ref); 7441 7442 value_ref = Expression::make_temporary_reference(value_temp, loc); 7443 value_ref->set_is_lvalue(); 7444 Expression* res = Expression::make_call_result(call, 0); 7445 s = Statement::make_assignment(value_ref, res, loc); 7446 s->determine_types(gogo); 7447 else_block->add_statement(s); 7448 7449 lhs = Expression::make_temporary_reference(next_index_temp, loc); 7450 lhs->set_is_lvalue(); 7451 res = Expression::make_call_result(call, 1); 7452 s = Statement::make_assignment(lhs, res, loc); 7453 s->determine_types(gogo); 7454 else_block->add_statement(s); 7455 7456 s = Statement::make_if_statement(cond, then_block, else_block, loc); 7457 s->determine_types(gogo); 7458 iter_init->add_statement(s); 7459 7460 *piter_init = iter_init; 7461 7462 // Set *PPOST to 7463 // index_temp = next_index_temp 7464 7465 Block* post = new Block(enclosing, loc); 7466 7467 index_ref = Expression::make_temporary_reference(index_temp, loc); 7468 index_ref->set_is_lvalue(); 7469 ref = Expression::make_temporary_reference(next_index_temp, loc); 7470 s = Statement::make_assignment(index_ref, ref, loc); 7471 s->determine_types(gogo); 7472 7473 post->add_statement(s); 7474 *ppost = post; 7475 } 7476 7477 // Lower a for range over a map. 7478 7479 void 7480 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 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 Block* init = new Block(enclosing, loc); 7513 7514 Type* map_iteration_type = map_type->hiter_type(gogo); 7515 Temporary_statement* hiter = Statement::make_temporary(map_iteration_type, 7516 NULL, loc); 7517 init->add_statement(hiter); 7518 7519 Expression* p1 = Expression::make_type_descriptor(map_type, loc); 7520 Expression* p2 = this->make_range_ref(range_object, range_temp, loc); 7521 Expression* ref = Expression::make_temporary_reference(hiter, loc); 7522 Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc); 7523 Expression* call = Runtime::make_call(gogo, Runtime::MAPITERINIT, loc, 3, 7524 p1, p2, p3); 7525 Statement* s = Statement::make_statement(call, true); 7526 s->determine_types(gogo); 7527 init->add_statement(s); 7528 7529 *pinit = init; 7530 7531 // Set *PCOND to 7532 // hiter.key != nil 7533 7534 ref = Expression::make_temporary_reference(hiter, loc); 7535 ref = Expression::make_field_reference(ref, 0, loc); 7536 Expression* ne = Expression::make_binary(OPERATOR_NOTEQ, ref, 7537 Expression::make_nil(loc), 7538 loc); 7539 *pcond = ne; 7540 7541 // Set *PITER_INIT to 7542 // index_temp = *hiter.key 7543 // value_temp = *hiter.val 7544 7545 Block* iter_init = new Block(body_block, loc); 7546 7547 Expression* lhs = Expression::make_temporary_reference(index_temp, loc); 7548 Expression* rhs = Expression::make_temporary_reference(hiter, loc); 7549 rhs = Expression::make_field_reference(ref, 0, loc); 7550 rhs = Expression::make_dereference(ref, Expression::NIL_CHECK_NOT_NEEDED, 7551 loc); 7552 Statement* set = Statement::make_assignment(lhs, rhs, loc); 7553 set->determine_types(gogo); 7554 iter_init->add_statement(set); 7555 7556 if (value_temp != NULL) 7557 { 7558 lhs = Expression::make_temporary_reference(value_temp, loc); 7559 rhs = Expression::make_temporary_reference(hiter, loc); 7560 rhs = Expression::make_field_reference(rhs, 1, loc); 7561 rhs = Expression::make_dereference(rhs, Expression::NIL_CHECK_NOT_NEEDED, 7562 loc); 7563 set = Statement::make_assignment(lhs, rhs, loc); 7564 set->determine_types(gogo); 7565 iter_init->add_statement(set); 7566 } 7567 7568 *piter_init = iter_init; 7569 7570 // Set *PPOST to 7571 // mapiternext(&hiter) 7572 7573 Block* post = new Block(enclosing, loc); 7574 7575 ref = Expression::make_temporary_reference(hiter, loc); 7576 p1 = Expression::make_unary(OPERATOR_AND, ref, loc); 7577 call = Runtime::make_call(gogo, Runtime::MAPITERNEXT, loc, 1, p1); 7578 s = Statement::make_statement(call, true); 7579 s->determine_types(gogo); 7580 post->add_statement(s); 7581 7582 *ppost = post; 7583 } 7584 7585 // Lower a for range over a channel. 7586 7587 void 7588 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 go_assert(value_temp == NULL); 7601 7602 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 *pinit = NULL; 7617 *pcond = NULL; 7618 *ppost = NULL; 7619 7620 // Set *PITER_INIT to 7621 // index_temp, ok_temp = <-range 7622 // if !ok_temp { 7623 // break 7624 // } 7625 7626 Block* iter_init = new Block(body_block, loc); 7627 7628 Temporary_statement* ok_temp = 7629 Statement::make_temporary(Type::lookup_bool_type(), NULL, loc); 7630 iter_init->add_statement(ok_temp); 7631 7632 Expression* cref = this->make_range_ref(range_object, range_temp, loc); 7633 Temporary_reference_expression* iref = 7634 Expression::make_temporary_reference(index_temp, loc); 7635 iref->set_is_lvalue(); 7636 Temporary_reference_expression* oref = 7637 Expression::make_temporary_reference(ok_temp, loc); 7638 oref->set_is_lvalue(); 7639 Statement* s = Statement::make_tuple_receive_assignment(iref, oref, cref, 7640 loc); 7641 s->determine_types(gogo); 7642 iter_init->add_statement(s); 7643 7644 Block* then_block = new Block(iter_init, loc); 7645 s = Statement::make_break_statement(this->break_label(), loc); 7646 then_block->add_statement(s); 7647 7648 oref = Expression::make_temporary_reference(ok_temp, loc); 7649 Expression* cond = Expression::make_unary(OPERATOR_NOT, oref, loc); 7650 s = Statement::make_if_statement(cond, then_block, NULL, loc); 7651 s->determine_types(gogo); 7652 iter_init->add_statement(s); 7653 7654 *piter_init = iter_init; 7655 } 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 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 if (this->value_var_ != NULL) 7674 return NULL; 7675 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 Var_expression* index_ve = this->index_var_->var_expression(); 7681 if (index_ve == NULL) 7682 return NULL; 7683 Named_object* index_no = index_ve->named_object(); 7684 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 const std::vector<Statement*>* statements = this->statements_->statements(); 7689 if (statements->size() != 1) 7690 return NULL; 7691 Expression_statement* es = statements->at(0)->expression_statement(); 7692 if (es == NULL) 7693 return NULL; 7694 Call_expression* call = es->expr()->call_expression(); 7695 if (call == NULL || !call->is_builtin() 7696 || call->builtin_call_expression()->code() 7697 != Builtin_call_expression::BUILTIN_DELETE) 7698 return NULL; 7699 if (!Expression::is_same_variable(call->args()->at(0), orig_range_expr) 7700 || !Expression::is_same_variable(call->args()->at(1), this->index_var_)) 7701 return NULL; 7702 7703 // Everything matches. Rewrite to mapclear(TYPE, MAP). 7704 Expression* e1 = Expression::make_type_descriptor(map_type, loc); 7705 Expression* e2 = this->make_range_ref(range_object, range_temp, loc); 7706 call = Runtime::make_call(gogo, Runtime::MAPCLEAR, loc, 2, e1, e2); 7707 Statement* s = Statement::make_statement(call, true); 7708 s->determine_types(gogo); 7709 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 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 if (this->value_var_ != NULL) 7729 return NULL; 7730 if (this->index_var_ == NULL) 7731 return NULL; 7732 7733 // Match the body, a single assignment statement a[i] = zero. 7734 const std::vector<Statement*>* statements = this->statements_->statements(); 7735 if (statements->size() != 1) 7736 return NULL; 7737 Assignment_statement* as = statements->at(0)->assignment_statement(); 7738 if (as == NULL || !as->rhs()->is_zero_value()) 7739 return NULL; 7740 if (as->lhs()->type()->interface_type() != NULL 7741 && as->rhs()->type()->interface_type() == NULL 7742 && !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 Array_index_expression* aie = as->lhs()->array_index_expression(); 7747 if (aie == NULL || aie->end() != NULL 7748 || !Expression::is_same_variable(orig_range_expr, aie->array()) 7749 || !Expression::is_same_variable(this->index_var_, aie->start())) 7750 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 Type* elem_type = array_type->array_type()->element_type(); 7762 int64_t elme_sz; 7763 bool ok = elem_type->backend_type_size(gogo, &elme_sz); 7764 if (!ok) 7765 return NULL; 7766 7767 Block* b = new Block(temp_block, loc); 7768 7769 Expression* ref; 7770 if (range_object == NULL && range_temp == NULL) 7771 // is_same_variable implies no side effect, so it is ok to copy. 7772 ref = orig_range_expr->copy(); 7773 else 7774 ref = this->make_range_ref(range_object, range_temp, loc); 7775 Expression* len = this->call_builtin(gogo, "len", ref, loc); 7776 Temporary_statement* tslen = Statement::make_temporary(NULL, len, loc); 7777 tslen->determine_types(gogo); 7778 temp_block->add_statement(tslen); 7779 7780 Expression* zero = Expression::make_integer_ul(0, this->index_var_->type(), loc); 7781 ref = ref->copy(); 7782 Expression* elem = Expression::make_array_index(ref, zero, NULL, NULL, loc); 7783 elem->array_index_expression()->set_needs_bounds_check(false); 7784 Expression* e1 = Expression::make_unary(OPERATOR_AND, elem, loc); 7785 Temporary_statement* ts1 = Statement::make_temporary(NULL, e1, loc); 7786 ts1->determine_types(gogo); 7787 b->add_statement(ts1); 7788 7789 len = Expression::make_temporary_reference(tslen, loc); 7790 Expression* sz = Expression::make_integer_int64(elme_sz, len->type(), loc); 7791 Expression* e2 = Expression::make_binary(OPERATOR_MULT, len, sz, loc); 7792 Temporary_statement* ts2 = Statement::make_temporary(NULL, e2, loc); 7793 ts2->determine_types(gogo); 7794 b->add_statement(ts2); 7795 7796 Expression* ptr_arg = Expression::make_temporary_reference(ts1, loc); 7797 Expression* sz_arg = Expression::make_temporary_reference(ts2, loc); 7798 Expression* call; 7799 if (elem_type->has_pointer()) 7800 call = Runtime::make_call(gogo, Runtime::MEMCLRHASPTR, loc, 2, 7801 ptr_arg, sz_arg); 7802 else 7803 { 7804 Type* int32_type = Type::lookup_integer_type("int32"); 7805 Expression* zero32 = Expression::make_integer_ul(0, int32_type, loc); 7806 call = Runtime::make_call(gogo, Runtime::BUILTIN_MEMSET, loc, 3, ptr_arg, 7807 zero32, sz_arg); 7808 } 7809 Statement* cs3 = Statement::make_statement(call, true); 7810 cs3->determine_types(gogo); 7811 b->add_statement(cs3); 7812 7813 len = Expression::make_temporary_reference(tslen, loc); 7814 Expression* one = Expression::make_integer_ul(1, len->type(), loc); 7815 Expression* rhs = Expression::make_binary(OPERATOR_MINUS, len, one, loc); 7816 Expression* lhs = this->index_var_->copy(); 7817 Statement* as4 = Statement::make_assignment(lhs, rhs, loc); 7818 as4->determine_types(gogo); 7819 b->add_statement(as4); 7820 7821 len = Expression::make_temporary_reference(tslen, loc); 7822 zero = zero->copy(); 7823 Expression* cond = Expression::make_binary(OPERATOR_NOTEQ, len, zero, loc); 7824 Statement* ret = Statement::make_if_statement(cond, b, NULL, loc); 7825 ret->determine_types(gogo); 7826 return ret; 7827 } 7828 7829 // Return the break LABEL_EXPR. 7830 7831 Unnamed_label* 7832 For_range_statement::break_label() 7833 { 7834 if (this->break_label_ == NULL) 7835 this->break_label_ = new Unnamed_label(this->location()); 7836 return this->break_label_; 7837 } 7838 7839 // Return the continue LABEL_EXPR. 7840 7841 Unnamed_label* 7842 For_range_statement::continue_label() 7843 { 7844 if (this->continue_label_ == NULL) 7845 this->continue_label_ = new Unnamed_label(this->location()); 7846 return this->continue_label_; 7847 } 7848 7849 // Dump the AST representation for a for range statement. 7850 7851 void 7852 For_range_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const 7853 { 7854 7855 ast_dump_context->print_indent(); 7856 ast_dump_context->ostream() << "for "; 7857 ast_dump_context->dump_expression(this->index_var_); 7858 if (this->value_var_ != NULL) 7859 { 7860 ast_dump_context->ostream() << ", "; 7861 ast_dump_context->dump_expression(this->value_var_); 7862 } 7863 7864 ast_dump_context->ostream() << " = range "; 7865 ast_dump_context->dump_expression(this->range_); 7866 if (ast_dump_context->dump_subblocks()) 7867 { 7868 ast_dump_context->ostream() << " {" << std::endl; 7869 7870 ast_dump_context->indent(); 7871 7872 ast_dump_context->dump_block(this->statements_); 7873 7874 ast_dump_context->unindent(); 7875 ast_dump_context->print_indent(); 7876 ast_dump_context->ostream() << "}"; 7877 } 7878 ast_dump_context->ostream() << dsuffix(location()) << std::endl; 7879 } 7880 7881 // Make a for statement with a range clause. 7882 7883 For_range_statement* 7884 Statement::make_for_range_statement(Expression* index_var, 7885 Expression* value_var, 7886 Expression* range, 7887 Location location) 7888 { 7889 return new For_range_statement(index_var, value_var, range, location); 7890 }